Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarek Safar <marek.safar@gmail.com>2018-09-19 15:19:22 +0300
committerGitHub <noreply@github.com>2018-09-19 15:19:22 +0300
commitefd29b5cf854679349066e22ef9038b8cfe76d94 (patch)
tree2de750c1ac8a487d7f6d149592a6362ade6a5a77 /src
parentf9124d69e41d42196510dd7234b2d53fed48ad4c (diff)
parent49f9ed0e66fc2d4cd682821396c6af5e80182048 (diff)
Merge pull request #25 from ntherning/bump-corert
Bump to latest upstream
Diffstat (limited to 'src')
-rw-r--r--src/BuildIntegration/Microsoft.NETCore.Native.Publish.targets10
-rw-r--r--src/BuildIntegration/Microsoft.NETCore.Native.Unix.props11
-rw-r--r--src/BuildIntegration/Microsoft.NETCore.Native.Windows.props9
-rw-r--r--src/BuildIntegration/Microsoft.NETCore.Native.targets73
-rw-r--r--src/Common/src/Internal/Metadata/NativeFormat/Generator/SchemaDef.cs2
-rw-r--r--src/Common/src/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs2
-rw-r--r--src/Common/src/Internal/NativeFormat/NativeFormatReader.cs2
-rw-r--r--src/Common/src/Internal/Runtime/CompilerHelpers/StartupCodeHelpers.cs7
-rw-r--r--src/Common/src/Internal/Runtime/EEType.cs319
-rw-r--r--src/Common/src/Internal/Runtime/ModuleHeaders.cs14
-rw-r--r--src/Common/src/Interop/Unix/System.Private.CoreLib.Native/Interop.GetEnviron.cs (renamed from src/Common/src/Interop/Unix/System.Private.CoreLib.Native/Interop.CreateGuid.cs)5
-rw-r--r--src/Common/src/Interop/Windows/Interop.Libraries.cs4
-rw-r--r--src/Common/src/Interop/Windows/mincore/Interop.MemAllocFree.cs2
-rw-r--r--src/Common/src/Interop/Windows/mincore/Interop.MemReAlloc.cs2
-rw-r--r--src/Common/src/Interop/Windows/mincore/Interop.Threading.cs33
-rw-r--r--src/Common/src/Interop/Windows/ole32/Interop.CoGetApartmentType.cs36
-rw-r--r--src/Common/src/Interop/Windows/ole32/Interop.CoInitializeEx.cs19
-rw-r--r--src/Common/src/Interop/Windows/ole32/Interop.CoUninitialize.cs16
-rw-r--r--src/Common/src/System/Collections/Concurrent/ConcurrentUnifier.cs2
-rw-r--r--src/Common/src/System/Collections/Concurrent/ConcurrentUnifierW.cs2
-rw-r--r--src/Common/src/System/Collections/Concurrent/ConcurrentUnifierWKeyed.cs2
-rw-r--r--src/Common/src/System/Collections/Generic/LowLevelStack.cs161
-rw-r--r--src/Common/src/System/CommonRuntimeTypes.cs30
-rw-r--r--src/Common/src/System/Numerics/Hashing/HashHelpers.cs2
-rw-r--r--src/Common/src/System/SR.cs25
-rw-r--r--src/Common/src/TypeSystem/Canon/CanonTypes.cs4
-rw-r--r--src/Common/src/TypeSystem/CodeGen/TypeDesc.CodeGen.cs30
-rw-r--r--src/Common/src/TypeSystem/Common/ArrayType.cs2
-rw-r--r--src/Common/src/TypeSystem/Common/ByRefType.cs2
-rw-r--r--src/Common/src/TypeSystem/Common/DefType.FieldLayout.cs49
-rw-r--r--src/Common/src/TypeSystem/Common/FieldDesc.FieldLayout.cs7
-rw-r--r--src/Common/src/TypeSystem/Common/FieldLayoutAlgorithm.cs3
-rw-r--r--src/Common/src/TypeSystem/Common/FunctionPointerType.cs2
-rw-r--r--src/Common/src/TypeSystem/Common/GenericParameterDesc.cs2
-rw-r--r--src/Common/src/TypeSystem/Common/InstantiatedType.cs10
-rw-r--r--src/Common/src/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs21
-rw-r--r--src/Common/src/TypeSystem/Common/MethodDesc.cs25
-rw-r--r--src/Common/src/TypeSystem/Common/PointerType.cs2
-rw-r--r--src/Common/src/TypeSystem/Common/TargetDetails.cs39
-rw-r--r--src/Common/src/TypeSystem/Common/TypeDesc.cs2
-rw-r--r--src/Common/src/TypeSystem/Common/TypeFlags.cs5
-rw-r--r--src/Common/src/TypeSystem/Common/TypeSystemContext.cs7
-rw-r--r--src/Common/src/TypeSystem/Common/UniversalCanonLayoutAlgorithm.cs3
-rw-r--r--src/Common/src/TypeSystem/Common/Utilities/GCPointerMap.Algorithm.cs6
-rw-r--r--src/Common/src/TypeSystem/Common/Utilities/GCPointerMap.cs7
-rw-r--r--src/Common/src/TypeSystem/Ecma/EcmaModule.cs13
-rw-r--r--src/Common/src/TypeSystem/Ecma/EcmaType.cs24
-rw-r--r--src/Common/src/TypeSystem/IL/DelegateInfo.cs56
-rw-r--r--src/Common/src/TypeSystem/IL/ILImporter.cs1
-rw-r--r--src/Common/src/TypeSystem/IL/ILProvider.cs35
-rw-r--r--src/Common/src/TypeSystem/IL/Stubs/CalliIntrinsic.cs8
-rw-r--r--src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Mangling.cs28
-rw-r--r--src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Sorting.cs20
-rw-r--r--src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.cs96
-rw-r--r--src/Common/src/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.Mangling.cs3
-rw-r--r--src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.Sorting.cs11
-rw-r--r--src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.cs259
-rw-r--r--src/Common/src/TypeSystem/IL/Stubs/DynamicInvokeMethodThunk.Sorting.cs24
-rw-r--r--src/Common/src/TypeSystem/IL/Stubs/DynamicInvokeMethodThunk.cs350
-rw-r--r--src/Common/src/TypeSystem/IL/Stubs/ILEmitter.cs2
-rw-r--r--src/Common/src/TypeSystem/IL/Stubs/PInvokeILEmitter.cs75
-rw-r--r--src/Common/src/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs8
-rw-r--r--src/Common/src/TypeSystem/IL/Stubs/PInvokeTargetNativeMethod.cs9
-rw-r--r--src/Common/src/TypeSystem/IL/Stubs/StructMarshallingThunk.cs48
-rw-r--r--src/Common/src/TypeSystem/IL/TypeSystemContext.DelegateInfo.cs18
-rw-r--r--src/Common/src/TypeSystem/IL/TypeSystemContext.DynamicInvoke.cs31
-rw-r--r--src/Common/src/TypeSystem/IL/TypeSystemContext.GeneratedAssembly.Sorting.cs23
-rw-r--r--src/Common/src/TypeSystem/IL/TypeSystemContext.GeneratedAssembly.cs252
-rw-r--r--src/Common/src/TypeSystem/IL/TypeSystemContext.ValueTypeMethods.cs3
-rw-r--r--src/Common/src/TypeSystem/Interop/IL/InlineArrayType.cs2
-rw-r--r--src/Common/src/TypeSystem/Interop/IL/MarshalHelpers.cs7
-rw-r--r--src/Common/src/TypeSystem/Interop/IL/Marshaller.cs159
-rw-r--r--src/Common/src/TypeSystem/Interop/IL/NativeStructType.cs3
-rw-r--r--src/Common/src/TypeSystem/Interop/IL/PInvokeDelegateWrapper.cs2
-rw-r--r--src/Common/src/TypeSystem/Interop/InteropStateManager.cs48
-rw-r--r--src/Common/src/TypeSystem/Interop/MethodDesc.Interop.cs23
-rw-r--r--src/Common/src/TypeSystem/Mangling/IPrefixMangledSignature.cs23
-rw-r--r--src/Common/src/TypeSystem/NativeFormat/NativeFormatMetadataUnit.cs2
-rw-r--r--src/Common/src/TypeSystem/NativeFormat/NativeFormatType.cs4
-rw-r--r--src/Common/src/TypeSystem/RuntimeDetermined/RuntimeDeterminedType.cs2
-rw-r--r--src/Common/src/TypeSystem/TypesDebugInfoWriter/DebugInfoWriter.cs5
-rw-r--r--src/Common/src/TypeSystem/TypesDebugInfoWriter/TypesDebugInfoWriter.cs14
-rw-r--r--src/Common/test-runtime/XUnit.Runtime.depproj91
-rw-r--r--src/Framework/Framework-native.depproj4
-rw-r--r--src/Framework/Framework-uapaot.depproj7
-rw-r--r--src/Framework/Framework.depproj24
-rw-r--r--src/ILCompiler.Build.Tasks/src/ComputeManagedAssemblies.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/AnalysisBasedMetadataManager.cs5
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/Compilation.cs23
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/CompilationModuleGroup.cs51
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedType.Sorting.cs22
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedType.cs198
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/CompilerMetadataFieldLayoutAlgorithm.cs12
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.BoxedTypes.cs39
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.Mangling.cs19
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.cs11
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/CoreRTNameMangler.cs39
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayMapNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfEmbeddedDataNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfFrozenObjectsNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/AssemblyStubNode.cs21
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/BlobNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/BlockReflectionTypeMapNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalDefinitionEETypeNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs14
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ClassConstructorContextMap.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ClonedConstructedEETypeNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CompilerComparer.cs6
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs33
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DefaultConstructorMapNode.cs52
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DelegateMarshallingStubMapNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DynamicInvokeTemplateDataNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs99
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs6
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedDataContainerNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternMethodSymbolNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternSymbolNode.cs6
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternalReferencesTableNode.cs5
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FatFunctionPointerNode.cs11
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FrozenArrayNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FrozenStringNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticDescNode.cs20
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticEETypeNode.cs6
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsNode.cs17
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsPreInitDataNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericCompositionNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDefinitionEETypeNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDictionaryNode.cs24
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesHashtableNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ILScanNodeFactory.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IMethodCodeNode.cs1
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/INodeWithCodeInfo.cs21
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ISortableNode.cs23
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ISymbolNode.cs16
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ISymbolNodeWithDebugInfo.cs38
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ImportedEETypeSymbolNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IndirectionExtensions.cs36
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IndirectionNode.cs6
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs57
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellSectionNode.cs132
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs97
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/JumpStubNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/LoopHijackFlagNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MetadataNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodAssociatedDataNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodCodeNode.cs15
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ModulesSectionNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MrtImports.cs18
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MrtProcessedExportAddressTableNode.cs36
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MrtProcessedImportAddressTableNode.cs9
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutSignatureNode.cs6
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs59
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NecessaryCanonicalEETypeNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs52
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NonExternMethodSymbolNode.cs38
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NonGCStaticsNode.cs15
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectDataBuilder.cs15
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectNode.cs10
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectNodeSection.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectWriter.cs93
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs28
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/PInvokeModuleFixupNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs8
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHeaderNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs12
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceDataNode.cs7
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceIndexNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeDecodableJumpStub.cs11
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeDeterminedMethodNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs16
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeImportMethodNode.cs24
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs16
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RyuJitNodeFactory.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ScannedMethodNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SealedVTableNode.cs170
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ShadowConcreteMethodNode.cs11
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ShadowConcreteUnboxingThunkNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SortableDependencyNode.cs20
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StackTraceEmbeddedMetadataNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StackTraceMethodMappingNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StaticsInfoHashtableNode.cs6
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StringAllocatorMethodNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StructMarshallingStubMapNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMDebug.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMInitialInterfaceDispatchStubNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs11
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64Emitter.cs14
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs17
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsIndexNode.cs15
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsNode.cs6
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsOffsetNode.cs11
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeManagerIndirectionNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataMapNode.cs7
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataNode.cs17
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeThreadStaticIndexNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UnboxingStubNode.cs15
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcDictionaryLayoutNode.cs49
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs64
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcThreadStaticsNode.cs13
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugILImagesSection.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugManagedNativeDictionaryInfoSection.cs3
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMergedAssemblyRecordsSection.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMethodInfoSection.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMethodMapSection.cs6
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugNeedTypeIndicesStoreNode.cs3
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugPseudoAssemblySection.cs3
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugTypeRecordsSection.cs13
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugTypeSignatureMapSection.cs6
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DynamicInvokeThunkGenerationPolicy.cs48
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/EmptyMetadataManager.cs19
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/FrameworkStringResourceBlockingPolicy.cs91
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/GeneratingMetadataManager.cs48
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/ILScannerBuilder.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/ILStreamReader.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/IRootingServiceProvider.cs1
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/LibraryInitializers.cs49
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/MainMethodRootProvider.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/ManifestResourceBlockingPolicy.cs21
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs142
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/MethodExtensions.cs34
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/MultiFileCompilationModuleGroup.cs8
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/NativeLibraryInitializerRootProvider.cs6
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/NoManifestResourceBlockingPolicy.cs19
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/NoMetadataBlockingPolicy.cs51
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/PrecomputedMetadataManager.cs97
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/RuntimeConfigurationRootProvider.cs58
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/SimdHelper.cs16
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/SingleFileCompilationModuleGroup.cs10
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/SingleMethodCompilationModuleGroup.cs6
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/TypeExtensions.cs27
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/UsageBasedMetadataManager.cs31
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/UserDefinedTypeDescriptor.cs135
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/UtcNameMangler.cs84
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/VirtualMethodCallHelper.cs87
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/WindowsNodeMangler.cs5
-rw-r--r--src/ILCompiler.Compiler/src/IL/ILImporter.Scanner.cs20
-rw-r--r--src/ILCompiler.Compiler/src/IL/Stubs/PInvokeILProvider.cs5
-rw-r--r--src/ILCompiler.Compiler/src/IL/Stubs/StartupCode/AppContextInitializerMethod.Sorting.cs22
-rw-r--r--src/ILCompiler.Compiler/src/IL/Stubs/StartupCode/AppContextInitializerMethod.cs83
-rw-r--r--src/ILCompiler.Compiler/src/IL/Stubs/StartupCode/NativeLibraryStartupMethod.cs4
-rw-r--r--src/ILCompiler.Compiler/src/IL/Stubs/StartupCode/StartupCodeMainMethod.cs4
-rw-r--r--src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj22
-rw-r--r--src/ILCompiler.Compiler/tests/DependencyGraphTests.cs2
-rw-r--r--src/ILCompiler.Compiler/tests/DevirtualizationTests.cs2
-rw-r--r--src/ILCompiler.Compiler/tests/ILCompiler.Compiler.Tests.Assets/ILCompiler.Compiler.Tests.Assets.csproj2
-rw-r--r--src/ILCompiler.Compiler/tests/ILCompiler.Compiler.Tests.csproj9
-rw-r--r--src/ILCompiler.CppCodeGen/src/Compiler/CppCodegenCompilationBuilder.cs2
-rw-r--r--src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppCodegenNodeFactory.cs3
-rw-r--r--src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppMethodCodeNode.cs4
-rw-r--r--src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppUnboxingStubNode.cs68
-rw-r--r--src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs150
-rw-r--r--src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs10
-rw-r--r--src/ILCompiler.CppCodeGen/src/ILCompiler.CppCodeGen.csproj1
-rw-r--r--src/ILCompiler.DependencyAnalysisFramework/tests/DependencyAnalysisFrameworkTests.cs16
-rw-r--r--src/ILCompiler.DependencyAnalysisFramework/tests/ILCompiler.DependencyAnalysisFramework.Tests.csproj9
-rw-r--r--src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.CustomAttribute.cs8
-rw-r--r--src/ILCompiler.MetadataTransform/tests/ExplicitScopeTests.cs4
-rw-r--r--src/ILCompiler.MetadataTransform/tests/ILCompiler.MetadataTransform.Tests.csproj9
-rw-r--r--src/ILCompiler.MetadataTransform/tests/ILMetadataAssembly/ILMetadataAssembly.ilproj2
-rw-r--r--src/ILCompiler.MetadataTransform/tests/PrimaryMetadataAssembly/PrimaryMetadataAssembly.csproj2
-rw-r--r--src/ILCompiler.MetadataTransform/tests/SampleMetadataAssembly/SampleMetadataAssembly.csproj2
-rw-r--r--src/ILCompiler.MetadataTransform/tests/SampleWinRTMetadataAssembly/SampleWinRTMetadataAssembly.csproj2
-rw-r--r--src/ILCompiler.MetadataTransform/tests/SimpleTests.cs2
-rw-r--r--src/ILCompiler.MetadataTransform/tests/WindowsWinRTMetadataAssembly/WindowsWinRTMetadataAssembly.csproj2
-rw-r--r--src/ILCompiler.MetadataWriter/src/Internal/Metadata/NativeFormat/Writer/NativeFormatWriterGen.cs3
-rw-r--r--src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj36
-rw-r--r--src/ILCompiler.TypeSystem/src/Utilities/UniqueTypeNameFormatter.cs2
-rw-r--r--src/ILCompiler.TypeSystem/tests/CoreTestAssembly/CoreTestAssembly.csproj2
-rw-r--r--src/ILCompiler.TypeSystem/tests/GCPointerMapTests.cs19
-rw-r--r--src/ILCompiler.TypeSystem/tests/GenericTypeAndMethodTests.cs40
-rw-r--r--src/ILCompiler.TypeSystem/tests/ILTestAssembly/ILTestAssembly.ilproj2
-rw-r--r--src/ILCompiler.TypeSystem/tests/TestMetadataFieldLayoutAlgorithm.cs6
-rw-r--r--src/ILCompiler.TypeSystem/tests/TestTypeSystemContext.cs3
-rw-r--r--src/ILCompiler.TypeSystem/tests/TypeSystem.Tests.csproj10
-rw-r--r--src/ILCompiler.TypeSystem/tests/UniversalGenericFieldLayoutTests.cs8
-rw-r--r--src/ILCompiler.WebAssembly/src/CodeGen/DebugMetadata.cs23
-rw-r--r--src/ILCompiler.WebAssembly/src/CodeGen/EvaluationStack.cs44
-rw-r--r--src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs1018
-rw-r--r--src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter_Statics.cs16
-rw-r--r--src/ILCompiler.WebAssembly/src/CodeGen/LLVMPInvokes.cs78
-rw-r--r--src/ILCompiler.WebAssembly/src/CodeGen/WebAssemblyObjectWriter.cs65
-rw-r--r--src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyCodegenNodeFactory.cs2
-rw-r--r--src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyMethodCodeNode.cs4
-rw-r--r--src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyVTableSlotNode.cs17
-rw-r--r--src/ILCompiler.WebAssembly/src/Compiler/WebAssemblyCodegenCompilation.cs8
-rw-r--r--src/ILCompiler.WebAssembly/src/Compiler/WebAssemblyCodegenCompilationBuilder.cs7
-rw-r--r--src/ILCompiler.WebAssembly/src/ILCompiler.WebAssembly.csproj8
-rw-r--r--src/ILCompiler.WebAssembly/src/libLLVMdep.depproj2
-rw-r--r--src/ILCompiler/ObjectWriter/ObjectWriter.depproj7
-rw-r--r--src/ILCompiler/RyuJIT/RyuJIT.depproj4
-rw-r--r--src/ILCompiler/netcoreapp/ilc.csproj2
-rw-r--r--src/ILCompiler/repro/repro.csproj8
-rw-r--r--src/ILCompiler/repro/repro.ilproj2
-rw-r--r--src/ILCompiler/reproNative/reproNative.vcxproj4
-rw-r--r--src/ILCompiler/src/ILCompiler.csproj2
-rw-r--r--src/ILCompiler/src/Program.cs125
-rw-r--r--src/ILVerification/src/ILVerification.csproj18
-rw-r--r--src/ILVerification/src/ILVerifyTypeSystemContext.cs36
-rw-r--r--src/ILVerification/src/IResolver.cs10
-rw-r--r--src/ILVerification/src/Verifier.cs9
-rw-r--r--src/ILVerification/tests/ILMethodTester.cs2
-rw-r--r--src/ILVerification/tests/ILTests/AccessTests.ilproj3
-rw-r--r--src/ILVerification/tests/ILTests/AccessTestsExtern.ilproj3
-rw-r--r--src/ILVerification/tests/ILTests/AccessTestsFriend.ilproj3
-rw-r--r--src/ILVerification/tests/ILTests/ArrayTests.ilproj3
-rw-r--r--src/ILVerification/tests/ILTests/BasicArithmeticTests.ilproj3
-rw-r--r--src/ILVerification/tests/ILTests/BranchingTests.ilproj3
-rw-r--r--src/ILVerification/tests/ILTests/CallTests.ilproj3
-rw-r--r--src/ILVerification/tests/ILTests/CastingTests.ilproj3
-rw-r--r--src/ILVerification/tests/ILTests/ComparisonTests.ilproj3
-rw-r--r--src/ILVerification/tests/ILTests/DelegateTests.ilproj3
-rw-r--r--src/ILVerification/tests/ILTests/ExceptionRegionTests.ilproj3
-rw-r--r--src/ILVerification/tests/ILTests/FieldTests.ilproj3
-rw-r--r--src/ILVerification/tests/ILTests/FtnTests.ilproj3
-rw-r--r--src/ILVerification/tests/ILTests/ILTests.targets17
-rw-r--r--src/ILVerification/tests/ILTests/LoadStoreIndirectTests.ilproj3
-rw-r--r--src/ILVerification/tests/ILTests/NewobjTests.ilproj3
-rw-r--r--src/ILVerification/tests/ILTests/PrefixTests.ilproj3
-rw-r--r--src/ILVerification/tests/ILTests/ReturnTests.ilproj3
-rw-r--r--src/ILVerification/tests/ILTests/ShiftTests.ilproj3
-rw-r--r--src/ILVerification/tests/ILTests/ThisStateTests.ilproj3
-rw-r--r--src/ILVerification/tests/ILTests/ValueTypeTests.ilproj3
-rw-r--r--src/ILVerification/tests/ILVerification.Tests.csproj18
-rw-r--r--src/ILVerification/tests/TestDataLoader.cs26
-rw-r--r--src/ILVerify/README.md14
-rw-r--r--src/ILVerify/netcoreapp/ILVerify.csproj2
-rw-r--r--src/ILVerify/src/ILVerify.csproj8
-rw-r--r--src/ILVerify/src/Program.cs112
-rw-r--r--src/JitInterface/src/CorInfoBase.cs61
-rw-r--r--src/JitInterface/src/CorInfoImpl.Intrinsics.cs6
-rw-r--r--src/JitInterface/src/CorInfoImpl.cs107
-rw-r--r--src/JitInterface/src/CorInfoTypes.cs8
-rw-r--r--src/JitInterface/src/ThunkGenerator/ThunkInput.txt1
-rw-r--r--src/JitInterface/src/ThunkGenerator/cordebuginfo.h198
-rw-r--r--src/JitInterface/src/ThunkGenerator/corinfo.h50
-rw-r--r--src/JitInterface/src/ThunkGenerator/corjitflags.h2
-rw-r--r--src/JitInterface/src/ThunkGenerator/corjithost.h26
-rw-r--r--src/Native/Bootstrap/main.cpp16
-rw-r--r--src/Native/CMakeLists.txt32
-rw-r--r--src/Native/ObjWriter/.nuget/Microsoft.DotNet.ObjectWriter.nuspec20
-rw-r--r--src/Native/ObjWriter/.nuget/runtime.json19
-rw-r--r--src/Native/ObjWriter/.nuget/toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter.nuspec20
-rw-r--r--src/Native/ObjWriter/.nuget/toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter.nuspec20
-rw-r--r--src/Native/ObjWriter/.nuget/toolchain.win7-x64.Microsoft.DotNet.ObjectWriter.nuspec20
-rw-r--r--src/Native/ObjWriter/CMakeLists.txt21
-rw-r--r--src/Native/ObjWriter/cordebuginfo.h194
-rw-r--r--src/Native/ObjWriter/cvconst.h18
-rw-r--r--src/Native/ObjWriter/debugInfo/codeView/codeViewTypeBuilder.cpp (renamed from src/Native/ObjWriter/typeBuilder.cpp)105
-rw-r--r--src/Native/ObjWriter/debugInfo/codeView/codeViewTypeBuilder.h73
-rw-r--r--src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.cpp284
-rw-r--r--src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.h59
-rw-r--r--src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.cpp1066
-rw-r--r--src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.h106
-rw-r--r--src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.cpp780
-rw-r--r--src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.h366
-rw-r--r--src/Native/ObjWriter/debugInfo/typeBuilder.h158
-rw-r--r--src/Native/ObjWriter/jitDebugInfo.h12
-rw-r--r--src/Native/ObjWriter/llvm.patch57
-rw-r--r--src/Native/ObjWriter/llvmCap/CMakeLists.txt20
-rw-r--r--src/Native/ObjWriter/objwriter.cpp114
-rw-r--r--src/Native/ObjWriter/objwriter.h48
-rw-r--r--src/Native/ObjWriter/typeBuilder.h145
-rw-r--r--src/Native/Runtime/CMakeLists.txt10
-rw-r--r--src/Native/Runtime/Full/CMakeLists.txt8
-rw-r--r--src/Native/Runtime/Portable/CMakeLists.txt3
-rw-r--r--src/Native/Runtime/RHCodeMan.cpp73
-rw-r--r--src/Native/Runtime/RhConfig.cpp119
-rw-r--r--src/Native/Runtime/RhConfig.h16
-rw-r--r--src/Native/Runtime/RuntimeInstance.cpp12
-rw-r--r--src/Native/Runtime/RuntimeInstance.h18
-rw-r--r--src/Native/Runtime/amd64/ExceptionHandling.S1
-rw-r--r--src/Native/Runtime/amd64/ExceptionHandling.asm1
-rw-r--r--src/Native/Runtime/arm/AllocFast.S2
-rw-r--r--src/Native/Runtime/arm/ExceptionHandling.S3
-rw-r--r--src/Native/Runtime/arm/ExceptionHandling.asm1
-rw-r--r--src/Native/Runtime/arm64/CallingConventionConverterHelpers.asm2
-rw-r--r--src/Native/Runtime/arm64/ExceptionHandling.asm18
-rw-r--r--src/Native/Runtime/arm64/GcProbe.asm239
-rw-r--r--src/Native/Runtime/arm64/InteropThunksHelpers.asm2
-rw-r--r--src/Native/Runtime/arm64/MiscStubs.asm2
-rw-r--r--src/Native/Runtime/arm64/StubDispatch.asm8
-rw-r--r--src/Native/Runtime/arm64/ThunkPoolThunks.asm5
-rw-r--r--src/Native/Runtime/arm64/UniversalTransition.asm2
-rw-r--r--src/Native/Runtime/i386/ExceptionHandling.asm1
-rw-r--r--src/Native/Runtime/i386/ThunkPoolThunks.asm8
-rw-r--r--src/Native/Runtime/inc/eetype.h16
-rw-r--r--src/Native/Runtime/inc/eetype.inl79
-rw-r--r--src/Native/Runtime/thread.cpp46
-rw-r--r--src/Native/Runtime/thread.h4
-rw-r--r--src/Native/Runtime/unix/PalRedhawkInline.h4
-rw-r--r--src/Native/Runtime/unix/PalRedhawkUnix.cpp16
-rw-r--r--src/Native/Runtime/unix/UnixContext.cpp4
-rw-r--r--src/Native/Runtime/unix/UnixNativeCodeManager.cpp10
-rw-r--r--src/Native/Runtime/unix/UnixNativeCodeManager.h7
-rw-r--r--src/Native/Runtime/unix/UnwindHelpers.cpp162
-rw-r--r--src/Native/Runtime/unix/unixasmmacrosamd64.inc6
-rw-r--r--src/Native/Runtime/windows/CoffNativeCodeManager.cpp109
-rw-r--r--src/Native/Runtime/windows/CoffNativeCodeManager.h5
-rw-r--r--src/Native/Runtime/windows/PalRedhawkCommon.cpp2
-rw-r--r--src/Native/Runtime/windows/PalRedhawkMinWin.cpp59
-rw-r--r--src/Native/System.Private.CoreLib.Native/CMakeLists.txt1
-rw-r--r--src/Native/System.Private.CoreLib.Native/config.h.in5
-rw-r--r--src/Native/System.Private.CoreLib.Native/configure.cmake17
-rw-r--r--src/Native/System.Private.CoreLib.Native/pal_dynamicload.cpp28
-rw-r--r--src/Native/System.Private.CoreLib.Native/pal_environment.cpp17
-rw-r--r--src/Native/System.Private.CoreLib.Native/pal_guid.cpp35
-rw-r--r--src/Native/System.Private.CoreLib.Native/pal_time.cpp2
-rw-r--r--src/Native/System.Private.TypeLoader.Native/CMakeLists.txt45
-rw-r--r--src/Native/System.Private.TypeLoader.Native/amd64/ConstrainedCallSupportHelpers.S12
-rw-r--r--src/Native/System.Private.TypeLoader.Native/amd64/ConstrainedCallSupportHelpers.asm85
-rw-r--r--src/Native/System.Private.TypeLoader.Native/amd64/MethodEntrypointStubs.S12
-rw-r--r--src/Native/System.Private.TypeLoader.Native/amd64/MethodEntrypointStubs.asm67
-rw-r--r--src/Native/System.Private.TypeLoader.Native/amd64/VTableResolver.S17
-rw-r--r--src/Native/System.Private.TypeLoader.Native/amd64/VTableResolver.asm221
-rw-r--r--src/Native/System.Private.TypeLoader.Native/arm/ConstrainedCallSupportHelpers.S13
-rw-r--r--src/Native/System.Private.TypeLoader.Native/arm/ConstrainedCallSupportHelpers.asm78
-rw-r--r--src/Native/System.Private.TypeLoader.Native/arm/MethodEntrypointStubs.S13
-rw-r--r--src/Native/System.Private.TypeLoader.Native/arm/MethodEntrypointStubs.asm5
-rw-r--r--src/Native/System.Private.TypeLoader.Native/arm/VTableResolver.S18
-rw-r--r--src/Native/System.Private.TypeLoader.Native/arm/VTableResolver.asm163
-rw-r--r--src/Native/System.Private.TypeLoader.Native/arm64/ConstrainedCallSupportHelpers.asm67
-rw-r--r--src/Native/System.Private.TypeLoader.Native/arm64/MethodEntrypointStubs.asm5
-rw-r--r--src/Native/System.Private.TypeLoader.Native/arm64/VTableResolver.asm155
-rw-r--r--src/Native/System.Private.TypeLoader.Native/i386/ConstrainedCallSupportHelpers.asm100
-rw-r--r--src/Native/System.Private.TypeLoader.Native/i386/MethodEntrypointStubs.asm5
-rw-r--r--src/Native/System.Private.TypeLoader.Native/i386/VTableResolver.asm246
-rw-r--r--src/Native/gc/gc.cpp10
-rw-r--r--src/Native/gc/gcrecord.h6
-rw-r--r--src/Native/gc/handletable.cpp2
-rw-r--r--src/Native/gc/unix/gcenv.unix.cpp8
-rwxr-xr-xsrc/Native/gen-buildsys-clang.sh8
-rw-r--r--src/Native/gen-buildsys-win.bat2
-rw-r--r--src/Native/jitinterface/CMakeLists.txt19
-rw-r--r--src/Native/jitinterface/CodeHeap.cpp10
-rw-r--r--src/Native/jitinterface/JITCodeManager.cpp18
-rw-r--r--src/Native/jitinterface/JITCodeManager.h14
-rw-r--r--src/Native/jitinterface/dllexport.h37
-rw-r--r--src/Native/jitinterface/jithost.cpp31
-rw-r--r--src/Native/jitinterface/jitinterface.cpp28
-rw-r--r--src/Native/jitinterface/jitinterface.h10
-rw-r--r--src/Native/jitinterface/jitwrapper.cpp10
-rw-r--r--src/Native/libunwind/include/libunwind.h2
-rw-r--r--src/Native/libunwind/include/unwind.h10
-rw-r--r--src/Native/libunwind/src/Unwind-EHABI.cpp26
-rw-r--r--src/Native/libunwind/src/UnwindCursor.hpp6
-rw-r--r--src/Native/libunwind/src/config.h5
-rw-r--r--src/Native/libunwind/src/libunwind.cpp6
-rw-r--r--src/Runtime.Base/src/Internal/Runtime/CompilerServices/Unsafe.cs26
-rw-r--r--src/Runtime.Base/src/Runtime.Base.csproj1
-rw-r--r--src/Runtime.Base/src/System/Runtime/CachedInterfaceDispatch.cs2
-rw-r--r--src/Runtime.Base/src/System/Runtime/CastableObjectSupport.cs4
-rw-r--r--src/Runtime.Base/src/System/Runtime/DispatchResolve.cs12
-rw-r--r--src/Runtime.Base/src/System/Runtime/ExceptionHandling.cs6
-rw-r--r--src/Runtime.Base/src/System/Runtime/InternalCalls.cs26
-rw-r--r--src/Runtime.Base/src/System/Runtime/InteropServices/UnmanagedType.cs8
-rw-r--r--src/Runtime.Base/src/System/Runtime/RuntimeExports.cs14
-rw-r--r--src/Runtime.Base/src/System/Runtime/TypeCast.cs107
-rw-r--r--src/Runtime.Base/src/System/Runtime/__Finalizer.cs2
-rw-r--r--src/System.Private.CoreLib/shared/Internal/Padding.cs26
-rw-r--r--src/System.Private.CoreLib/shared/Internal/Runtime/CompilerServices/Unsafe.cs11
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Unix/Interop.Errors.cs4
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Casing.cs6
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Collation.cs28
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Idna.cs4
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Locale.cs14
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.GetRandomBytes.cs2
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.Read.cs2
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.Write.cs4
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegCloseKey.cs (renamed from src/Common/src/Interop/Windows/mincore/Interop.RegCloseKey.cs)7
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegCreateKeyEx.cs (renamed from src/Common/src/Interop/Windows/mincore/Interop.RegCreateKeyEx.cs)10
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegDeleteKeyEx.cs (renamed from src/Common/src/Interop/Windows/advapi32/Interop.RegSetValueEx.cs)7
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegDeleteValue.cs (renamed from src/Common/src/Interop/Windows/advapi32/Interop.RegDeleteValue.cs)6
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegEnumKeyEx.cs (renamed from src/Common/src/Interop/Windows/mincore/Interop.RegEnumKeyEx.cs)6
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegEnumValue.cs (renamed from src/Common/src/Interop/Windows/mincore/Interop.RegEnumValue.cs)6
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegFlushKey.cs (renamed from src/Common/src/Interop/Windows/mincore/Interop.RegFlushKey.cs)4
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegOpenKeyEx.cs (renamed from src/Common/src/Interop/Windows/mincore/Interop.RegOpenKeyEx.cs)6
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegQueryInfoKey.cs (renamed from src/Common/src/Interop/Windows/mincore/Interop.RegQueryInfoKey.cs)4
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegQueryValueEx.cs (renamed from src/Common/src/Interop/Windows/mincore/Interop.RegQueryValueEx.cs)18
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegSetValueEx.cs59
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegistryConstants.cs (renamed from src/Common/src/Interop/Windows/mincore/Interop.RegistryOptions.cs)14
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.BCryptGenRandom.GetRandomBytes.cs29
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.BCryptGenRandom.cs30
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.NTSTATUS.cs20
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Interop.Libraries.cs2
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CloseHandle.cs1
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Constants.cs15
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.EventWaitHandle.cs28
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FileTypes.cs1
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FindClose.cs2
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FindFirstFileEx.cs2
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FormatMessage.cs108
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFileType_SafeHandle.cs2
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFullPathNameW.cs13
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetLongPathNameW.cs11
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetTempFileNameW.cs4
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetTempPathW.cs4
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Globalization.cs30
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MUI.cs2
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MultiByteToWideChar.cs20
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Mutex.cs24
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Semaphore.cs22
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.TimeZone.cs2
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/NtDll/NtQueryInformationFile.cs46
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/Ole32/Interop.CoCreateGuid.cs (renamed from src/Common/src/Interop/Windows/mincore/Interop.CoCreateGuid.cs)6
-rw-r--r--src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysAllocStringLen.cs2
-rw-r--r--src/System.Private.CoreLib/shared/Microsoft/Win32/Registry.cs104
-rw-r--r--src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryHive.cs (renamed from src/System.Private.CoreLib/src/Microsoft/Win32/RegistryHive.cs)2
-rw-r--r--src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryOptions.cs (renamed from src/System.Private.CoreLib/src/Microsoft/Win32/RegistryOptions.cs)4
-rw-r--r--src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryValueKind.cs (renamed from src/System.Private.CoreLib/src/Microsoft/Win32/RegistryValueKind.cs)14
-rw-r--r--src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryValueOptions.cs (renamed from src/System.Private.CoreLib/src/Microsoft/Win32/RegistryValueOptions.cs)0
-rw-r--r--src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryView.cs (renamed from src/System.Private.CoreLib/src/Microsoft/Win32/RegistryView.cs)4
-rw-r--r--src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs5
-rw-r--r--src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeRegistryHandle.Windows.cs (renamed from src/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.Windows.cs)4
-rw-r--r--src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs (renamed from src/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs)13
-rw-r--r--src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.Windows.cs11
-rw-r--r--src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs21
-rw-r--r--src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems181
-rw-r--r--src/System.Private.CoreLib/shared/System/AccessViolationException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/ApplicationException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/ArgumentException.cs20
-rw-r--r--src/System.Private.CoreLib/shared/System/ArgumentNullException.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/ArgumentOutOfRangeException.cs18
-rw-r--r--src/System.Private.CoreLib/shared/System/ArithmeticException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/ArraySegment.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/ArrayTypeMismatchException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/BadImageFormatException.cs22
-rw-r--r--src/System.Private.CoreLib/shared/System/BitConverter.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Boolean.cs108
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/ArrayPool.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/ArrayPoolEventSource.cs14
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/IMemoryOwner.cs17
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/IPinnable.cs25
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/IRetainable.cs26
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/MemoryHandle.cs30
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/MemoryManager.cs75
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/OwnedMemory.cs95
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/Text/FormattingHelpers.CountDigits.cs161
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs216
-rw-r--r--src/System.Private.CoreLib/shared/System/Buffers/Utilities.cs13
-rw-r--r--src/System.Private.CoreLib/shared/System/Byte.cs60
-rw-r--r--src/System.Private.CoreLib/shared/System/Char.cs88
-rw-r--r--src/System.Private.CoreLib/shared/System/CharEnumerator.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Comparer.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/CompatibleComparer.cs61
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueue.cs (renamed from src/System.Private.CoreLib/src/System/Collections/Concurrent/LowLevelConcurrentQueue.cs)652
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueueSegment.cs332
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollection.cs70
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollectionDebugView.cs41
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/DictionaryEntry.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Generic/ArraySortHelper.cs1115
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Generic/Dictionary.cs551
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Generic/KeyNotFoundException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Generic/List.cs172
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Generic/ValueListBuilder.cs11
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/HashHelpers.SerializationInfoTable.cs29
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/HashHelpers.cs40
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/Hashtable.cs1650
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/ICollection.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/IComparer.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/IDictionary.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/IDictionaryEnumerator.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/IEnumerator.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/IEqualityComparer.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/IHashCodeProvider.cs18
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/IList.cs12
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/IStructuralComparable.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/IStructuralEquatable.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/KeyValuePairs.cs33
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/ListDictionaryInternal.cs36
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/ObjectModel/Collection.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Collections/ObjectModel/ReadOnlyCollection.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/ComponentModel/DefaultValueAttribute.cs36
-rw-r--r--src/System.Private.CoreLib/shared/System/Convert.Base64.cs217
-rw-r--r--src/System.Private.CoreLib/shared/System/Convert.cs709
-rw-r--r--src/System.Private.CoreLib/shared/System/CurrentSystemTimeZone.cs46
-rw-r--r--src/System.Private.CoreLib/shared/System/DataMisalignedException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/DateTime.cs241
-rw-r--r--src/System.Private.CoreLib/shared/System/DateTimeOffset.cs109
-rw-r--r--src/System.Private.CoreLib/shared/System/Decimal.DecCalc.cs (renamed from src/System.Private.CoreLib/src/System/Decimal.DecCalc.cs)1264
-rw-r--r--src/System.Private.CoreLib/shared/System/Decimal.cs (renamed from src/System.Private.CoreLib/src/System/Decimal.cs)493
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Debug.Unix.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/StackFrame.cs (renamed from src/System.Private.CoreLib/src/System/Diagnostics/StackFrame.cs)15
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/ActivityTracker.cs5
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventDescriptor.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventProvider.cs81
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSource.cs588
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IEventProvider.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/StubEnvironment.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/DataCollector.cs39
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventPayload.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventSourceActivity.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/FieldMetadata.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/InvokeTypeInfo.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/NameInfo.cs46
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/PropertyValue.cs106
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs58
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/Statics.cs52
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingDataCollector.cs11
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs76
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventTypes.cs20
-rw-r--r--src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingMetadataCollector.cs31
-rw-r--r--src/System.Private.CoreLib/shared/System/DivideByZeroException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/DllNotFoundException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Double.cs79
-rw-r--r--src/System.Private.CoreLib/shared/System/DuplicateWaitObjectException.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/EntryPointNotFoundException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/EventHandler.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/ExecutionEngineException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/FieldAccessException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/FormatException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/FormattableString.cs23
-rw-r--r--src/System.Private.CoreLib/shared/System/Gen2GcCallback.cs76
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/Calendar.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Unix.cs99
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Windows.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CalendarData.cs118
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CharUnicodeInfo.cs63
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/ChineseLunisolarCalendar.cs426
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Invariant.cs14
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Unix.cs (renamed from src/System.Private.CoreLib/src/System/Globalization/CompareInfo.Unix.cs)217
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Windows.cs (renamed from src/System.Private.CoreLib/src/System/Globalization/CompareInfo.Windows.cs)209
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.cs275
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CultureData.Unix.cs14
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CultureData.Windows.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CultureData.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/CultureNotFoundException.cs22
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormat.cs356
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfo.cs348
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfoScanner.cs100
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs690
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/DaylightTime.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/EastAsianLunisolarCalendar.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/GregorianCalendar.cs44
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/GregorianCalendarHelper.cs129
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/HebrewCalendar.cs16
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/HebrewNumber.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Win32.cs16
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.cs22
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/ISOWeek.cs162
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Unix.cs21
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Windows.cs24
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.cs48
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/InternalGlobalizationHelper.cs12
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Win32.cs16
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.WinRT.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.cs16
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/JapaneseLunisolarCalendar.cs193
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/JulianCalendar.cs12
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/KoreanCalendar.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/KoreanLunisolarCalendar.cs2293
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/NumberFormatInfo.cs96
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/PersianCalendar.cs16
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/RegionInfo.cs28
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/SortKey.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/StringInfo.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/TaiwanCalendar.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/TaiwanLunisolarCalendar.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/TextElementEnumerator.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/TextInfo.Unix.cs111
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/TextInfo.Windows.cs120
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/TextInfo.cs315
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/ThaiBuddhistCalendar.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/TimeSpanFormat.cs351
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/TimeSpanParse.cs326
-rw-r--r--src/System.Private.CoreLib/shared/System/Globalization/UmAlQuraCalendar.cs14
-rw-r--r--src/System.Private.CoreLib/shared/System/Guid.Unix.cs38
-rw-r--r--src/System.Private.CoreLib/shared/System/Guid.Windows.cs (renamed from src/System.Private.CoreLib/src/System/Guid.Windows.cs)10
-rw-r--r--src/System.Private.CoreLib/shared/System/Guid.cs32
-rw-r--r--src/System.Private.CoreLib/shared/System/HResults.cs3
-rw-r--r--src/System.Private.CoreLib/shared/System/IAsyncResult.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/IComparable.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/IConvertible.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/ICustomFormatter.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/IFormatProvider.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/IFormattable.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/BinaryReader.cs (renamed from src/System.Private.CoreLib/src/System/IO/BinaryReader.cs)208
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/BinaryWriter.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/DisableMediaInsertionPrompt.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/DriveNotFoundException.cs36
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/FileStream.Unix.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/FileStream.Win32.cs58
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/FileStream.WinRT.cs53
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/FileStream.Windows.cs140
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/FileStream.cs33
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/FileStreamCompletionSource.Win32.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/IOException.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/MemoryStream.cs34
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/Path.Unix.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/Path.Windows.cs101
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/Path.cs187
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/PathHelper.Windows.cs66
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/PathInternal.Windows.cs17
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/PathInternal.cs129
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/PinnedBufferMemoryStream.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/Stream.cs1322
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/StreamReader.cs16
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/StreamWriter.cs187
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/TextReader.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/TextWriter.cs176
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStream.cs58
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStreamWrapper.cs26
-rw-r--r--src/System.Private.CoreLib/shared/System/IO/Win32Marshal.cs110
-rw-r--r--src/System.Private.CoreLib/shared/System/IndexOutOfRangeException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/InsufficientExecutionStackException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/InsufficientMemoryException.cs (renamed from src/System.Private.CoreLib/src/System/InsufficientMemoryException.cs)39
-rw-r--r--src/System.Private.CoreLib/shared/System/Int16.cs54
-rw-r--r--src/System.Private.CoreLib/shared/System/Int32.cs40
-rw-r--r--src/System.Private.CoreLib/shared/System/Int64.cs42
-rw-r--r--src/System.Private.CoreLib/shared/System/IntPtr.cs13
-rw-r--r--src/System.Private.CoreLib/shared/System/InvalidCastException.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/InvalidOperationException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/InvalidProgramException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/InvalidTimeZoneException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Lazy.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Marvin.cs (renamed from src/System.Private.CoreLib/src/System/Marvin.cs)55
-rw-r--r--src/System.Private.CoreLib/shared/System/Math.cs18
-rw-r--r--src/System.Private.CoreLib/shared/System/MemberAccessException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Memory.cs186
-rw-r--r--src/System.Private.CoreLib/shared/System/MemoryDebugView.cs28
-rw-r--r--src/System.Private.CoreLib/shared/System/MemoryExtensions.Fast.cs267
-rw-r--r--src/System.Private.CoreLib/shared/System/MemoryExtensions.cs479
-rw-r--r--src/System.Private.CoreLib/shared/System/MethodAccessException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/MissingFieldException.cs (renamed from src/System.Private.CoreLib/src/System/MissingFieldException.cs)25
-rw-r--r--src/System.Private.CoreLib/shared/System/MissingMemberException.cs (renamed from src/System.Private.CoreLib/src/System/MissingMemberException.cs)34
-rw-r--r--src/System.Private.CoreLib/shared/System/MulticastNotSupportedException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/NotFiniteNumberException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/NotImplementedException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/NotSupportedException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/NullReferenceException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Nullable.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Number.Formatting.cs517
-rw-r--r--src/System.Private.CoreLib/shared/System/Number.NumberBuffer.cs20
-rw-r--r--src/System.Private.CoreLib/shared/System/Number.Parsing.cs1489
-rw-r--r--src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.cs60
-rw-r--r--src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.tt17
-rw-r--r--src/System.Private.CoreLib/shared/System/Numerics/GenerationConfig.ttinclude61
-rw-r--r--src/System.Private.CoreLib/shared/System/Numerics/Register.cs132
-rw-r--r--src/System.Private.CoreLib/shared/System/Numerics/Register.tt2
-rw-r--r--src/System.Private.CoreLib/shared/System/Numerics/Vector.cs4501
-rw-r--r--src/System.Private.CoreLib/shared/System/Numerics/Vector.tt647
-rw-r--r--src/System.Private.CoreLib/shared/System/Numerics/Vector_Operations.cs64
-rw-r--r--src/System.Private.CoreLib/shared/System/ObjectDisposedException.cs18
-rw-r--r--src/System.Private.CoreLib/shared/System/ObsoleteAttribute.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/OperationCanceledException.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/OutOfMemoryException.cs (renamed from src/System.Private.CoreLib/src/System/OutOfMemoryException.cs)25
-rw-r--r--src/System.Private.CoreLib/shared/System/OverflowException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/PlatformNotSupportedException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Random.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/RankException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/ReadOnlyMemory.cs127
-rw-r--r--src/System.Private.CoreLib/shared/System/ReadOnlySpan.Fast.cs15
-rw-r--r--src/System.Private.CoreLib/shared/System/ReadOnlySpan.cs16
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/AssemblyNameFormatter.cs3
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Emit/AssemblyBuilderAccess.cs18
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Emit/FlowControl.cs32
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Emit/Label.cs75
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodeType.cs29
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodes.cs2539
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Emit/Opcode.cs191
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Emit/OperandType.cs41
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Emit/PEFileKinds.cs17
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Emit/PackingSize.cs19
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Emit/StackBehaviour.cs51
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/ExceptionHandlingClause.cs (renamed from src/System.Private.CoreLib/src/System/Reflection/ExceptionHandlingClause.cs)17
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/LocalVariableInfo.cs26
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/MethodBody.cs (renamed from src/System.Private.CoreLib/src/System/Reflection/MethodBody.cs)8
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/Module.cs42
-rw-r--r--src/System.Private.CoreLib/shared/System/Reflection/SignatureConstructedGenericType.cs20
-rw-r--r--src/System.Private.CoreLib/shared/System/Resources/FastResourceComparer.cs (renamed from src/System.Private.CoreLib/src/System/Resources/FastResourceComparer.cs)43
-rw-r--r--src/System.Private.CoreLib/shared/System/Resources/MissingSatelliteAssemblyException.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Resources/ResourceReader.cs (renamed from src/System.Private.CoreLib/src/System/Resources/ResourceReader.cs)186
-rw-r--r--src/System.Private.CoreLib/shared/System/Resources/ResourceSet.cs (renamed from src/System.Private.CoreLib/src/System/Resources/ResourceSet.cs)87
-rw-r--r--src/System.Private.CoreLib/shared/System/Resources/RuntimeResourceSet.cs42
-rw-r--r--src/System.Private.CoreLib/shared/System/Resources/SatelliteContractVersionAttribute.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerArgumentExpressionAttribute.cs17
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs100
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CustomConstantAttribute.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DecimalConstantAttribute.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DependencyAttribute.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ICastable.cs (renamed from src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastable.cs)11
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IndexerNameAttribute.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TaskAwaiter.cs (renamed from src/System.Private.CoreLib/src/System/Runtime/CompilerServices/TaskAwaiter.cs)147
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs86
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/YieldAwaitable.cs41
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/ConstrainedExecution/CriticalFinalizerObject.cs (renamed from src/System.Private.CoreLib/src/System/Runtime/ConstrainedExecution/CriticalFinalizerObject.cs)0
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ExternalException.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/InteropServices/HandleRef.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MarshalDirectiveException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.Fast.cs98
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.cs245
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/InteropServices/NativeCallableAttribute.cs (renamed from src/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeCallableAttribute.cs)25
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/InteropServices/SafeBuffer.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Aes.PlatformNotSupported.cs40
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Aes.cs40
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Base.PlatformNotSupported.cs33
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Base.cs33
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha1.PlatformNotSupported.cs54
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha1.cs53
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha256.PlatformNotSupported.cs41
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha256.cs41
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Simd.PlatformNotSupported.cs344
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Simd.cs344
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128.cs44
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128DebugView.cs118
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256.cs46
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256DebugView.cs118
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64.cs43
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64DebugView.cs118
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Aes.PlatformNotSupported.cs58
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Aes.cs58
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx.PlatformNotSupported.cs1230
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx.cs1412
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs1915
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.cs2641
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi1.PlatformNotSupported.cs96
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi1.cs96
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi2.PlatformNotSupported.cs64
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi2.cs64
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Enums.cs189
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Fma.PlatformNotSupported.cs190
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Fma.cs190
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Lzcnt.PlatformNotSupported.cs30
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Lzcnt.cs31
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Pclmulqdq.PlatformNotSupported.cs31
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Pclmulqdq.cs31
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Popcnt.PlatformNotSupported.cs30
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Popcnt.cs31
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.PlatformNotSupported.cs606
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.cs631
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.PlatformNotSupported.cs1763
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.cs2002
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse3.PlatformNotSupported.cs91
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse3.cs90
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.PlatformNotSupported.cs636
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.cs636
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse42.PlatformNotSupported.cs304
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse42.cs304
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Ssse3.PlatformNotSupported.cs116
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Ssse3.cs116
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Remoting/ObjectHandle.cs25
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationException.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfo.cs (renamed from src/System.Private.CoreLib/src/System/Runtime/Serialization/SerializationInfo.cs)157
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfoEnumerator.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Runtime/Versioning/TargetFrameworkAttribute.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/SByte.cs52
-rw-r--r--src/System.Private.CoreLib/shared/System/Security/AccessControl/RegistryRights.cs42
-rw-r--r--src/System.Private.CoreLib/shared/System/Security/SafeBSTRHandle.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Security/SecureString.Unix.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/Security/SecureString.Windows.cs11
-rw-r--r--src/System.Private.CoreLib/shared/System/Security/SecureString.cs19
-rw-r--r--src/System.Private.CoreLib/shared/System/Single.cs83
-rw-r--r--src/System.Private.CoreLib/shared/System/Span.Fast.cs15
-rw-r--r--src/System.Private.CoreLib/shared/System/Span.cs16
-rw-r--r--src/System.Private.CoreLib/shared/System/SpanDebugView.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/SpanHelpers.BinarySearch.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs509
-rw-r--r--src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs420
-rw-r--r--src/System.Private.CoreLib/shared/System/SpanHelpers.T.cs109
-rw-r--r--src/System.Private.CoreLib/shared/System/SpanHelpers.cs220
-rw-r--r--src/System.Private.CoreLib/shared/System/StackOverflowException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/String.Comparison.cs (renamed from src/System.Private.CoreLib/src/System/String.Comparison.cs)741
-rw-r--r--src/System.Private.CoreLib/shared/System/String.Manipulation.cs42
-rw-r--r--src/System.Private.CoreLib/shared/System/String.Searching.cs274
-rw-r--r--src/System.Private.CoreLib/shared/System/String.cs (renamed from src/System.Private.CoreLib/src/System/String.cs)507
-rw-r--r--src/System.Private.CoreLib/shared/System/StringComparer.cs20
-rw-r--r--src/System.Private.CoreLib/shared/System/StringSpanHelpers.cs142
-rw-r--r--src/System.Private.CoreLib/shared/System/SystemException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/ASCIIEncoding.cs124
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/Decoder.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/DecoderBestFitFallback.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/DecoderExceptionFallback.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/DecoderFallback.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/DecoderReplacementFallback.cs14
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/Encoder.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncoderBestFitFallback.cs14
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncoderExceptionFallback.cs20
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncoderFallback.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncoderReplacementFallback.cs22
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/Encoding.cs50
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncodingInfo.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncodingNLS.cs70
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncodingProvider.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/Latin1Encoding.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/StringBuilder.Debug.cs37
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs263
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/StringBuilderCache.cs62
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/UTF32Encoding.cs84
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/UTF7Encoding.cs92
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/UTF8Encoding.cs324
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/UnicodeEncoding.cs284
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/ValueStringBuilder.cs60
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/AbandonedMutexException.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/AsyncLocal.cs120
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/CancellationToken.cs (renamed from src/System.Private.CoreLib/src/System/Threading/CancellationToken.cs)256
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.Windows.cs93
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.cs51
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs33
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/ManualResetEventSlim.cs759
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Mutex.Windows.cs100
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Mutex.cs62
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/NativeOverlapped.cs (renamed from src/System.Private.CoreLib/src/System/Threading/NativeOverlapped.cs)0
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/ReaderWriterLockSlim.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Semaphore.Windows.cs88
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Semaphore.cs (renamed from src/System.Private.CoreLib/src/System/Threading/Semaphore.cs)69
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/SemaphoreFullException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/SemaphoreSlim.cs (renamed from src/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs)167
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/SendOrPostCallback.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/SpinLock.cs (renamed from src/System.Private.CoreLib/src/System/Threading/SpinLock.cs)214
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/SpinWait.cs51
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/SynchronizationLockException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs (renamed from src/System.Private.CoreLib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs)68
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCanceledException.cs12
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCompletionSource.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs510
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/ThreadInterruptedException.cs (renamed from src/System.Private.CoreLib/src/System/Threading/ThreadInterruptedException.cs)31
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/ThreadLocal.cs (renamed from src/System.Private.CoreLib/src/System/Threading/ThreadLocal.cs)251
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/ThreadStateException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/TimeoutHelper.cs14
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/WaitHandleCannotBeOpenedException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/TimeSpan.cs70
-rw-r--r--src/System.Private.CoreLib/shared/System/TimeZone.cs18
-rw-r--r--src/System.Private.CoreLib/shared/System/TimeZoneInfo.AdjustmentRule.cs27
-rw-r--r--src/System.Private.CoreLib/shared/System/TimeZoneInfo.Unix.cs262
-rw-r--r--src/System.Private.CoreLib/shared/System/TimeZoneInfo.Win32.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/TimeZoneInfo.cs89
-rw-r--r--src/System.Private.CoreLib/shared/System/TimeZoneNotFoundException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/TimeoutException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/Tuple.cs144
-rw-r--r--src/System.Private.CoreLib/shared/System/Type.Helpers.cs43
-rw-r--r--src/System.Private.CoreLib/shared/System/Type.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/TypeInitializationException.cs12
-rw-r--r--src/System.Private.CoreLib/shared/System/UInt16.cs50
-rw-r--r--src/System.Private.CoreLib/shared/System/UInt32.cs42
-rw-r--r--src/System.Private.CoreLib/shared/System/UInt64.cs40
-rw-r--r--src/System.Private.CoreLib/shared/System/UIntPtr.cs13
-rw-r--r--src/System.Private.CoreLib/shared/System/UnauthorizedAccessException.cs4
-rw-r--r--src/System.Private.CoreLib/shared/System/UnhandledExceptionEventArgs.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/UnhandledExceptionEventHandler.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/UnitySerializationHolder.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/ValueTuple.cs14
-rw-r--r--src/System.Private.CoreLib/shared/System/Version.cs30
-rw-r--r--src/System.Private.CoreLib/src/Internal/DeveloperExperience/DeveloperExperience.cs51
-rw-r--r--src/System.Private.CoreLib/src/Internal/IntrinsicSupport/ComparerHelpers.cs6
-rw-r--r--src/System.Private.CoreLib/src/Internal/IntrinsicSupport/EqualityComparerHelpers.cs15
-rw-r--r--src/System.Private.CoreLib/src/Internal/Reflection/ExplicitScopeAttribute.cs2
-rw-r--r--src/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeInstantiator.cs14
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.Unix.cs51
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/Augments/ReflectionExecutionDomainCallbacks.cs2
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs48
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.Unix.cs20
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.Windows.cs138
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.cs63
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs67
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs90
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/SynchronizedMethodHelpers.cs2
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RelocatedTypeAttribute.cs2
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/ThreadStatics.cs25
-rw-r--r--src/System.Private.CoreLib/src/Internal/Threading/Tasks/AsyncCausalitySupport.cs2
-rw-r--r--src/System.Private.CoreLib/src/Interop/Interop.WinRT.cs23
-rw-r--r--src/System.Private.CoreLib/src/Interop/Interop.manual.cs36
-rw-r--r--src/System.Private.CoreLib/src/MembersMustExist.AnalyzerData3
-rw-r--r--src/System.Private.CoreLib/src/Microsoft/Win32/Registry.cs34
-rw-r--r--src/System.Private.CoreLib/src/Microsoft/Win32/RegistryKey.Windows.cs206
-rw-r--r--src/System.Private.CoreLib/src/Microsoft/Win32/RegistryKey.cs11
-rw-r--r--src/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.Unix.cs17
-rw-r--r--src/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs47
-rw-r--r--src/System.Private.CoreLib/src/Resources/Strings.resx140
-rw-r--r--src/System.Private.CoreLib/src/System.Private.CoreLib.csproj135
-rw-r--r--src/System.Private.CoreLib/src/System/Activator.cs45
-rw-r--r--src/System.Private.CoreLib/src/System/AppContext.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/AppContextDefaultValues.cs10
-rw-r--r--src/System.Private.CoreLib/src/System/AppContextSwitches.cs60
-rw-r--r--src/System.Private.CoreLib/src/System/Array.CoreRT.cs46
-rw-r--r--src/System.Private.CoreLib/src/System/Array.cs112
-rw-r--r--src/System.Private.CoreLib/src/System/Attribute.cs24
-rw-r--r--src/System.Private.CoreLib/src/System/Buffer.cs74
-rw-r--r--src/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.CoreRT.cs37
-rw-r--r--src/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.cs603
-rw-r--r--src/System.Private.CoreLib/src/System/Collections/Generic/CompatibilityEqualityComparers.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/Collections/Generic/EqualOnlyComparer.cs52
-rw-r--r--src/System.Private.CoreLib/src/System/CurrentSystemTimeZone.Cache.cs21
-rw-r--r--src/System.Private.CoreLib/src/System/DefaultBinder.CanConvert.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/Delegate.DefaultParameters.cs4
-rw-r--r--src/System.Private.CoreLib/src/System/Delegate.cs43
-rw-r--r--src/System.Private.CoreLib/src/System/Diagnostics/Contracts/Contracts.cs52
-rw-r--r--src/System.Private.CoreLib/src/System/Diagnostics/Contracts/ContractsBCL.cs38
-rw-r--r--src/System.Private.CoreLib/src/System/Diagnostics/Debug.Windows.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs4
-rw-r--r--src/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreRT.cs10
-rw-r--r--src/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs31
-rw-r--r--src/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource_CoreRT.cs7
-rw-r--r--src/System.Private.CoreLib/src/System/Diagnostics/Tracing/UnsafeNativeMethods.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/EETypePtr.cs3
-rw-r--r--src/System.Private.CoreLib/src/System/Enum.cs201
-rw-r--r--src/System.Private.CoreLib/src/System/Environment.Unix.cs12
-rw-r--r--src/System.Private.CoreLib/src/System/Environment.Windows.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/Environment.cs47
-rw-r--r--src/System.Private.CoreLib/src/System/Exception.cs64
-rw-r--r--src/System.Private.CoreLib/src/System/GC.cs33
-rw-r--r--src/System.Private.CoreLib/src/System/Globalization/CultureInfo.Windows.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/Globalization/CultureInfo.cs44
-rw-r--r--src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs5
-rw-r--r--src/System.Private.CoreLib/src/System/Guid.Unix.cs24
-rw-r--r--src/System.Private.CoreLib/src/System/IO/Stream.CoreRT.cs13
-rw-r--r--src/System.Private.CoreLib/src/System/IO/Stream.cs808
-rw-r--r--src/System.Private.CoreLib/src/System/InvokeUtils.cs52
-rw-r--r--src/System.Private.CoreLib/src/System/MissingMemberException.CoreRT.cs20
-rw-r--r--src/System.Private.CoreLib/src/System/MulticastDelegate.cs14
-rw-r--r--src/System.Private.CoreLib/src/System/Number.CoreRT.cs107
-rw-r--r--src/System.Private.CoreLib/src/System/Number.Unix.cs7
-rw-r--r--src/System.Private.CoreLib/src/System/Object.cs8
-rw-r--r--src/System.Private.CoreLib/src/System/PrimitivesRuntimeContracts.cs409
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs214
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/AssemblyNameLexer.cs10
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs32
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/CustomAttributeData.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs96
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/Emit/ConstructorBuilder.cs150
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/Emit/CustomAttributeBuilder.cs29
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs194
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/Emit/EnumBuilder.cs361
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/Emit/EventBuilder.cs38
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/Emit/FieldBuilder.cs105
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/Emit/GenericTypeParameterBuilder.cs446
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs177
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/Emit/LocalBuilder.cs38
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs246
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs142
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/Emit/ParameterBuilder.cs74
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/Emit/PropertyBuilder.cs155
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/Emit/ReflectionEmitThrower.cs14
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/Emit/SignatureHelper.cs108
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs642
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/LocalVariableInfo.cs54
-rw-r--r--src/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs12
-rw-r--r--src/System.Private.CoreLib/src/System/Resources/FileBasedResourceGroveler.cs23
-rw-r--r--src/System.Private.CoreLib/src/System/Resources/IResourceGroveler.cs10
-rw-r--r--src/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs55
-rw-r--r--src/System.Private.CoreLib/src/System/Resources/ResourceManager.cs120
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.NonPortable.cs5
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs19
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs117
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/CompilerServices/FeatureRemovedException.cs25
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs14
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/InitializeFinalizerThread.cs4
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/InteropServices/CriticalHandle.cs13
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs16
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/InteropServices/InteropExtensions.cs29
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs4
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.cs12
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/InteropServices/UnsafeGCHandle.cs6
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs3
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/MemoryFailPoint.cs74
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs46
-rw-r--r--src/System.Private.CoreLib/src/System/Runtime/TypeLoaderExports.cs20
-rw-r--r--src/System.Private.CoreLib/src/System/RuntimeExceptionHelpers.cs22
-rw-r--r--src/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs9
-rw-r--r--src/System.Private.CoreLib/src/System/Security/AccessControl/RegistryRights.cs42
-rw-r--r--src/System.Private.CoreLib/src/System/String.CoreRT.cs57
-rw-r--r--src/System.Private.CoreLib/src/System/Text/EncodingData.cs4
-rw-r--r--src/System.Private.CoreLib/src/System/Text/StringBuilder.CoreRT.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/Text/StringBuilderCache.cs85
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/CancellationTokenRegistration.cs19
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs370
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/ClrThreadPool.CpuUtilizationReader.Windows.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Unix.cs54
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs116
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/EventWaitHandle.cs130
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Interlocked.cs4
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.Windows.cs4
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/LowLevelMonitor.Windows.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/ManagedThreadId.cs6
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/ManualResetEventSlim.cs14
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Monitor.cs36
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Mutex.Unix.cs29
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs91
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Mutex.cs103
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Overlapped.cs305
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/PinnableBufferCache.cs693
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Semaphore.Unix.cs29
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs106
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/SynchronizationContext.cs4
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Tasks/DebuggerSupport.Dummy.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Tasks/DebuggerSupport.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs34
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Tasks/FutureFactory.cs12
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Tasks/ProducerConsumerQueues.cs6
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs98
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Tasks/TaskContinuation.cs4
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Tasks/TaskFactory.cs38
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Tasks/TaskScheduler.cs14
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/ThreadPool.Portable.cs3
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/ThreadPool.Windows.cs4
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/ThreadPool.cs46
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/ThreadStart.cs18
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Timer.Unix.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Timer.Windows.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Timer.cs44
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Volatile.cs102
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/WaitHandle.Windows.cs4
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/WaitHandle.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/Threading/Win32ThreadPoolNativeOverlapped.cs6
-rw-r--r--src/System.Private.CoreLib/src/System/ThrowHelper.cs22
-rw-r--r--src/System.Private.CoreLib/src/System/TimeZoneInfo.WinRT.cs20
-rw-r--r--src/System.Private.CoreLib/src/System/ValueType.cs2
-rw-r--r--src/System.Private.CoreLib/src/System/WeakReference.cs14
-rw-r--r--src/System.Private.CoreLib/src/System/WeakReferenceOfT.cs2
-rw-r--r--src/System.Private.Interop/src/Interop/Interop.COM.Windows.cs64
-rw-r--r--src/System.Private.Interop/src/Interop/Interop.Common.Windows.cs8
-rw-r--r--src/System.Private.Interop/src/Interop/Interop.String.Windows.cs28
-rw-r--r--src/System.Private.Interop/src/InteropExtensions/InteropExtensions.cs2
-rw-r--r--src/System.Private.Interop/src/Shared/ComCallableObject.cs4
-rw-r--r--src/System.Private.Interop/src/Shared/InternalModule.cs13
-rw-r--r--src/System.Private.Interop/src/Shared/Interop.Manual.cs2
-rw-r--r--src/System.Private.Interop/src/Shared/McgHelpers.cs68
-rw-r--r--src/System.Private.Interop/src/Shared/McgIntrinsics.cs2
-rw-r--r--src/System.Private.Interop/src/Shared/McgMarshal.cs176
-rw-r--r--src/System.Private.Interop/src/Shared/StandardInterfaces.cs8
-rw-r--r--src/System.Private.Interop/src/Shared/StringPool.cs2
-rw-r--r--src/System.Private.Interop/src/Shared/__ComObject.cs2
-rw-r--r--src/System.Private.Interop/src/System.Private.Interop.Experimental.csproj9
-rw-r--r--src/System.Private.Interop/src/System.Private.Interop.csproj5
-rw-r--r--src/System.Private.Interop/src/System/Runtime/InteropServices/Marshal.cs181
-rw-r--r--src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/CustomPropertyImpl.cs2
-rw-r--r--src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationTokenTable.cs2
-rw-r--r--src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/PropertyValueImpl.cs8
-rw-r--r--src/System.Private.Interop/src/WinRT/ExceptionHelpers.cs145
-rw-r--r--src/System.Private.Interpreter/src/Internal/Runtime/CompilerHelpers/LibraryInitializer.cs17
-rw-r--r--src/System.Private.Interpreter/src/Internal/Runtime/Interpreter/ILImporter.Interpreter.cs501
-rw-r--r--src/System.Private.Interpreter/src/Internal/Runtime/Interpreter/ILInterpreter.cs46
-rw-r--r--src/System.Private.Interpreter/src/Internal/Runtime/Interpreter/InterpreterCallInterceptor.cs72
-rw-r--r--src/System.Private.Interpreter/src/Internal/Runtime/Interpreter/InterpreterExecutionStrategy.cs22
-rw-r--r--src/System.Private.Interpreter/src/Internal/Runtime/Interpreter/StackItem.cs105
-rw-r--r--src/System.Private.Interpreter/src/System.Private.Interpreter.csproj35
-rw-r--r--src/System.Private.Jit/src/Internal/Runtime/CompilerHelpers/LibraryInitializer.cs17
-rw-r--r--src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitCompilation.cs9
-rw-r--r--src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitMethodCodeNode.cs8
-rw-r--r--src/System.Private.Jit/src/Internal/Runtime/JitSupport/RyuJitExecutionStrategy.cs12
-rw-r--r--src/System.Private.Jit/src/Internal/Runtime/JitSupport/VirtualMethodSlotHelper.cs2
-rw-r--r--src/System.Private.Jit/src/System.Private.Jit.csproj9
-rw-r--r--src/System.Private.Reflection.Core/src/Resources/Strings.resx21
-rw-r--r--src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.Experimental.csproj2
-rw-r--r--src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj3
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/QueriedMemberList.cs4
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Dispensers.cs2
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/EcmaFormat/DefaultValueProcessing.cs2
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/MetadataReaderExtensions.NativeFormat.cs18
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NativeFormat/DefaultValueParser.cs2
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs7
-rw-r--r--src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs6
-rw-r--r--src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs250
-rw-r--r--src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecution.cs11
-rw-r--r--src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecutionDomainCallbacksImplementation.cs10
-rw-r--r--src/System.Private.Reflection.Execution/src/Resources/Strings.resx24
-rw-r--r--src/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.Experimental.csproj2
-rw-r--r--src/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj9
-rw-r--r--src/System.Private.Reflection.Metadata/tests/System.Private.Reflection.Metadata.Tests.csproj9
-rw-r--r--src/System.Private.StackTraceMetadata/src/System.Private.StackTraceMetadata.Experimental.csproj8
-rw-r--r--src/System.Private.StackTraceMetadata/src/System.Private.StackTraceMetadata.csproj8
-rw-r--r--src/System.Private.Threading/src/Resources/Strings.resx47
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Reflection/Core/AssemblyBinder.cs2
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.Ecma.cs8
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.cs6
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallConverterThunk.cs36
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallInterceptor.cs195
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallingConventions.cs16
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ConstrainedCallSupport.cs8
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/McgIntrinsics.cs7
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/MetadataReaderExtensions.Ecma.cs11
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/MethodEntrypointStubs.cs (renamed from src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/JitSupport.MethodEntrypointStubs.cs)0
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutFieldAlgorithm.cs6
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NoMetadataFieldLayoutAlgorithm.cs3
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs14
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilderState.cs4
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs2
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.MethodAddress.cs2
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderTypeSystemContext.cs4
-rw-r--r--src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeSystemExtensions.cs3
-rw-r--r--src/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeNoMetadataType.cs4
-rw-r--r--src/System.Private.TypeLoader/src/System.Private.TypeLoader.Experimental.csproj2
-rw-r--r--src/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj12
-rw-r--r--src/Test.CoreLib/src/Test.CoreLib.csproj3
-rw-r--r--src/dirs.proj3
1203 files changed, 65694 insertions, 25177 deletions
diff --git a/src/BuildIntegration/Microsoft.NETCore.Native.Publish.targets b/src/BuildIntegration/Microsoft.NETCore.Native.Publish.targets
index 5a801d765..bf6c643da 100644
--- a/src/BuildIntegration/Microsoft.NETCore.Native.Publish.targets
+++ b/src/BuildIntegration/Microsoft.NETCore.Native.Publish.targets
@@ -53,6 +53,10 @@
<!-- Fail with descriptive error message for common mistake. -->
<Error Condition="'$(RuntimeIdentifier)' == ''" Text="RuntimeIdentifier is required for native compilation. Try running dotnet publish with the -r option value specified." />
+ <!-- Fail with descriptive error message for common unsupported case. -->
+ <Error Condition="'$(OS)' == 'Windows_NT' and !$(RuntimeIdentifier.StartsWith('win'))" Text="Cross-compilation is not supported yet. https://github.com/dotnet/corert/issues/5458" />
+ <Error Condition="'$(OS)' != 'Windows_NT' and $(RuntimeIdentifier.StartsWith('win'))" Text="Cross-compilation is not supported yet. https://github.com/dotnet/corert/issues/5458" />
+
<!-- CoreRT SDK and Framework Assemblies need to be defined to avoid CoreCLR implementations being set as compiler inputs -->
<Error Condition="'@(PrivateSdkAssemblies)' == ''" Text="The PrivateSdkAssemblies ItemGroup is required for _ComputeAssembliesToCompileToNative" />
<Error Condition="'@(FrameworkAssemblies)' == ''" Text="The FrameworkAssemblies ItemGroup is required for _ComputeAssembliesToCompileToNative" />
@@ -66,4 +70,10 @@
</Target>
+ <Target Name="CopyNativePdb" Condition="'$(DebugType)' != 'None' and '$(TargetOS)' == 'Windows_NT'" AfterTargets="Publish">
+ <!-- dotnet CLI produces managed debug symbols - substitute with those we generated during native compilation -->
+ <Delete Files="$(PublishDir)\$(TargetName).pdb"/>
+ <Copy SourceFiles="$(NativeOutputPath)$(TargetName).pdb" DestinationFolder="$(PublishDir)" />
+ </Target>
+
</Project>
diff --git a/src/BuildIntegration/Microsoft.NETCore.Native.Unix.props b/src/BuildIntegration/Microsoft.NETCore.Native.Unix.props
index 441f4754c..a8c8bafdb 100644
--- a/src/BuildIntegration/Microsoft.NETCore.Native.Unix.props
+++ b/src/BuildIntegration/Microsoft.NETCore.Native.Unix.props
@@ -36,6 +36,8 @@ See the LICENSE file in the project root for more information.
<PropertyGroup>
<NativeLibraryExtension Condition="'$(NativeCodeGen)' != 'wasm'">.a</NativeLibraryExtension>
<NativeLibraryExtension Condition="'$(NativeCodeGen)' == 'wasm'">.bc</NativeLibraryExtension>
+ <FullRuntimeName>libRuntime</FullRuntimeName>
+ <FullRuntimeName Condition="'$(ServerGarbageCollection)' != ''">libRuntime.ServerGC</FullRuntimeName>
</PropertyGroup>
<ItemGroup>
@@ -50,7 +52,7 @@ See the LICENSE file in the project root for more information.
<NativeLibrary Condition="'$(IlcMultiModule)' == 'true' and $(NativeCodeGen) == ''" Include="$(SharedLibrary)" />
<NativeLibrary Condition="$(NativeCodeGen) == '' and $(NativeLib) == ''" Include="$(IlcPath)/sdk/libbootstrapper.a" />
<NativeLibrary Condition="$(NativeCodeGen) == '' and $(NativeLib) != ''" Include="$(IlcPath)/sdk/libbootstrapperdll.a" />
- <NativeLibrary Condition="$(NativeCodeGen) == ''" Include="$(IlcPath)/sdk/libRuntime.a" />
+ <NativeLibrary Condition="$(NativeCodeGen) == ''" Include="$(IlcPath)/sdk/$(FullRuntimeName).a" />
<NativeLibrary Condition="$(NativeCodeGen) == 'cpp'" Include="$(IlcPath)/sdk/libbootstrappercpp.a" />
<NativeLibrary Condition="$(NativeCodeGen) == 'cpp'" Include="$(IlcPath)/sdk/libPortableRuntime.a" />
<NativeLibrary Condition="$(NativeCodeGen) == 'wasm'" Include="$(IlcPath)/sdk/libbootstrappercpp.bc" />
@@ -59,6 +61,7 @@ See the LICENSE file in the project root for more information.
<ItemGroup>
<NativeLibrary Include="$(IlcPath)/sdk/libSystem.Private.CoreLib.Native$(NativeLibraryExtension)" />
+ <NativeLibrary Condition="$(NativeCodeGen) == ''" Include="$(IlcPath)/sdk/libSystem.Private.TypeLoader.Native$(NativeLibraryExtension)" />
<NativeLibrary Include="$(IlcPath)/framework/System.Native$(NativeLibraryExtension)" />
<NativeLibrary Include="$(IlcPath)/framework/System.Globalization.Native$(NativeLibraryExtension)" />
<NativeLibrary Include="$(IlcPath)/framework/System.IO.Compression.Native$(NativeLibraryExtension)" />
@@ -71,26 +74,28 @@ See the LICENSE file in the project root for more information.
<ItemGroup Condition="'$(TargetOS)' == 'OSX'">
<NativeFramework Include="CoreFoundation" />
<NativeFramework Include="Security" />
+ <NativeFramework Include="GSS" />
</ItemGroup>
<ItemGroup>
<LinkerArg Include="@(NativeLibrary)" />
<LinkerArg Include="-g" />
<LinkerArg Include="-Wl,-rpath,'$ORIGIN'" />
+ <LinkerArg Include="-Wl,--as-needed" Condition="'$(TargetOS)' != 'OSX'" />
<LinkerArg Include="-pthread" />
<LinkerArg Include="-lstdc++" />
<LinkerArg Include="-ldl" />
<LinkerArg Include="-lm" />
<LinkerArg Include="-lcurl" />
<LinkerArg Include="-lz" />
- <LinkerArg Include="-luuid" Condition="'$(TargetOS)' != 'OSX'" />
+ <LinkerArg Include="-lgssapi_krb5" Condition="'$(TargetOS)' != 'OSX'" />
<LinkerArg Include="-lrt" Condition="'$(TargetOS)' != 'OSX'" />
<LinkerArg Include="-licucore" Condition="'$(TargetOS)' == 'OSX'" />
<LinkerArg Include="-dynamiclib" Condition="'$(TargetOS)' == 'OSX' and '$(NativeLib)' == 'Shared'" />
<LinkerArg Include="-shared" Condition="'$(TargetOS)' != 'OSX' and '$(NativeLib)' == 'Shared'" />
<LinkerArg Include="@(NativeFramework->'-framework %(Identity)')" Condition="'$(TargetOS)' == 'OSX'" />
</ItemGroup>
-
+
<Exec Command="command -v $(CppLinker)" IgnoreExitCode="true">
<Output TaskParameter="ExitCode" PropertyName="_WhereLinker"/>
</Exec>
diff --git a/src/BuildIntegration/Microsoft.NETCore.Native.Windows.props b/src/BuildIntegration/Microsoft.NETCore.Native.Windows.props
index eadca8826..b06165b8a 100644
--- a/src/BuildIntegration/Microsoft.NETCore.Native.Windows.props
+++ b/src/BuildIntegration/Microsoft.NETCore.Native.Windows.props
@@ -18,6 +18,8 @@ See the LICENSE file in the project root for more information.
<CppCompiler>cl</CppCompiler>
<CppLinker>link</CppLinker>
<CppLibCreator>lib</CppLibCreator>
+ <FullRuntimeName>Runtime</FullRuntimeName>
+ <FullRuntimeName Condition="'$(ServerGarbageCollection)' != ''">Runtime.ServerGC</FullRuntimeName>
</PropertyGroup>
<!-- Part of workaround for lack of secondary build artifact import - https://github.com/Microsoft/msbuild/issues/2807 -->
@@ -36,7 +38,9 @@ See the LICENSE file in the project root for more information.
<ItemGroup>
<NativeLibrary Condition="$(NativeCodeGen) == '' and $(NativeLib) == ''" Include="$(IlcPath)\sdk\bootstrapper.lib" />
<NativeLibrary Condition="$(NativeCodeGen) == '' and $(NativeLib) != ''" Include="$(IlcPath)\sdk\bootstrapperdll.lib" />
- <NativeLibrary Condition="$(NativeCodeGen) == ''" Include="$(IlcPath)\sdk\Runtime.lib" />
+ <NativeLibrary Condition="$(NativeCodeGen) == ''" Include="$(IlcPath)\sdk\$(FullRuntimeName).lib" />
+ <NativeLibrary Condition="$(NativeCodeGen) == ''" Include="$(IlcPath)\sdk\System.Private.TypeLoader.Native.lib" />
+ <NativeLibrary Condition="$(NativeCodeGen) == '' and '$(ExperimentalJitSupport)' == 'true'" Include="$(IlcPath)\sdk\System.Private.Jit.Native.lib" />
<NativeLibrary Condition="$(NativeCodeGen) == 'cpp'" Include="$(IlcPath)\sdk\bootstrappercpp.lib" />
<NativeLibrary Condition="$(NativeCodeGen) == 'cpp'" Include="$(IlcPath)\sdk\PortableRuntime.lib" />
<NativeLibrary Condition="$(NativeCodeGen) == 'wasm'" Include="$(IlcPath)\sdk\bootstrappercpp.lib" />
@@ -61,10 +65,11 @@ See the LICENSE file in the project root for more information.
<ItemGroup>
<LinkerArg Condition="$(NativeLib) == 'Shared'" Include="/DLL" />
- <LinkerArg Include="@(NativeLibrary)" />
+ <LinkerArg Include="@(NativeLibrary->'&quot;%(Identity)&quot;')" />
<LinkerArg Include="/NOLOGO /DEBUG /MANIFEST:NO" />
<!-- The runtime is not compatible with jump stubs inserted by incremental linking. -->
<LinkerArg Include="/INCREMENTAL:NO" />
+ <LinkerArg Condition="'$(OutputType)' == 'WinExe'" Include="/SUBSYSTEM:WINDOWS /ENTRY:wmainCRTStartup" />
</ItemGroup>
<ItemGroup>
diff --git a/src/BuildIntegration/Microsoft.NETCore.Native.targets b/src/BuildIntegration/Microsoft.NETCore.Native.targets
index 23b817c7a..e5d806dce 100644
--- a/src/BuildIntegration/Microsoft.NETCore.Native.targets
+++ b/src/BuildIntegration/Microsoft.NETCore.Native.targets
@@ -39,14 +39,15 @@ See the LICENSE file in the project root for more information.
<IlcOutputFileExt Condition="$(NativeCodeGen) == 'cpp'">.cpp</IlcOutputFileExt>
<IlcOutputFileExt Condition="'$(NativeCodeGen)' == 'wasm'">.bc</IlcOutputFileExt>
-
- <NativeBinaryExt Condition="'$(OutputType)' == 'Exe' and '$(TargetOS)' == 'Windows_NT'">.exe</NativeBinaryExt>
- <NativeBinaryExt Condition="'$(OutputType)' == 'Exe' and '$(TargetOS)' != 'Windows_NT'"></NativeBinaryExt>
- <NativeBinaryExt Condition="'$(OutputType)' != 'Exe' and '$(TargetOS)' == 'Windows_NT' and $(NativeLib) == 'Shared'">.dll</NativeBinaryExt>
- <NativeBinaryExt Condition="'$(OutputType)' != 'Exe' and '$(TargetOS)' == 'OSX' and $(NativeLib) == 'Shared'">.dylib</NativeBinaryExt>
- <NativeBinaryExt Condition="'$(OutputType)' != 'Exe' and '$(TargetOS)' != 'Windows_NT' and '$(TargetOS)' != 'OSX' and $(NativeLib) == 'Shared'">.so</NativeBinaryExt>
- <NativeBinaryExt Condition="'$(OutputType)' != 'Exe' and '$(TargetOS)' == 'Windows_NT' and $(NativeLib) == 'Static'">.lib</NativeBinaryExt>
- <NativeBinaryExt Condition="'$(OutputType)' != 'Exe' and '$(TargetOS)' != 'Windows_NT' and $(NativeLib) == 'Static'">.a</NativeBinaryExt>
+ <IsNativeExecutable Condition="'$(OutputType)' == 'Exe' or '$(OutputType)' == 'WinExe'">true</IsNativeExecutable>
+
+ <NativeBinaryExt Condition="'$(IsNativeExecutable)' == 'true' and '$(TargetOS)' == 'Windows_NT'">.exe</NativeBinaryExt>
+ <NativeBinaryExt Condition="'$(IsNativeExecutable)' == 'true' and '$(TargetOS)' != 'Windows_NT'"></NativeBinaryExt>
+ <NativeBinaryExt Condition="'$(IsNativeExecutable)' != 'true' and '$(TargetOS)' == 'Windows_NT' and $(NativeLib) == 'Shared'">.dll</NativeBinaryExt>
+ <NativeBinaryExt Condition="'$(IsNativeExecutable)' != 'true' and '$(TargetOS)' == 'OSX' and $(NativeLib) == 'Shared'">.dylib</NativeBinaryExt>
+ <NativeBinaryExt Condition="'$(IsNativeExecutable)' != 'true' and '$(TargetOS)' != 'Windows_NT' and '$(TargetOS)' != 'OSX' and $(NativeLib) == 'Shared'">.so</NativeBinaryExt>
+ <NativeBinaryExt Condition="'$(IsNativeExecutable)' != 'true' and '$(TargetOS)' == 'Windows_NT' and $(NativeLib) == 'Static'">.lib</NativeBinaryExt>
+ <NativeBinaryExt Condition="'$(IsNativeExecutable)' != 'true' and '$(TargetOS)' != 'Windows_NT' and $(NativeLib) == 'Static'">.a</NativeBinaryExt>
<NativeBinaryExt Condition="'$(NativeCodeGen)' == 'wasm'">.html</NativeBinaryExt>
<ExportsFileExt Condition="'$(OutputType)' != 'Exe' and '$(TargetOS)' == 'Windows_NT' and '$(NativeLib)' == 'Shared'">.def</ExportsFileExt>
@@ -66,6 +67,8 @@ See the LICENSE file in the project root for more information.
<FrameworkLibPath Condition="'$(FrameworkLibPath)' == ''">$(NativeOutputPath)</FrameworkLibPath>
<FrameworkObjPath Condition="'$(FrameworkObjPath)' == ''">$(NativeIntermediateOutputPath)</FrameworkObjPath>
+ <ExperimentalDynamicCodeSupport Condition="'$(ExperimentalInterpreterSupport)' == 'true' or '$(ExperimentalJitSupport)' == 'true'">true</ExperimentalDynamicCodeSupport>
+
<SharedLibrary Condition="'$(OS)' == 'Windows_NT'">$(FrameworkLibPath)\Framework$(LibFileExt)</SharedLibrary>
<SharedLibrary Condition="'$(OS)' != 'Windows_NT'">$(FrameworkLibPath)\libframework$(LibFileExt)</SharedLibrary>
<IlcDynamicBuildPropertyDependencies Condition="'$(IlcCalledViaPackage)' == 'true'">SetupProperties</IlcDynamicBuildPropertyDependencies>
@@ -78,10 +81,32 @@ See the LICENSE file in the project root for more information.
</PropertyGroup>
<ItemGroup>
+ <AutoInitializedAssemblies Include="System.Private.CoreLib" />
+ <AutoInitializedAssemblies Include="System.Private.DeveloperExperience.Console" />
+ <AutoInitializedAssemblies Condition="'$(ExperimentalInterpreterSupport)' == 'true'" Include="System.Private.Interpreter" />
+ <AutoInitializedAssemblies Condition="'$(ExperimentalJitSupport)' == 'true'" Include="System.Private.Jit" />
+ </ItemGroup>
+
+ <ItemGroup Condition="'$(ExperimentalDynamicCodeSupport)' != 'true'">
+ <AutoInitializedAssemblies Include="System.Private.StackTraceMetadata" />
+ <AutoInitializedAssemblies Include="System.Private.TypeLoader" />
+ <AutoInitializedAssemblies Include="System.Private.Reflection.Execution" />
+ <AutoInitializedAssemblies Include="System.Private.Interop" />
+ </ItemGroup>
+
+ <ItemGroup Condition="'$(ExperimentalDynamicCodeSupport)' == 'true'">
+ <AutoInitializedAssemblies Include="System.Private.StackTraceMetadata.Experimental" />
+ <AutoInitializedAssemblies Include="System.Private.TypeLoader.Experimental" />
+ <AutoInitializedAssemblies Include="System.Private.Reflection.Execution.Experimental" />
+ <AutoInitializedAssemblies Include="System.Private.Interop.Experimental" />
+ </ItemGroup>
+
+ <ItemGroup>
<PrivateSdkAssemblies Include="$(IlcPath)\sdk\*.dll" />
</ItemGroup>
<ItemGroup>
- <FrameworkAssemblies Include="$(IlcPath)\framework\*.dll" />
+ <!-- Exclude clrcompression.dll for now https://github.com/dotnet/corert/issues/5496 -->
+ <FrameworkAssemblies Include="$(IlcPath)\framework\*.dll" Exclude="$(IlcPath)\framework\clrcompression.dll" />
</ItemGroup>
<ItemGroup>
@@ -159,6 +184,10 @@ See the LICENSE file in the project root for more information.
<IlcArg Condition="$(OutputType) == 'Library' and $(NativeLib) != ''" Include="--nativelib" />
<IlcArg Condition="$(ExportsFile) != ''" Include="--exportsfile:$(ExportsFile)" />
<ILcArg Condition="'$(Platform)' == 'wasm'" Include="--wasm" />
+ <ILcArg Condition="'$(ExperimentalDynamicCodeSupport)' == 'true'" Include="--nometadatablocking" />
+ <IlcArg Include="@(AutoInitializedAssemblies->'--initassembly:%(Identity)')" />
+ <IlcArg Include="@(AppContextSwitchOverrides->'--appcontextswitch:%(Identity)')" />
+ <IlcArg Condition="$(ServerGarbageCollection) != ''" Include="--runtimeopt:RH_UseServerGC=1" />
</ItemGroup>
<MakeDir Directories="$(NativeIntermediateOutputPath)" />
@@ -180,9 +209,9 @@ See the LICENSE file in the project root for more information.
DependsOnTargets="IlcCompile">
<ItemGroup>
- <CompilerArg Include="$(IlcCompileOutput)" />
- <CompilerArg Include="/Fo$(NativeObject)" Condition="'$(OS)' == 'Windows_NT'" />
- <CompilerArg Include="-o $(NativeObject)" Condition="'$(OS)' != 'Windows_NT'" />
+ <CompilerArg Include="&quot;$(IlcCompileOutput)&quot;" />
+ <CompilerArg Include="/Fo&quot;$(NativeObject)&quot;" Condition="'$(OS)' == 'Windows_NT'" />
+ <CompilerArg Include="-o &quot;$(NativeObject)&quot;" Condition="'$(OS)' != 'Windows_NT'" />
<CompilerArg Include="@(CppCompilerAndLinkerArg)" />
</ItemGroup>
@@ -198,19 +227,19 @@ See the LICENSE file in the project root for more information.
DependsOnTargets="$(LinkNativeDependsOn)">
<ItemGroup>
- <CustomLinkerArg Include="$(NativeObject)" />
- <CustomLinkerArg Include="-o $(NativeBinary)" Condition="'$(OS)' != 'Windows_NT'" />
- <CustomLinkerArg Include="/OUT:$(NativeBinary)" Condition="'$(OS)' == 'Windows_NT'" />
- <CustomLinkerArg Include="/DEF:$(ExportsFile)" Condition="'$(OS)' == 'Windows_NT' and $(ExportsFile) != ''" />
+ <CustomLinkerArg Include="&quot;$(NativeObject)&quot;" />
+ <CustomLinkerArg Include="-o &quot;$(NativeBinary)&quot;" Condition="'$(OS)' != 'Windows_NT'" />
+ <CustomLinkerArg Include="/OUT:&quot;$(NativeBinary)&quot;" Condition="'$(OS)' == 'Windows_NT'" />
+ <CustomLinkerArg Include="/DEF:&quot;$(ExportsFile)&quot;" Condition="'$(OS)' == 'Windows_NT' and $(ExportsFile) != ''" />
<CustomLinkerArg Include="/LIBPATH:&quot;%(AdditionalNativeLibraryDirectories.Identity)&quot;" Condition="'$(OS)' == 'Windows_NT' and '@(AdditionalNativeLibraryDirectories->Count())' &gt; 0" />
- <CustomLinkerArg Include="-exported_symbols_list $(ExportsFile)" Condition="'$(OS)' != 'Windows_NT' and $(ExportsFile) != ''" />
+ <CustomLinkerArg Include="-exported_symbols_list &quot;$(ExportsFile)&quot;" Condition="'$(OS)' != 'Windows_NT' and $(ExportsFile) != ''" />
<CustomLinkerArg Include="@(LinkerArg)" />
</ItemGroup>
<ItemGroup>
- <CustomLibArg Include="-crs $(NativeBinary)" Condition="'$(OS)' != 'Windows_NT'" />
- <CustomLibArg Include="/OUT:$(NativeBinary)" Condition="'$(OS)' == 'Windows_NT'" />
- <CustomLibArg Include="$(NativeObject)" />
+ <CustomLibArg Include="-crs &quot;$(NativeBinary)&quot;" Condition="'$(OS)' != 'Windows_NT'" />
+ <CustomLibArg Include="/OUT:&quot;$(NativeBinary)&quot;" Condition="'$(OS)' == 'Windows_NT'" />
+ <CustomLibArg Include="&quot;$(NativeObject)&quot;" />
</ItemGroup>
<MakeDir Directories="$([System.IO.Path]::GetDirectoryName($(NativeBinary)))" />
@@ -224,8 +253,8 @@ See the LICENSE file in the project root for more information.
<Exec Command="$(CppLibCreator) @&quot;$(NativeIntermediateOutputPath)lib.rsp&quot;" Condition="'$(OS)' == 'Windows_NT' and '$(NativeLib)' == 'Static' and '$(NativeCodeGen)' != 'wasm'" />
<PropertyGroup>
- <EmccArgs>&quot;$(NativeObject)&quot; -o &quot;$(NativeBinary)&quot; -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 </EmccArgs>
- <EmccArgs Condition="'$(Platform)'=='wasm'">$(EmccArgs) &quot;$(IlcPath)/sdk/libPortableRuntime.bc&quot; &quot;$(IlcPath)/sdk/libbootstrappercpp.bc&quot; </EmccArgs>
+ <EmccArgs>&quot;$(NativeObject)&quot; -o &quot;$(NativeBinary)&quot; -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 --emrun </EmccArgs>
+ <EmccArgs Condition="'$(Platform)'=='wasm'">$(EmccArgs) &quot;$(IlcPath)/sdk/libPortableRuntime.bc&quot; &quot;$(IlcPath)/sdk/libbootstrappercpp.bc&quot; &quot;$(IlcPath)/sdk/libSystem.Private.CoreLib.Native.bc&quot; </EmccArgs>
<EmccArgs Condition="'$(Configuration)'=='Release'">$(EmccArgs) -O2 --llvm-lto 2</EmccArgs>
<EmccArgs Condition="'$(Configuration)'=='Debug'">$(EmccArgs) -g3</EmccArgs>
</PropertyGroup>
diff --git a/src/Common/src/Internal/Metadata/NativeFormat/Generator/SchemaDef.cs b/src/Common/src/Internal/Metadata/NativeFormat/Generator/SchemaDef.cs
index d5da54db8..a6bb922ee 100644
--- a/src/Common/src/Internal/Metadata/NativeFormat/Generator/SchemaDef.cs
+++ b/src/Common/src/Internal/Metadata/NativeFormat/Generator/SchemaDef.cs
@@ -644,7 +644,7 @@ class SchemaDef
new MemberDef("Flags", "GenericParameterAttributes"),
new MemberDef("Kind", "GenericParameterKind"),
new MemberDef("Name", "ConstantStringValue", MemberDefFlags.RecordRef | MemberDefFlags.Child),
- new MemberDef("Constraints", TypeDefOrRefOrSpec, MemberDefFlags.List | MemberDefFlags.RecordRef | MemberDefFlags.EnumerateForHashCode),
+ new MemberDef("Constraints", TypeDefOrRefOrSpecOrMod, MemberDefFlags.List | MemberDefFlags.RecordRef | MemberDefFlags.EnumerateForHashCode),
new MemberDef("CustomAttributes", "CustomAttribute", MemberDefFlags.List | MemberDefFlags.RecordRef | MemberDefFlags.Child),
}
),
diff --git a/src/Common/src/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs b/src/Common/src/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs
index f068f31f9..9ade71970 100644
--- a/src/Common/src/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs
+++ b/src/Common/src/Internal/Metadata/NativeFormat/NativeFormatReaderGen.cs
@@ -4314,7 +4314,7 @@ namespace Internal.Metadata.NativeFormat
} // Name
internal ConstantStringValueHandle _name;
- /// One of: TypeDefinition, TypeReference, TypeSpecification
+ /// One of: TypeDefinition, TypeReference, TypeSpecification, ModifiedType
public HandleCollection Constraints
{
diff --git a/src/Common/src/Internal/NativeFormat/NativeFormatReader.cs b/src/Common/src/Internal/NativeFormat/NativeFormatReader.cs
index beb49d932..f10028e4f 100644
--- a/src/Common/src/Internal/NativeFormat/NativeFormatReader.cs
+++ b/src/Common/src/Internal/NativeFormat/NativeFormatReader.cs
@@ -223,7 +223,7 @@ namespace Internal.NativeFormat
public NativeReader(byte* base_, uint size)
{
// Limit the maximum blob size to prevent buffer overruns triggered by boundary integer overflows
- if (size >= UInt32.MaxValue / 4)
+ if (size >= uint.MaxValue / 4)
ThrowBadImageFormatException();
Debug.Assert(base_ <= base_ + size);
diff --git a/src/Common/src/Internal/Runtime/CompilerHelpers/StartupCodeHelpers.cs b/src/Common/src/Internal/Runtime/CompilerHelpers/StartupCodeHelpers.cs
index e5fba47ad..b7e299219 100644
--- a/src/Common/src/Internal/Runtime/CompilerHelpers/StartupCodeHelpers.cs
+++ b/src/Common/src/Internal/Runtime/CompilerHelpers/StartupCodeHelpers.cs
@@ -121,7 +121,10 @@ namespace Internal.Runtime.CompilerHelpers
for (int i = 0; i < count; i++)
{
if (pModuleHeaders[i] != IntPtr.Zero)
- modules[moduleIndex++] = RuntimeImports.RhpCreateTypeManager(osModule, pModuleHeaders[i], pClasslibFunctions, nClasslibFunctions);
+ {
+ modules[moduleIndex] = RuntimeImports.RhpCreateTypeManager(osModule, pModuleHeaders[i], pClasslibFunctions, nClasslibFunctions);
+ moduleIndex++;
+ }
}
return modules;
@@ -301,6 +304,6 @@ namespace Internal.Runtime.CompilerHelpers
internal unsafe struct TypeManagerSlot
{
public TypeManagerHandle TypeManager;
- public Int32 ModuleIndex;
+ public int ModuleIndex;
}
}
diff --git a/src/Common/src/Internal/Runtime/EEType.cs b/src/Common/src/Internal/Runtime/EEType.cs
index c9852dd80..66d952d2f 100644
--- a/src/Common/src/Internal/Runtime/EEType.cs
+++ b/src/Common/src/Internal/Runtime/EEType.cs
@@ -3,9 +3,11 @@
// See the LICENSE file in the project root for more information.
using System;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Internal.NativeFormat;
+using Internal.Runtime.CompilerServices;
using Debug = System.Diagnostics.Debug;
@@ -63,12 +65,12 @@ namespace Internal.Runtime
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct DispatchMapEntry
{
- internal UInt16 _usInterfaceIndex;
- internal UInt16 _usInterfaceMethodSlot;
- internal UInt16 _usImplMethodSlot;
+ internal ushort _usInterfaceIndex;
+ internal ushort _usInterfaceMethodSlot;
+ internal ushort _usImplMethodSlot;
}
- private UInt32 _entryCount;
+ private uint _entryCount;
private DispatchMapEntry _dispatchMap; // at least one entry if any interfaces defined
public bool IsEmpty
@@ -79,7 +81,7 @@ namespace Internal.Runtime
}
}
- public UInt32 NumEntries
+ public uint NumEntries
{
get
{
@@ -97,7 +99,7 @@ namespace Internal.Runtime
{
get
{
- return sizeof(UInt32) + sizeof(DispatchMapEntry) * (int)_entryCount;
+ return sizeof(uint) + sizeof(DispatchMapEntry) * (int)_entryCount;
}
}
@@ -106,7 +108,7 @@ namespace Internal.Runtime
get
{
fixed (DispatchMap* pThis = &this)
- return (DispatchMapEntry*)((byte*)pThis + sizeof(UInt32) + (sizeof(DispatchMapEntry) * index));
+ return (DispatchMapEntry*)((byte*)pThis + sizeof(uint) + (sizeof(DispatchMapEntry) * index));
}
}
}
@@ -147,7 +149,7 @@ namespace Internal.Runtime
private static unsafe class OptionalFieldsReader
{
- internal static UInt32 GetInlineField(byte* pFields, EETypeOptionalFieldTag eTag, UInt32 uiDefaultValue)
+ internal static uint GetInlineField(byte* pFields, EETypeOptionalFieldTag eTag, uint uiDefaultValue)
{
if (pFields == null)
return uiDefaultValue;
@@ -158,7 +160,7 @@ namespace Internal.Runtime
byte fieldHeader = NativePrimitiveDecoder.ReadUInt8(ref pFields);
isLastField = (fieldHeader & 0x80) != 0;
EETypeOptionalFieldTag eCurrentTag = (EETypeOptionalFieldTag)(fieldHeader & 0x7f);
- UInt32 uiCurrentValue = NativePrimitiveDecoder.DecodeUnsigned(ref pFields);
+ uint uiCurrentValue = NativePrimitiveDecoder.DecodeUnsigned(ref pFields);
// If we found a tag match return the current value.
if (eCurrentTag == eTag)
@@ -170,13 +172,29 @@ namespace Internal.Runtime
}
}
- private UInt16 _usComponentSize;
- private UInt16 _usFlags;
- private UInt32 _uBaseSize;
+ /// <summary>
+ /// Gets a value indicating whether the statically generated data structures use relative pointers.
+ /// </summary>
+ internal static bool SupportsRelativePointers
+ {
+ [Intrinsic]
+ get
+ {
+#if PROJECTN
+ return true;
+#else
+ throw new NotImplementedException();
+#endif
+ }
+ }
+
+ private ushort _usComponentSize;
+ private ushort _usFlags;
+ private uint _uBaseSize;
private RelatedTypeUnion _relatedType;
- private UInt16 _usNumVtableSlots;
- private UInt16 _usNumInterfaces;
- private UInt32 _uHashCode;
+ private ushort _usNumVtableSlots;
+ private ushort _usNumInterfaces;
+ private uint _uHashCode;
#if EETYPE_TYPE_MANAGER
private IntPtr _ppTypeManager;
@@ -187,14 +205,14 @@ namespace Internal.Runtime
// if the alignment is 8 bytes or less. If the alignment is higher then there may be a need for more bits to hold
// the rest of the padding data.
// If paddings of greater than 7 bytes are necessary, then the high bits of the field represent that padding
- private const UInt32 ValueTypePaddingLowMask = 0x7;
- private const UInt32 ValueTypePaddingHighMask = 0xFFFFFF00;
- private const UInt32 ValueTypePaddingMax = 0x07FFFFFF;
+ private const uint ValueTypePaddingLowMask = 0x7;
+ private const uint ValueTypePaddingHighMask = 0xFFFFFF00;
+ private const uint ValueTypePaddingMax = 0x07FFFFFF;
private const int ValueTypePaddingHighShift = 8;
- private const UInt32 ValueTypePaddingAlignmentMask = 0xF8;
+ private const uint ValueTypePaddingAlignmentMask = 0xF8;
private const int ValueTypePaddingAlignmentShift = 3;
- internal UInt16 ComponentSize
+ internal ushort ComponentSize
{
get
{
@@ -208,7 +226,7 @@ namespace Internal.Runtime
#endif
}
- internal UInt16 GenericArgumentCount
+ internal ushort GenericArgumentCount
{
get
{
@@ -224,7 +242,7 @@ namespace Internal.Runtime
#endif
}
- internal UInt16 Flags
+ internal ushort Flags
{
get
{
@@ -238,7 +256,7 @@ namespace Internal.Runtime
#endif
}
- internal UInt32 BaseSize
+ internal uint BaseSize
{
get
{
@@ -252,7 +270,7 @@ namespace Internal.Runtime
#endif
}
- internal UInt16 NumVtableSlots
+ internal ushort NumVtableSlots
{
get
{
@@ -266,7 +284,7 @@ namespace Internal.Runtime
#endif
}
- internal UInt16 NumInterfaces
+ internal ushort NumInterfaces
{
get
{
@@ -280,7 +298,7 @@ namespace Internal.Runtime
#endif
}
- internal UInt32 HashCode
+ internal uint HashCode
{
get
{
@@ -298,7 +316,7 @@ namespace Internal.Runtime
{
get
{
- return (EETypeKind)(_usFlags & (UInt16)EETypeFlags.EETypeKindMask);
+ return (EETypeKind)(_usFlags & (ushort)EETypeFlags.EETypeKindMask);
}
}
@@ -306,7 +324,7 @@ namespace Internal.Runtime
{
get
{
- return ((_usFlags & (UInt16)EETypeFlags.OptionalFieldsFlag) != 0);
+ return ((_usFlags & (ushort)EETypeFlags.OptionalFieldsFlag) != 0);
}
}
@@ -316,7 +334,7 @@ namespace Internal.Runtime
{
get
{
- return ((_usFlags & (UInt16)EETypeFlags.GenericVarianceFlag) != 0);
+ return ((_usFlags & (ushort)EETypeFlags.GenericVarianceFlag) != 0);
}
}
@@ -399,7 +417,7 @@ namespace Internal.Runtime
{
get
{
- return ((_usFlags & (UInt16)EETypeFlags.IsGenericFlag) != 0);
+ return ((_usFlags & (ushort)EETypeFlags.IsGenericFlag) != 0);
}
}
@@ -416,11 +434,10 @@ namespace Internal.Runtime
get
{
Debug.Assert(IsGeneric);
- UInt32 cbOffset = GetFieldOffset(EETypeField.ETF_GenericDefinition);
- fixed (EEType* pThis = &this)
- {
- return ((EETypeRef*)((byte*)pThis + cbOffset))->Value;
- }
+ if (IsDynamicType || !SupportsRelativePointers)
+ return GetField<IatAwarePointer<EEType>>(EETypeField.ETF_GenericDefinition).Value;
+
+ return GetField<IatAwareRelativePointer<EEType>>(EETypeField.ETF_GenericDefinition).Value;
}
#if TYPE_LOADER_IMPLEMENTATION
set
@@ -435,17 +452,39 @@ namespace Internal.Runtime
#endif
}
+ [StructLayout(LayoutKind.Sequential)]
+ private readonly struct GenericComposition
+ {
+ public readonly ushort Arity;
+
+ private readonly EETypeRef _genericArgument1;
+ public EETypeRef* GenericArguments
+ {
+ get
+ {
+ return (EETypeRef*)Unsafe.AsPointer(ref Unsafe.AsRef(in _genericArgument1));
+ }
+ }
+
+ public GenericVariance* GenericVariance
+ {
+ get
+ {
+ // Generic variance directly follows the last generic argument
+ return (GenericVariance*)(GenericArguments + Arity);
+ }
+ }
+ }
+
internal uint GenericArity
{
get
{
Debug.Assert(IsGeneric);
- UInt32 cbOffset = GetFieldOffset(EETypeField.ETF_GenericComposition);
- fixed (EEType* pThis = &this)
- {
- // Number of generic arguments is the first UInt16 of the composition stream.
- return **(UInt16**)((byte*)pThis + cbOffset);
- }
+ if (IsDynamicType || !SupportsRelativePointers)
+ return GetField<Pointer<GenericComposition>>(EETypeField.ETF_GenericComposition).Value->Arity;
+
+ return GetField<RelativePointer<GenericComposition>>(EETypeField.ETF_GenericComposition).Value->Arity;
}
}
@@ -454,13 +493,10 @@ namespace Internal.Runtime
get
{
Debug.Assert(IsGeneric);
- UInt32 cbOffset = GetFieldOffset(EETypeField.ETF_GenericComposition);
- fixed (EEType* pThis = &this)
- {
- // Generic arguments follow after a (padded) UInt16 specifying their count
- // in the generic composition stream.
- return ((*(EETypeRef**)((byte*)pThis + cbOffset)) + 1);
- }
+ if (IsDynamicType || !SupportsRelativePointers)
+ return GetField<Pointer<GenericComposition>>(EETypeField.ETF_GenericComposition).Value->GenericArguments;
+
+ return GetField<RelativePointer<GenericComposition>>(EETypeField.ETF_GenericComposition).Value->GenericArguments;
}
}
@@ -473,12 +509,10 @@ namespace Internal.Runtime
if (!HasGenericVariance)
return null;
- UInt32 cbOffset = GetFieldOffset(EETypeField.ETF_GenericComposition);
- fixed (EEType* pThis = &this)
- {
- // Variance info follows immediatelly after the generic arguments
- return (GenericVariance*)(GenericArguments + GenericArity);
- }
+ if (IsDynamicType || !SupportsRelativePointers)
+ return GetField<Pointer<GenericComposition>>(EETypeField.ETF_GenericComposition).Value->GenericVariance;
+
+ return GetField<RelativePointer<GenericComposition>>(EETypeField.ETF_GenericComposition).Value->GenericVariance;
}
}
@@ -504,7 +538,7 @@ namespace Internal.Runtime
{
get
{
- return ((_usFlags & (UInt16)EETypeFlags.IsInterfaceFlag) != 0);
+ return ((_usFlags & (ushort)EETypeFlags.IsInterfaceFlag) != 0);
}
}
@@ -561,7 +595,7 @@ namespace Internal.Runtime
// Currently, the meaning is a shape of 0 indicates that this is a Pointer,
// shape of 1 indicates a ByRef, and >=SZARRAY_BASE_SIZE indicates that this is an array.
// Two types are not equivalent if their shapes do not exactly match.
- internal UInt32 ParameterizedTypeShape
+ internal uint ParameterizedTypeShape
{
get
{
@@ -579,7 +613,7 @@ namespace Internal.Runtime
{
get
{
- return ((_usFlags & (UInt16)EETypeFlags.RelatedTypeViaIATFlag) != 0);
+ return ((_usFlags & (ushort)EETypeFlags.RelatedTypeViaIATFlag) != 0);
}
}
@@ -595,7 +629,7 @@ namespace Internal.Runtime
{
get
{
- return ((_usFlags & (UInt16)EETypeFlags.ICastableFlag) != 0);
+ return ((_usFlags & (ushort)EETypeFlags.ICastableFlag) != 0);
}
}
@@ -611,14 +645,14 @@ namespace Internal.Runtime
byte* optionalFields = OptionalFieldsPtr;
if(optionalFields != null)
{
- const UInt16 NoSlot = 0xFFFF;
- UInt16 uiSlot = (UInt16)OptionalFieldsReader.GetInlineField(optionalFields, EETypeOptionalFieldTag.ICastableIsInstSlot, NoSlot);
+ const ushort NoSlot = 0xFFFF;
+ ushort uiSlot = (ushort)OptionalFieldsReader.GetInlineField(optionalFields, EETypeOptionalFieldTag.ICastableIsInstSlot, NoSlot);
if (uiSlot != NoSlot)
{
if (uiSlot < NumVtableSlots)
return GetVTableStartAddress()[uiSlot];
else
- return GetSealedVirtualSlot((UInt16)(uiSlot - NumVtableSlots));
+ return GetSealedVirtualSlot((ushort)(uiSlot - NumVtableSlots));
}
}
@@ -643,14 +677,14 @@ namespace Internal.Runtime
byte* optionalFields = OptionalFieldsPtr;
if(optionalFields != null)
{
- const UInt16 NoSlot = 0xFFFF;
- UInt16 uiSlot = (UInt16)OptionalFieldsReader.GetInlineField(optionalFields, EETypeOptionalFieldTag.ICastableGetImplTypeSlot, NoSlot);
+ const ushort NoSlot = 0xFFFF;
+ ushort uiSlot = (ushort)OptionalFieldsReader.GetInlineField(optionalFields, EETypeOptionalFieldTag.ICastableGetImplTypeSlot, NoSlot);
if (uiSlot != NoSlot)
{
if (uiSlot < NumVtableSlots)
return GetVTableStartAddress()[uiSlot];
else
- return GetSealedVirtualSlot((UInt16)(uiSlot - NumVtableSlots));
+ return GetSealedVirtualSlot((ushort)(uiSlot - NumVtableSlots));
}
}
@@ -667,7 +701,7 @@ namespace Internal.Runtime
{
get
{
- return ((_usFlags & (UInt16)EETypeFlags.ValueTypeFlag) != 0);
+ return ((_usFlags & (ushort)EETypeFlags.ValueTypeFlag) != 0);
}
}
@@ -675,7 +709,7 @@ namespace Internal.Runtime
{
get
{
- return ((_usFlags & (UInt16)EETypeFlags.HasPointersFlag) != 0);
+ return ((_usFlags & (ushort)EETypeFlags.HasPointersFlag) != 0);
}
#if TYPE_LOADER_IMPLEMENTATION
set
@@ -700,7 +734,7 @@ namespace Internal.Runtime
}
}
- internal UInt32 ValueTypeFieldPadding
+ internal uint ValueTypeFieldPadding
{
get
{
@@ -712,15 +746,15 @@ namespace Internal.Runtime
// Get the value from the optional fields. The default is zero if that particular field was not included.
// The low bits of this field is the ValueType field padding, the rest of the byte is the alignment if present
- UInt32 ValueTypeFieldPaddingData = OptionalFieldsReader.GetInlineField(optionalFields, EETypeOptionalFieldTag.ValueTypeFieldPadding, 0);
- UInt32 padding = ValueTypeFieldPaddingData & ValueTypePaddingLowMask;
+ uint ValueTypeFieldPaddingData = OptionalFieldsReader.GetInlineField(optionalFields, EETypeOptionalFieldTag.ValueTypeFieldPadding, 0);
+ uint padding = ValueTypeFieldPaddingData & ValueTypePaddingLowMask;
// If there is additional padding, the other bits have that data
padding |= (ValueTypeFieldPaddingData & ValueTypePaddingHighMask) >> (ValueTypePaddingHighShift - ValueTypePaddingAlignmentShift);
return padding;
}
}
- internal UInt32 ValueTypeSize
+ internal uint ValueTypeSize
{
get
{
@@ -732,7 +766,7 @@ namespace Internal.Runtime
}
}
- internal UInt32 FieldByteCountNonGCAligned
+ internal uint FieldByteCountNonGCAligned
{
get
{
@@ -769,7 +803,7 @@ namespace Internal.Runtime
byte* optionalFields = OptionalFieldsPtr;
if (optionalFields == null)
return false;
- UInt32 idxDispatchMap = OptionalFieldsReader.GetInlineField(optionalFields, EETypeOptionalFieldTag.DispatchMap, 0xffffffff);
+ uint idxDispatchMap = OptionalFieldsReader.GetInlineField(optionalFields, EETypeOptionalFieldTag.DispatchMap, 0xffffffff);
if (idxDispatchMap == 0xffffffff)
{
if (HasDynamicallyAllocatedDispatchMap)
@@ -912,7 +946,7 @@ namespace Internal.Runtime
get
{
Debug.Assert(IsNullable);
- UInt32 cbNullableTypeOffset = GetFieldOffset(EETypeField.ETF_NullableType);
+ uint cbNullableTypeOffset = GetFieldOffset(EETypeField.ETF_NullableType);
fixed (EEType* pThis = &this)
{
if (IsNullableTypeViaIAT)
@@ -987,30 +1021,30 @@ namespace Internal.Runtime
return (IntPtr*)pResult;
}
- private static IntPtr FollowRelativePointer(Int32* pDist)
+ private static IntPtr FollowRelativePointer(int* pDist)
{
- Int32 dist = *pDist;
+ int dist = *pDist;
IntPtr result = (IntPtr)((byte*)pDist + dist);
return result;
}
- internal IntPtr GetSealedVirtualSlot(UInt16 slotNumber)
+ internal IntPtr GetSealedVirtualSlot(ushort slotNumber)
{
Debug.Assert(!IsNullable);
Debug.Assert((RareFlags & EETypeRareFlags.HasSealedVTableEntriesFlag) != 0);
fixed (EEType* pThis = &this)
{
- if (IsDynamicType)
+ if (IsDynamicType || !SupportsRelativePointers)
{
- UInt32 cbSealedVirtualSlotsTypeOffset = GetFieldOffset(EETypeField.ETF_SealedVirtualSlots);
+ uint cbSealedVirtualSlotsTypeOffset = GetFieldOffset(EETypeField.ETF_SealedVirtualSlots);
IntPtr* pSealedVirtualsSlotTable = *(IntPtr**)((byte*)pThis + cbSealedVirtualSlotsTypeOffset);
return pSealedVirtualsSlotTable[slotNumber];
}
else
{
- UInt32 cbSealedVirtualSlotsTypeOffset = GetFieldOffset(EETypeField.ETF_SealedVirtualSlots);
- Int32* pSealedVirtualsSlotTable = (Int32*)FollowRelativePointer((Int32*)((byte*)pThis + cbSealedVirtualSlotsTypeOffset));
+ uint cbSealedVirtualSlotsTypeOffset = GetFieldOffset(EETypeField.ETF_SealedVirtualSlots);
+ int* pSealedVirtualsSlotTable = (int*)FollowRelativePointer((int*)((byte*)pThis + cbSealedVirtualSlotsTypeOffset));
IntPtr result = FollowRelativePointer(&pSealedVirtualsSlotTable[slotNumber]);
return result;
}
@@ -1038,7 +1072,7 @@ namespace Internal.Runtime
if (!HasOptionalFields)
return null;
- UInt32 cbOptionalFieldsOffset = GetFieldOffset(EETypeField.ETF_OptionalFieldsPtr);
+ uint cbOptionalFieldsOffset = GetFieldOffset(EETypeField.ETF_OptionalFieldsPtr);
fixed (EEType* pThis = &this)
{
return *(byte**)((byte*)pThis + cbOptionalFieldsOffset);
@@ -1063,7 +1097,7 @@ namespace Internal.Runtime
get
{
Debug.Assert(IsDynamicType);
- UInt32 cbOffset = GetFieldOffset(EETypeField.ETF_DynamicTemplateType);
+ uint cbOffset = GetFieldOffset(EETypeField.ETF_DynamicTemplateType);
fixed (EEType* pThis = &this)
{
return *(EEType**)((byte*)pThis + cbOffset);
@@ -1087,7 +1121,7 @@ namespace Internal.Runtime
get
{
Debug.Assert((RareFlags & EETypeRareFlags.IsDynamicTypeWithGcStatics) != 0);
- UInt32 cbOffset = GetFieldOffset(EETypeField.ETF_DynamicGcStatics);
+ uint cbOffset = GetFieldOffset(EETypeField.ETF_DynamicGcStatics);
fixed (EEType* pThis = &this)
{
return (IntPtr)((byte*)pThis + cbOffset);
@@ -1111,7 +1145,7 @@ namespace Internal.Runtime
get
{
Debug.Assert((RareFlags & EETypeRareFlags.IsDynamicTypeWithNonGcStatics) != 0);
- UInt32 cbOffset = GetFieldOffset(EETypeField.ETF_DynamicNonGcStatics);
+ uint cbOffset = GetFieldOffset(EETypeField.ETF_DynamicNonGcStatics);
fixed (EEType* pThis = &this)
{
return (IntPtr)((byte*)pThis + cbOffset);
@@ -1136,7 +1170,7 @@ namespace Internal.Runtime
{
if ((RareFlags & EETypeRareFlags.HasDynamicModuleFlag) != 0)
{
- UInt32 cbOffset = GetFieldOffset(EETypeField.ETF_DynamicModule);
+ uint cbOffset = GetFieldOffset(EETypeField.ETF_DynamicModule);
fixed (EEType* pThis = &this)
{
return *(DynamicModule**)((byte*)pThis + cbOffset);
@@ -1209,7 +1243,7 @@ namespace Internal.Runtime
// Get the value from the optional fields. The default is zero if that particular field was not included.
// The low bits of this field is the ValueType field padding, the rest of the value is the alignment if present
- UInt32 alignmentValue = (OptionalFieldsReader.GetInlineField(optionalFields, EETypeOptionalFieldTag.ValueTypeFieldPadding, 0) & ValueTypePaddingAlignmentMask) >> ValueTypePaddingAlignmentShift;
+ uint alignmentValue = (OptionalFieldsReader.GetInlineField(optionalFields, EETypeOptionalFieldTag.ValueTypeFieldPadding, 0) & ValueTypePaddingAlignmentMask) >> ValueTypePaddingAlignmentShift;
// Alignment is stored as 1 + the log base 2 of the alignment, except a 0 indicates standard pointer alignment.
if (alignmentValue == 0)
@@ -1235,10 +1269,10 @@ namespace Internal.Runtime
}
}
- public UInt32 GetFieldOffset(EETypeField eField)
+ public uint GetFieldOffset(EETypeField eField)
{
// First part of EEType consists of the fixed portion followed by the vtable.
- UInt32 cbOffset = (UInt32)(sizeof(EEType) + (IntPtr.Size * _usNumVtableSlots));
+ uint cbOffset = (uint)(sizeof(EEType) + (IntPtr.Size * _usNumVtableSlots));
// Then we have the interface map.
if (eField == EETypeField.ETF_InterfaceMap)
@@ -1246,7 +1280,7 @@ namespace Internal.Runtime
Debug.Assert(NumInterfaces > 0);
return cbOffset;
}
- cbOffset += (UInt32)(sizeof(EEInterfaceInfo) * NumInterfaces);
+ cbOffset += (uint)(sizeof(EEInterfaceInfo) * NumInterfaces);
// Followed by the pointer to the finalizer method.
if (eField == EETypeField.ETF_Finalizer)
@@ -1255,7 +1289,7 @@ namespace Internal.Runtime
return cbOffset;
}
if (IsFinalizable)
- cbOffset += (UInt32)IntPtr.Size;
+ cbOffset += (uint)IntPtr.Size;
// Followed by the pointer to the optional fields.
if (eField == EETypeField.ETF_OptionalFieldsPtr)
@@ -1264,7 +1298,7 @@ namespace Internal.Runtime
return cbOffset;
}
if (HasOptionalFields)
- cbOffset += (UInt32)IntPtr.Size;
+ cbOffset += (uint)IntPtr.Size;
// Followed by the pointer to the type target of a Nullable<T>.
if (eField == EETypeField.ETF_NullableType)
@@ -1278,13 +1312,13 @@ namespace Internal.Runtime
return cbOffset;
if (IsNullable)
- cbOffset += (UInt32)IntPtr.Size;
+ cbOffset += (uint)IntPtr.Size;
EETypeRareFlags rareFlags = RareFlags;
// in the case of sealed vtable entries on static types, we have a UInt sized relative pointer
if ((rareFlags & EETypeRareFlags.HasSealedVTableEntriesFlag) != 0)
- cbOffset += (IsDynamicType ? (UInt32)IntPtr.Size : 4);
+ cbOffset += (IsDynamicType || !SupportsRelativePointers ? (uint)IntPtr.Size : 4);
if (eField == EETypeField.ETF_DynamicDispatchMap)
{
@@ -1292,7 +1326,7 @@ namespace Internal.Runtime
return cbOffset;
}
if ((rareFlags & EETypeRareFlags.HasDynamicallyAllocatedDispatchMapFlag) != 0)
- cbOffset += (UInt32)IntPtr.Size;
+ cbOffset += (uint)IntPtr.Size;
if (eField == EETypeField.ETF_GenericDefinition)
{
@@ -1300,7 +1334,12 @@ namespace Internal.Runtime
return cbOffset;
}
if (IsGeneric)
- cbOffset += (UInt32)IntPtr.Size;
+ {
+ if ((rareFlags & EETypeRareFlags.IsDynamicTypeFlag) != 0 || !SupportsRelativePointers)
+ cbOffset += (uint)IntPtr.Size;
+ else
+ cbOffset += 4;
+ }
if (eField == EETypeField.ETF_GenericComposition)
{
@@ -1308,7 +1347,12 @@ namespace Internal.Runtime
return cbOffset;
}
if (IsGeneric)
- cbOffset += (UInt32)IntPtr.Size;
+ {
+ if ((rareFlags & EETypeRareFlags.IsDynamicTypeFlag) != 0 || !SupportsRelativePointers)
+ cbOffset += (uint)IntPtr.Size;
+ else
+ cbOffset += 4;
+ }
if (eField == EETypeField.ETF_DynamicModule)
{
@@ -1316,7 +1360,7 @@ namespace Internal.Runtime
}
if ((rareFlags & EETypeRareFlags.HasDynamicModuleFlag) != 0)
- cbOffset += (UInt32)IntPtr.Size;
+ cbOffset += (uint)IntPtr.Size;
if (eField == EETypeField.ETF_DynamicTemplateType)
{
@@ -1324,7 +1368,7 @@ namespace Internal.Runtime
return cbOffset;
}
if (IsDynamicType)
- cbOffset += (UInt32)IntPtr.Size;
+ cbOffset += (uint)IntPtr.Size;
if (eField == EETypeField.ETF_DynamicGcStatics)
{
@@ -1332,7 +1376,7 @@ namespace Internal.Runtime
return cbOffset;
}
if ((rareFlags & EETypeRareFlags.IsDynamicTypeWithGcStatics) != 0)
- cbOffset += (UInt32)IntPtr.Size;
+ cbOffset += (uint)IntPtr.Size;
if (eField == EETypeField.ETF_DynamicNonGcStatics)
{
@@ -1340,7 +1384,7 @@ namespace Internal.Runtime
return cbOffset;
}
if ((rareFlags & EETypeRareFlags.IsDynamicTypeWithNonGcStatics) != 0)
- cbOffset += (UInt32)IntPtr.Size;
+ cbOffset += (uint)IntPtr.Size;
if (eField == EETypeField.ETF_DynamicThreadStaticOffset)
{
@@ -1354,6 +1398,12 @@ namespace Internal.Runtime
return 0;
}
+ public ref T GetField<T>(EETypeField eField)
+ {
+ fixed (EEType* pThis = &this)
+ return ref Unsafe.AddByteOffset(ref Unsafe.As<EEType, T>(ref *pThis), (IntPtr)GetFieldOffset(eField));
+ }
+
#if TYPE_LOADER_IMPLEMENTATION
internal static UInt32 GetSizeofEEType(
UInt16 cVirtuals,
@@ -1415,6 +1465,75 @@ namespace Internal.Runtime
}
}
+ // Wrapper around pointers
+ [StructLayout(LayoutKind.Sequential)]
+ internal unsafe readonly struct Pointer<T> where T : unmanaged
+ {
+ private readonly T* _value;
+
+ public T* Value
+ {
+ get
+ {
+ return _value;
+ }
+ }
+ }
+
+ // Wrapper around pointers that might be indirected through IAT
+ [StructLayout(LayoutKind.Sequential)]
+ internal unsafe readonly struct IatAwarePointer<T> where T : unmanaged
+ {
+ private readonly T* _value;
+
+ public T* Value
+ {
+ get
+ {
+ if (((int)_value & IndirectionConstants.IndirectionCellPointer) == 0)
+ return _value;
+ return *(T**)((byte*)_value - IndirectionConstants.IndirectionCellPointer);
+ }
+ }
+ }
+
+ // Wrapper around relative pointers
+ [StructLayout(LayoutKind.Sequential)]
+ internal unsafe readonly struct RelativePointer<T> where T : unmanaged
+ {
+ private readonly int _value;
+
+ public T* Value
+ {
+ get
+ {
+ return (T*)((byte*)Unsafe.AsPointer(ref Unsafe.AsRef(in _value)) + _value);
+ }
+ }
+ }
+
+ // Wrapper around relative pointers that might be indirected through IAT
+ [StructLayout(LayoutKind.Sequential)]
+ internal unsafe readonly struct IatAwareRelativePointer<T> where T : unmanaged
+ {
+ private readonly int _value;
+
+ public T* Value
+ {
+ get
+ {
+ if ((_value & IndirectionConstants.IndirectionCellPointer) == 0)
+ {
+ return (T*)((byte*)Unsafe.AsPointer(ref Unsafe.AsRef(in _value)) + _value);
+ }
+ else
+ {
+ return *(T**)((byte*)Unsafe.AsPointer(ref Unsafe.AsRef(in _value)) + (_value & ~IndirectionConstants.IndirectionCellPointer));
+ }
+ }
+ }
+ }
+
[StructLayout(LayoutKind.Sequential)]
internal struct DynamicModule
{
diff --git a/src/Common/src/Internal/Runtime/ModuleHeaders.cs b/src/Common/src/Internal/Runtime/ModuleHeaders.cs
index 20195b7cc..af312f84e 100644
--- a/src/Common/src/Internal/Runtime/ModuleHeaders.cs
+++ b/src/Common/src/Internal/Runtime/ModuleHeaders.cs
@@ -22,15 +22,15 @@ namespace Internal.Runtime
#pragma warning disable 0169
internal struct ReadyToRunHeader
{
- private UInt32 Signature; // ReadyToRunHeaderConstants.Signature
- private UInt16 MajorVersion;
- private UInt16 MinorVersion;
+ private uint Signature; // ReadyToRunHeaderConstants.Signature
+ private ushort MajorVersion;
+ private ushort MinorVersion;
- private UInt32 Flags;
+ private uint Flags;
- private UInt16 NumberOfSections;
- private Byte EntrySize;
- private Byte EntryType;
+ private ushort NumberOfSections;
+ private byte EntrySize;
+ private byte EntryType;
// Array of sections follows.
};
diff --git a/src/Common/src/Interop/Unix/System.Private.CoreLib.Native/Interop.CreateGuid.cs b/src/Common/src/Interop/Unix/System.Private.CoreLib.Native/Interop.GetEnviron.cs
index b6326aed0..539cdb3cf 100644
--- a/src/Common/src/Interop/Unix/System.Private.CoreLib.Native/Interop.CreateGuid.cs
+++ b/src/Common/src/Interop/Unix/System.Private.CoreLib.Native/Interop.GetEnviron.cs
@@ -3,14 +3,13 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
internal static partial class Interop
{
internal unsafe partial class Sys
{
- [DllImport(Interop.Libraries.CoreLibNative, EntryPoint = "CoreLibNative_CreateGuid")]
- internal static extern void CreateGuid(out Guid guid);
+ [DllImport(Interop.Libraries.CoreLibNative, EntryPoint = "CoreLibNative_GetEnviron")]
+ internal static extern unsafe IntPtr GetEnviron();
}
}
diff --git a/src/Common/src/Interop/Windows/Interop.Libraries.cs b/src/Common/src/Interop/Windows/Interop.Libraries.cs
index 8536bc367..68a50eadd 100644
--- a/src/Common/src/Interop/Windows/Interop.Libraries.cs
+++ b/src/Common/src/Interop/Windows/Interop.Libraries.cs
@@ -6,9 +6,6 @@ internal static partial class Interop
{
internal static partial class Libraries
{
- internal const string CoreFile_L1 = "api-ms-win-core-file-l1-1-0.dll";
- internal const string CoreFile_L1_2 = "api-ms-win-core-file-l1-2-0.dll";
- internal const string CoreFile_L2 = "api-ms-win-core-file-l2-1-0.dll";
internal const string ErrorHandling = "api-ms-win-core-errorhandling-l1-1-0.dll";
internal const string Handle = "api-ms-win-core-handle-l1-1-0.dll";
internal const string IO = "api-ms-win-core-io-l1-1-0.dll";
@@ -17,7 +14,6 @@ internal static partial class Interop
internal const string ProcessThreads = "api-ms-win-core-processthreads-l1-1-0.dll";
internal const string RealTime = "api-ms-win-core-realtime-l1-1-0.dll";
internal const string SysInfo = "api-ms-win-core-sysinfo-l1-2-0.dll";
- internal const string Registry_L1 = "api-ms-win-core-registry-l1-1-0.dll";
internal const string ThreadPool = "api-ms-win-core-threadpool-l1-2-0.dll";
internal const string Localization = "api-ms-win-core-localization-l1-2-1.dll";
}
diff --git a/src/Common/src/Interop/Windows/mincore/Interop.MemAllocFree.cs b/src/Common/src/Interop/Windows/mincore/Interop.MemAllocFree.cs
index bc537f749..823516ec4 100644
--- a/src/Common/src/Interop/Windows/mincore/Interop.MemAllocFree.cs
+++ b/src/Common/src/Interop/Windows/mincore/Interop.MemAllocFree.cs
@@ -17,7 +17,7 @@ internal static partial class Interop
internal static extern IntPtr HeapAlloc(IntPtr hHeap, uint dwFlags, UIntPtr dwBytes);
[DllImport("api-ms-win-core-heap-l1-1-0.dll")]
- internal static extern int HeapFree(IntPtr hHeap, UInt32 dwFlags, IntPtr lpMem);
+ internal static extern int HeapFree(IntPtr hHeap, uint dwFlags, IntPtr lpMem);
}
#if MULTIPLEX_OS
diff --git a/src/Common/src/Interop/Windows/mincore/Interop.MemReAlloc.cs b/src/Common/src/Interop/Windows/mincore/Interop.MemReAlloc.cs
index 45dc7c675..c195f481b 100644
--- a/src/Common/src/Interop/Windows/mincore/Interop.MemReAlloc.cs
+++ b/src/Common/src/Interop/Windows/mincore/Interop.MemReAlloc.cs
@@ -11,7 +11,7 @@ internal static partial class Interop
internal static unsafe partial class mincore
{
[DllImport("api-ms-win-core-heap-l1-1-0.dll")]
- internal static extern unsafe IntPtr HeapReAlloc(IntPtr hHeap, UInt32 dwFlags, IntPtr lpMem, UIntPtr dwBytes);
+ internal static extern unsafe IntPtr HeapReAlloc(IntPtr hHeap, uint dwFlags, IntPtr lpMem, UIntPtr dwBytes);
}
internal static unsafe IntPtr MemReAlloc(IntPtr ptr, UIntPtr newSize)
diff --git a/src/Common/src/Interop/Windows/mincore/Interop.Threading.cs b/src/Common/src/Interop/Windows/mincore/Interop.Threading.cs
index 23477e361..a08c62c81 100644
--- a/src/Common/src/Interop/Windows/mincore/Interop.Threading.cs
+++ b/src/Common/src/Interop/Windows/mincore/Interop.Threading.cs
@@ -10,39 +10,6 @@ internal static partial class Interop
{
internal static partial class mincore
{
- [DllImport(Libraries.Kernel32, EntryPoint = "CreateEventExW", SetLastError = true, CharSet = CharSet.Unicode)]
- internal extern static SafeWaitHandle CreateEventEx(IntPtr lpEventAttributes, string lpName, uint dwFlags, uint dwDesiredAccess);
-
- [DllImport(Libraries.Kernel32, EntryPoint = "CreateSemaphoreExW", SetLastError = true, CharSet = CharSet.Unicode)]
- internal static extern SafeWaitHandle CreateSemaphoreEx(IntPtr lpSemaphoreAttributes, int lInitialCount, int lMaximumCount, string lpName, uint dwFlags, uint dwDesiredAccess);
-
- [DllImport(Libraries.Kernel32, EntryPoint = "CreateMutexExW", SetLastError = true, CharSet = CharSet.Unicode)]
- internal extern static SafeWaitHandle CreateMutexEx(IntPtr lpMutexAttributes, string lpName, uint dwFlags, uint dwDesiredAccess);
-
- [DllImport(Libraries.Kernel32, EntryPoint = "OpenEventW", SetLastError = true, CharSet = CharSet.Unicode)]
- internal extern static SafeWaitHandle OpenEvent(uint dwDesiredAccess, bool bInheritHandle, string lpName);
-
- [DllImport(Libraries.Kernel32, EntryPoint = "OpenSemaphoreW", SetLastError = true, CharSet = CharSet.Unicode)]
- internal extern static SafeWaitHandle OpenSemaphore(uint dwDesiredAccess, bool bInheritHandle, string lpName);
-
- [DllImport(Libraries.Kernel32, EntryPoint = "OpenMutexW", SetLastError = true, CharSet = CharSet.Unicode)]
- internal extern static SafeWaitHandle OpenMutex(uint dwDesiredAccess, bool bInheritHandle, string lpName);
-
- [DllImport(Libraries.Kernel32)]
- internal extern static bool ResetEvent(IntPtr hEvent);
-
- [DllImport(Libraries.Kernel32)]
- internal extern static bool SetEvent(IntPtr hEvent);
-
- [DllImport(Libraries.Kernel32)]
- internal extern static bool SetEvent(SafeWaitHandle hEvent);
-
- [DllImport(Libraries.Kernel32)]
- internal extern static bool ReleaseSemaphore(IntPtr hSemaphore, int lReleaseCount, out int lpPreviousCount);
-
- [DllImport(Libraries.Kernel32)]
- internal extern static bool ReleaseMutex(IntPtr hMutex);
-
[DllImport(Libraries.Kernel32)]
internal extern static uint WaitForMultipleObjectsEx(uint nCount, IntPtr lpHandles, bool bWaitAll, uint dwMilliseconds, bool bAlertable);
diff --git a/src/Common/src/Interop/Windows/ole32/Interop.CoGetApartmentType.cs b/src/Common/src/Interop/Windows/ole32/Interop.CoGetApartmentType.cs
new file mode 100644
index 000000000..a7aca2ab7
--- /dev/null
+++ b/src/Common/src/Interop/Windows/ole32/Interop.CoGetApartmentType.cs
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+ internal enum APTTYPE : uint
+ {
+ APTTYPE_STA = 0x0u,
+ APTTYPE_MTA = 0x1u,
+ APTTYPE_NA = 0x2u,
+ APTTYPE_MAINSTA = 0x3u,
+ APTTYPE_CURRENT = 0xFFFFFFFFu,
+ }
+
+ internal enum APTTYPEQUALIFIER : uint
+ {
+ APTTYPEQUALIFIER_NONE = 0x0u,
+ APTTYPEQUALIFIER_IMPLICIT_MTA = 0x1u,
+ APTTYPEQUALIFIER_NA_ON_MTA = 0x2u,
+ APTTYPEQUALIFIER_NA_ON_STA = 0x3u,
+ APTTYPEQUALIFIER_NA_ON_IMPLICIT_MTA = 0x4u,
+ APTTYPEQUALIFIER_NA_ON_MAINSTA = 0x5u,
+ APTTYPEQUALIFIER_APPLICATION_STA = 0x6u,
+ }
+
+ internal static partial class Ole32
+ {
+ [DllImport(Interop.Libraries.Ole32, ExactSpelling = true)]
+ internal extern static int CoGetApartmentType(out APTTYPE pAptType, out APTTYPEQUALIFIER pAptQualifier);
+ }
+}
diff --git a/src/Common/src/Interop/Windows/ole32/Interop.CoInitializeEx.cs b/src/Common/src/Interop/Windows/ole32/Interop.CoInitializeEx.cs
new file mode 100644
index 000000000..f953d5ec4
--- /dev/null
+++ b/src/Common/src/Interop/Windows/ole32/Interop.CoInitializeEx.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+ internal static partial class Ole32
+ {
+ internal const uint COINIT_APARTMENTTHREADED = 2;
+ internal const uint COINIT_MULTITHREADED = 0;
+
+ [DllImport(Interop.Libraries.Ole32, ExactSpelling = true)]
+ internal extern static int CoInitializeEx(IntPtr reserved, uint dwCoInit);
+ }
+}
diff --git a/src/Common/src/Interop/Windows/ole32/Interop.CoUninitialize.cs b/src/Common/src/Interop/Windows/ole32/Interop.CoUninitialize.cs
new file mode 100644
index 000000000..ae0836688
--- /dev/null
+++ b/src/Common/src/Interop/Windows/ole32/Interop.CoUninitialize.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+ internal static partial class Ole32
+ {
+ [DllImport(Interop.Libraries.Ole32, ExactSpelling = true)]
+ internal extern static int CoUninitialize();
+ }
+}
diff --git a/src/Common/src/System/Collections/Concurrent/ConcurrentUnifier.cs b/src/Common/src/System/Collections/Concurrent/ConcurrentUnifier.cs
index cc7edb0a4..bbb5959ca 100644
--- a/src/Common/src/System/Collections/Concurrent/ConcurrentUnifier.cs
+++ b/src/Common/src/System/Collections/Concurrent/ConcurrentUnifier.cs
@@ -102,7 +102,7 @@ namespace System.Collections.Concurrent
// State of a key must never go from found to not found, and only one value may exist per key.
Debug.Assert(checkedFound);
if (default(V) == null) // No good way to do the "only one value" check for value types.
- Debug.Assert(Object.ReferenceEquals(checkedValue, value));
+ Debug.Assert(object.ReferenceEquals(checkedValue, value));
}
}
#endif //DEBUG
diff --git a/src/Common/src/System/Collections/Concurrent/ConcurrentUnifierW.cs b/src/Common/src/System/Collections/Concurrent/ConcurrentUnifierW.cs
index 8324b6c39..b2b70d8af 100644
--- a/src/Common/src/System/Collections/Concurrent/ConcurrentUnifierW.cs
+++ b/src/Common/src/System/Collections/Concurrent/ConcurrentUnifierW.cs
@@ -112,7 +112,7 @@ namespace System.Collections.Concurrent
// Since this DEBUG code is holding a strong reference to "value", state of a key must never go from found to not found,
// and only one value may exist per key.
Debug.Assert(checkedFound);
- Debug.Assert(Object.ReferenceEquals(checkedValue, value));
+ Debug.Assert(object.ReferenceEquals(checkedValue, value));
GC.KeepAlive(value);
}
}
diff --git a/src/Common/src/System/Collections/Concurrent/ConcurrentUnifierWKeyed.cs b/src/Common/src/System/Collections/Concurrent/ConcurrentUnifierWKeyed.cs
index 8aa21984d..5dfcab17a 100644
--- a/src/Common/src/System/Collections/Concurrent/ConcurrentUnifierWKeyed.cs
+++ b/src/Common/src/System/Collections/Concurrent/ConcurrentUnifierWKeyed.cs
@@ -125,7 +125,7 @@ namespace System.Collections.Concurrent
// Since this DEBUG code is holding a strong reference to "value", state of a key must never go from found to not found,
// and only one value may exist per key.
Debug.Assert(checkedFound);
- Debug.Assert(Object.ReferenceEquals(checkedValue, value));
+ Debug.Assert(object.ReferenceEquals(checkedValue, value));
GC.KeepAlive(value);
}
}
diff --git a/src/Common/src/System/Collections/Generic/LowLevelStack.cs b/src/Common/src/System/Collections/Generic/LowLevelStack.cs
new file mode 100644
index 000000000..b193036a2
--- /dev/null
+++ b/src/Common/src/System/Collections/Generic/LowLevelStack.cs
@@ -0,0 +1,161 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+** Private version of Stack<T> for internal System.Private.CoreLib use. This
+** permits sharing more source between BCL and System.Private.CoreLib (as well as the
+** fact that Stack<T> is just a useful class in general.)
+**
+** This does not strive to implement the full api surface area
+** (but any portion it does implement should match the real Stack<T>'s
+** behavior.)
+**
+===========================================================*/
+
+namespace System.Collections.Generic
+{
+ // Implements a variable-size Stack that uses an array of objects to store the
+ // elements. A Stack has a capacity, which is the allocated length
+ // of the internal array. As elements are added to a Stack, the capacity
+ // of the Stack is automatically increased as required by reallocating the
+ // internal array.
+ //
+ /// <summary>
+ /// LowLevelStack with no interface implementation to minimize both code and data size
+ /// Data size is smaller because there will be minimal virtual function table.
+ /// Code size is smaller because only functions called will be in the binary.
+ /// </summary>
+ internal class LowLevelStack<T>
+ {
+ protected T[] _items;
+ protected int _size;
+ protected int _version;
+
+ private static readonly T[] s_emptyArray = new T[0];
+
+ public LowLevelStack()
+ {
+ _items = s_emptyArray;
+ }
+
+ public LowLevelStack(int capacity)
+ {
+ if (capacity < 0)
+ throw new ArgumentOutOfRangeException(nameof(capacity));
+
+ if (capacity == 0)
+ _items = s_emptyArray;
+ else
+ {
+ _size = capacity;
+ _items = new T[capacity];
+ }
+ }
+
+ public LowLevelStack(IEnumerable<T> collection)
+ {
+ if (collection == null)
+ throw new ArgumentNullException(nameof(collection));
+
+ ICollection<T> c = collection as ICollection<T>;
+ if (c != null)
+ {
+ int count = c.Count;
+ if (count == 0)
+ {
+ _items = s_emptyArray;
+ }
+ else
+ {
+ _items = new T[count];
+ c.CopyTo(_items, 0);
+ _size = count;
+ }
+ }
+ else
+ {
+ _size = 0;
+ _items = s_emptyArray;
+
+ using (IEnumerator<T> en = collection.GetEnumerator())
+ {
+ while (en.MoveNext())
+ {
+ Push(en.Current);
+ }
+ }
+ }
+ }
+
+ public int Count
+ {
+ get
+ {
+ return _items.Length;
+ }
+ }
+
+ public void Push(T item)
+ {
+ _size = _size + 1;
+ Array.Resize(ref _items, _size);
+ _items[_size - 1] = item;
+ _version++;
+ }
+
+ public T Pop()
+ {
+ ThrowIfEmptyStack();
+
+ _size = _size - 1;
+ T item = _items[_size];
+ Array.Resize(ref _items, _size);
+ _version++;
+ return item;
+ }
+
+ public bool TryPop(out T result)
+ {
+ if (_size == 0)
+ {
+ result = default;
+ return false;
+ }
+
+ _size = _size - 1;
+ result = _items[_size];
+ Array.Resize(ref _items, _size);
+ _version++;
+
+ return true;
+ }
+
+ public T Peek()
+ {
+ ThrowIfEmptyStack();
+ return _items[_size - 1];
+ }
+
+ public bool TryPeek(out T result)
+ {
+ if (_size == 0)
+ {
+ result = default;
+ return false;
+ }
+
+ result = _items[_size - 1];
+ _version++;
+ return true;
+ }
+
+ private void ThrowIfEmptyStack()
+ {
+ if (_size == 0)
+ throw new InvalidOperationException();
+ }
+ }
+}
diff --git a/src/Common/src/System/CommonRuntimeTypes.cs b/src/Common/src/System/CommonRuntimeTypes.cs
index f4cfec469..435a1867e 100644
--- a/src/Common/src/System/CommonRuntimeTypes.cs
+++ b/src/Common/src/System/CommonRuntimeTypes.cs
@@ -37,28 +37,28 @@ namespace System
internal static Type Void { get { return s_void; } }
internal static Type MulticastDelegate { get { return s_multicastDelegate; } }
- private static Type s_object = typeof(Object);
+ private static Type s_object = typeof(object);
private static Type s_valuetype = typeof(ValueType);
private static Type s_type = typeof(Type);
private static Type s_attribute = typeof(Attribute);
- private static Type s_string = typeof(String);
+ private static Type s_string = typeof(string);
private static Type s_array = typeof(Array);
private static Type s_enum = typeof(Enum);
- private static Type s_boolean = typeof(Boolean);
- private static Type s_char = typeof(Char);
- private static Type s_byte = typeof(Byte);
- private static Type s_sByte = typeof(SByte);
- private static Type s_uInt16 = typeof(UInt16);
- private static Type s_int16 = typeof(Int16);
- private static Type s_uInt32 = typeof(UInt32);
- private static Type s_int32 = typeof(Int32);
- private static Type s_uInt64 = typeof(UInt64);
- private static Type s_int64 = typeof(Int64);
+ private static Type s_boolean = typeof(bool);
+ private static Type s_char = typeof(char);
+ private static Type s_byte = typeof(byte);
+ private static Type s_sByte = typeof(sbyte);
+ private static Type s_uInt16 = typeof(ushort);
+ private static Type s_int16 = typeof(short);
+ private static Type s_uInt32 = typeof(uint);
+ private static Type s_int32 = typeof(int);
+ private static Type s_uInt64 = typeof(ulong);
+ private static Type s_int64 = typeof(long);
private static Type s_uIntPtr = typeof(UIntPtr);
private static Type s_intPtr = typeof(IntPtr);
- private static Type s_single = typeof(Single);
- private static Type s_double = typeof(Double);
- private static Type s_decimal = typeof(Decimal);
+ private static Type s_single = typeof(float);
+ private static Type s_double = typeof(double);
+ private static Type s_decimal = typeof(decimal);
private static Type s_datetime = typeof(DateTime);
private static Type s_nullable = typeof(Nullable<>);
private static Type s_void = typeof(void);
diff --git a/src/Common/src/System/Numerics/Hashing/HashHelpers.cs b/src/Common/src/System/Numerics/Hashing/HashHelpers.cs
index f017309a9..dd405eba7 100644
--- a/src/Common/src/System/Numerics/Hashing/HashHelpers.cs
+++ b/src/Common/src/System/Numerics/Hashing/HashHelpers.cs
@@ -8,7 +8,7 @@ namespace System.Numerics.Hashing
internal static class HashHelpers
{
- public static readonly int RandomSeed = new Random().Next(Int32.MinValue, Int32.MaxValue);
+ public static readonly int RandomSeed = new Random().Next(int.MinValue, int.MaxValue);
public static int Combine(int h1, int h2)
{
diff --git a/src/Common/src/System/SR.cs b/src/Common/src/System/SR.cs
index 30462614f..ef42e9a6b 100644
--- a/src/Common/src/System/SR.cs
+++ b/src/Common/src/System/SR.cs
@@ -29,6 +29,10 @@ namespace System
// This method is used to decide if we need to append the exception message parameters to the message when calling SR.Format.
// by default it returns false.
+ // Native code generators can replace the value this returns based on user input at the time of native code generation.
+ // Marked as NoInlining because if this is used in an AoT compiled app that is not compiled into a single file, the user
+ // could compile each module with a different setting for this. We want to make sure there's a consistent behavior
+ // that doesn't depend on which native module this method got inlined into.
[MethodImpl(MethodImplOptions.NoInlining)]
private static bool UsingResourceKeys()
{
@@ -38,11 +42,14 @@ namespace System
// Needed for debugger integration
internal static string GetResourceString(string resourceKey)
{
- return GetResourceString(resourceKey, String.Empty);
+ return GetResourceString(resourceKey, string.Empty);
}
internal static string GetResourceString(string resourceKey, string defaultString)
{
+ if (UsingResourceKeys())
+ return defaultString ?? resourceKey;
+
string resourceString = null;
try { resourceString = InternalGetResourceString(resourceKey); }
catch (MissingManifestResourceException) { }
@@ -139,10 +146,10 @@ namespace System
{
if (UsingResourceKeys())
{
- return resourceFormat + String.Join(", ", args);
+ return resourceFormat + string.Join(", ", args);
}
- return String.Format(resourceFormat, args);
+ return string.Format(resourceFormat, args);
}
return resourceFormat;
@@ -152,29 +159,29 @@ namespace System
{
if (UsingResourceKeys())
{
- return String.Join(", ", resourceFormat, p1);
+ return string.Join(", ", resourceFormat, p1);
}
- return String.Format(resourceFormat, p1);
+ return string.Format(resourceFormat, p1);
}
internal static string Format(string resourceFormat, object p1, object p2)
{
if (UsingResourceKeys())
{
- return String.Join(", ", resourceFormat, p1, p2);
+ return string.Join(", ", resourceFormat, p1, p2);
}
- return String.Format(resourceFormat, p1, p2);
+ return string.Format(resourceFormat, p1, p2);
}
internal static string Format(string resourceFormat, object p1, object p2, object p3)
{
if (UsingResourceKeys())
{
- return String.Join(", ", resourceFormat, p1, p2, p3);
+ return string.Join(", ", resourceFormat, p1, p2, p3);
}
- return String.Format(resourceFormat, p1, p2, p3);
+ return string.Format(resourceFormat, p1, p2, p3);
}
}
}
diff --git a/src/Common/src/TypeSystem/Canon/CanonTypes.cs b/src/Common/src/TypeSystem/Canon/CanonTypes.cs
index ef8b60190..d84341b15 100644
--- a/src/Common/src/TypeSystem/Canon/CanonTypes.cs
+++ b/src/Common/src/TypeSystem/Canon/CanonTypes.cs
@@ -175,7 +175,7 @@ namespace Internal.TypeSystem
}
flags |= TypeFlags.HasFinalizerComputed;
- flags |= TypeFlags.IsByRefLikeComputed;
+ flags |= TypeFlags.AttributeCacheComputed;
return flags;
}
@@ -262,7 +262,7 @@ namespace Internal.TypeSystem
}
flags |= TypeFlags.HasFinalizerComputed;
- flags |= TypeFlags.IsByRefLikeComputed;
+ flags |= TypeFlags.AttributeCacheComputed;
return flags;
}
diff --git a/src/Common/src/TypeSystem/CodeGen/TypeDesc.CodeGen.cs b/src/Common/src/TypeSystem/CodeGen/TypeDesc.CodeGen.cs
new file mode 100644
index 000000000..9a5a1c8b2
--- /dev/null
+++ b/src/Common/src/TypeSystem/CodeGen/TypeDesc.CodeGen.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Internal.TypeSystem
+{
+ partial class TypeDesc
+ {
+ /// <summary>
+ /// Gets a value indicating whether this is a type that needs to be treated
+ /// specially.
+ /// </summary>
+ public bool IsIntrinsic
+ {
+ get
+ {
+ return (GetTypeFlags(TypeFlags.IsIntrinsic | TypeFlags.AttributeCacheComputed) & TypeFlags.IsIntrinsic) != 0;
+ }
+ }
+ }
+
+ partial class InstantiatedType
+ {
+ partial void AddComputedIntrinsicFlag(ref TypeFlags flags)
+ {
+ if (_typeDef.IsIntrinsic)
+ flags |= TypeFlags.IsIntrinsic;
+ }
+ }
+}
diff --git a/src/Common/src/TypeSystem/Common/ArrayType.cs b/src/Common/src/TypeSystem/Common/ArrayType.cs
index 22a985012..eaa454786 100644
--- a/src/Common/src/TypeSystem/Common/ArrayType.cs
+++ b/src/Common/src/TypeSystem/Common/ArrayType.cs
@@ -145,7 +145,7 @@ namespace Internal.TypeSystem
flags |= TypeFlags.HasFinalizerComputed;
- flags |= TypeFlags.IsByRefLikeComputed;
+ flags |= TypeFlags.AttributeCacheComputed;
return flags;
}
diff --git a/src/Common/src/TypeSystem/Common/ByRefType.cs b/src/Common/src/TypeSystem/Common/ByRefType.cs
index 164925f9d..6d1984594 100644
--- a/src/Common/src/TypeSystem/Common/ByRefType.cs
+++ b/src/Common/src/TypeSystem/Common/ByRefType.cs
@@ -37,7 +37,7 @@ namespace Internal.TypeSystem
flags |= TypeFlags.HasFinalizerComputed;
- flags |= TypeFlags.IsByRefLikeComputed;
+ flags |= TypeFlags.AttributeCacheComputed;
return flags;
}
diff --git a/src/Common/src/TypeSystem/Common/DefType.FieldLayout.cs b/src/Common/src/TypeSystem/Common/DefType.FieldLayout.cs
index 497701812..7f5638607 100644
--- a/src/Common/src/TypeSystem/Common/DefType.FieldLayout.cs
+++ b/src/Common/src/TypeSystem/Common/DefType.FieldLayout.cs
@@ -55,7 +55,8 @@ namespace Internal.TypeSystem
{
public StaticsBlock NonGcStatics;
public StaticsBlock GcStatics;
- public StaticsBlock ThreadStatics;
+ public StaticsBlock ThreadNonGcStatics;
+ public StaticsBlock ThreadGcStatics;
}
ThreadSafeFlags _fieldLayoutFlags;
@@ -217,10 +218,42 @@ namespace Internal.TypeSystem
}
/// <summary>
+ /// How many bytes must be allocated to represent the non GC visible thread static fields
+ /// of this type.
+ /// </summary>
+ public LayoutInt ThreadNonGcStaticFieldSize
+ {
+ get
+ {
+ if (!_fieldLayoutFlags.HasFlags(FieldLayoutFlags.ComputedStaticRegionLayout))
+ {
+ ComputeStaticFieldLayout(StaticLayoutKind.StaticRegionSizes);
+ }
+ return _staticBlockInfo == null ? LayoutInt.Zero : _staticBlockInfo.ThreadNonGcStatics.Size;
+ }
+ }
+
+ /// <summary>
+ /// What is the alignment required for allocating the non GC visible thread static fields
+ /// of this type.
+ /// </summary>
+ public LayoutInt ThreadNonGcStaticFieldAlignment
+ {
+ get
+ {
+ if (!_fieldLayoutFlags.HasFlags(FieldLayoutFlags.ComputedStaticRegionLayout))
+ {
+ ComputeStaticFieldLayout(StaticLayoutKind.StaticRegionSizes);
+ }
+ return _staticBlockInfo == null ? LayoutInt.Zero : _staticBlockInfo.ThreadNonGcStatics.LargestAlignment;
+ }
+ }
+
+ /// <summary>
/// How many bytes must be allocated to represent the (potentially GC visible) thread static
/// fields of this type.
/// </summary>
- public LayoutInt ThreadStaticFieldSize
+ public LayoutInt ThreadGcStaticFieldSize
{
get
{
@@ -228,7 +261,7 @@ namespace Internal.TypeSystem
{
ComputeStaticFieldLayout(StaticLayoutKind.StaticRegionSizes);
}
- return _staticBlockInfo == null ? LayoutInt.Zero : _staticBlockInfo.ThreadStatics.Size;
+ return _staticBlockInfo == null ? LayoutInt.Zero : _staticBlockInfo.ThreadGcStatics.Size;
}
}
@@ -236,7 +269,7 @@ namespace Internal.TypeSystem
/// What is the alignment required for allocating the (potentially GC visible) thread static
/// fields of this type.
/// </summary>
- public LayoutInt ThreadStaticFieldAlignment
+ public LayoutInt ThreadGcStaticFieldAlignment
{
get
{
@@ -244,7 +277,7 @@ namespace Internal.TypeSystem
{
ComputeStaticFieldLayout(StaticLayoutKind.StaticRegionSizes);
}
- return _staticBlockInfo == null ? LayoutInt.Zero : _staticBlockInfo.ThreadStatics.LargestAlignment;
+ return _staticBlockInfo == null ? LayoutInt.Zero : _staticBlockInfo.ThreadGcStatics.LargestAlignment;
}
}
@@ -328,13 +361,15 @@ namespace Internal.TypeSystem
if ((computedStaticLayout.NonGcStatics.Size != LayoutInt.Zero) ||
(computedStaticLayout.GcStatics.Size != LayoutInt.Zero) ||
- (computedStaticLayout.ThreadStatics.Size != LayoutInt.Zero))
+ (computedStaticLayout.ThreadNonGcStatics.Size != LayoutInt.Zero) ||
+ (computedStaticLayout.ThreadGcStatics.Size != LayoutInt.Zero))
{
var staticBlockInfo = new StaticBlockInfo
{
NonGcStatics = computedStaticLayout.NonGcStatics,
GcStatics = computedStaticLayout.GcStatics,
- ThreadStatics = computedStaticLayout.ThreadStatics
+ ThreadNonGcStatics = computedStaticLayout.ThreadNonGcStatics,
+ ThreadGcStatics = computedStaticLayout.ThreadGcStatics
};
_staticBlockInfo = staticBlockInfo;
}
diff --git a/src/Common/src/TypeSystem/Common/FieldDesc.FieldLayout.cs b/src/Common/src/TypeSystem/Common/FieldDesc.FieldLayout.cs
index 4f095421c..4452e8d6e 100644
--- a/src/Common/src/TypeSystem/Common/FieldDesc.FieldLayout.cs
+++ b/src/Common/src/TypeSystem/Common/FieldDesc.FieldLayout.cs
@@ -33,16 +33,13 @@ namespace Internal.TypeSystem
}
/// <summary>
- /// For static fields, represents whether or not the field is held in the GC or non GC statics region
- /// Does not apply to thread static fields.
+ /// For static fields, represents whether or not the field is held in the GC or non GC statics region.
/// </summary>
public bool HasGCStaticBase
{
get
{
- // If this assert fires then make sure the caller checks the IsThreadStatic attribute
- // of FieldDesc before checking its HasGCStaticBase property.
- Debug.Assert(IsStatic && !IsThreadStatic);
+ Debug.Assert(IsStatic);
return Context.ComputeHasGCStaticBase(this);
}
}
diff --git a/src/Common/src/TypeSystem/Common/FieldLayoutAlgorithm.cs b/src/Common/src/TypeSystem/Common/FieldLayoutAlgorithm.cs
index eee09f1b3..720c80a65 100644
--- a/src/Common/src/TypeSystem/Common/FieldLayoutAlgorithm.cs
+++ b/src/Common/src/TypeSystem/Common/FieldLayoutAlgorithm.cs
@@ -101,7 +101,8 @@ namespace Internal.TypeSystem
{
public StaticsBlock NonGcStatics;
public StaticsBlock GcStatics;
- public StaticsBlock ThreadStatics;
+ public StaticsBlock ThreadNonGcStatics;
+ public StaticsBlock ThreadGcStatics;
/// <summary>
/// If Offsets is non-null, then all field based layout is complete.
diff --git a/src/Common/src/TypeSystem/Common/FunctionPointerType.cs b/src/Common/src/TypeSystem/Common/FunctionPointerType.cs
index 5d50620d7..523b105d0 100644
--- a/src/Common/src/TypeSystem/Common/FunctionPointerType.cs
+++ b/src/Common/src/TypeSystem/Common/FunctionPointerType.cs
@@ -67,7 +67,7 @@ namespace Internal.TypeSystem
flags |= TypeFlags.HasFinalizerComputed;
- flags |= TypeFlags.IsByRefLikeComputed;
+ flags |= TypeFlags.AttributeCacheComputed;
return flags;
}
diff --git a/src/Common/src/TypeSystem/Common/GenericParameterDesc.cs b/src/Common/src/TypeSystem/Common/GenericParameterDesc.cs
index d98497921..4eff6c6cb 100644
--- a/src/Common/src/TypeSystem/Common/GenericParameterDesc.cs
+++ b/src/Common/src/TypeSystem/Common/GenericParameterDesc.cs
@@ -164,7 +164,7 @@ namespace Internal.TypeSystem
flags |= TypeFlags.HasGenericVarianceComputed;
- flags |= TypeFlags.IsByRefLikeComputed;
+ flags |= TypeFlags.AttributeCacheComputed;
return flags;
}
diff --git a/src/Common/src/TypeSystem/Common/InstantiatedType.cs b/src/Common/src/TypeSystem/Common/InstantiatedType.cs
index c5ae6776e..a777f223f 100644
--- a/src/Common/src/TypeSystem/Common/InstantiatedType.cs
+++ b/src/Common/src/TypeSystem/Common/InstantiatedType.cs
@@ -79,6 +79,10 @@ namespace Internal.TypeSystem
}
}
+ // Type system implementations that support the notion of intrinsic types
+ // will provide an implementation that adds the flag if necessary.
+ partial void AddComputedIntrinsicFlag(ref TypeFlags flags);
+
protected override TypeFlags ComputeTypeFlags(TypeFlags mask)
{
TypeFlags flags = 0;
@@ -104,12 +108,14 @@ namespace Internal.TypeSystem
flags |= TypeFlags.HasFinalizer;
}
- if ((mask & TypeFlags.IsByRefLikeComputed) != 0)
+ if ((mask & TypeFlags.AttributeCacheComputed) != 0)
{
- flags |= TypeFlags.IsByRefLikeComputed;
+ flags |= TypeFlags.AttributeCacheComputed;
if (_typeDef.IsByRefLike)
flags |= TypeFlags.IsByRefLike;
+
+ AddComputedIntrinsicFlag(ref flags);
}
return flags;
diff --git a/src/Common/src/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs b/src/Common/src/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs
index ab35f0548..94074e1d8 100644
--- a/src/Common/src/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs
+++ b/src/Common/src/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs
@@ -185,7 +185,8 @@ namespace Internal.TypeSystem
ComputedStaticFieldLayout result;
result.GcStatics = new StaticsBlock();
result.NonGcStatics = new StaticsBlock();
- result.ThreadStatics = new StaticsBlock();
+ result.ThreadGcStatics = new StaticsBlock();
+ result.ThreadNonGcStatics = new StaticsBlock();
if (numStaticFields == 0)
{
@@ -231,7 +232,12 @@ namespace Internal.TypeSystem
private ref StaticsBlock GetStaticsBlockForField(ref ComputedStaticFieldLayout layout, FieldDesc field)
{
if (field.IsThreadStatic)
- return ref layout.ThreadStatics;
+ {
+ if (field.HasGCStaticBase)
+ return ref layout.ThreadGcStatics;
+ else
+ return ref layout.ThreadNonGcStatics;
+ }
else if (field.HasGCStaticBase)
return ref layout.GcStatics;
else
@@ -293,7 +299,7 @@ namespace Internal.TypeSystem
var layoutMetadata = type.GetClassLayout();
- int packingSize = ComputePackingSize(type);
+ int packingSize = ComputePackingSize(type, layoutMetadata);
LayoutInt largestAlignmentRequired = LayoutInt.One;
var offsets = new FieldAndOffset[numInstanceFields];
@@ -353,9 +359,11 @@ namespace Internal.TypeSystem
// For types inheriting from another type, field offsets continue on from where they left off
LayoutInt cumulativeInstanceFieldPos = ComputeBytesUsedInParentType(type);
+ var layoutMetadata = type.GetClassLayout();
+
LayoutInt largestAlignmentRequirement = LayoutInt.One;
int fieldOrdinal = 0;
- int packingSize = ComputePackingSize(type);
+ int packingSize = ComputePackingSize(type, layoutMetadata);
foreach (var field in type.GetFields())
{
@@ -375,7 +383,6 @@ namespace Internal.TypeSystem
if (type.IsValueType)
{
- var layoutMetadata = type.GetClassLayout();
cumulativeInstanceFieldPos = LayoutInt.Max(cumulativeInstanceFieldPos, new LayoutInt(layoutMetadata.Size));
}
@@ -442,10 +449,8 @@ namespace Internal.TypeSystem
return result;
}
- private static int ComputePackingSize(MetadataType type)
+ private static int ComputePackingSize(MetadataType type, ClassLayoutMetadata layoutMetadata)
{
- var layoutMetadata = type.GetClassLayout();
-
// If a type contains pointers then the metadata specified packing size is ignored (On desktop this is disqualification from ManagedSequential)
if (layoutMetadata.PackingSize == 0 || type.ContainsGCPointers)
return type.Context.Target.DefaultPackingSize;
diff --git a/src/Common/src/TypeSystem/Common/MethodDesc.cs b/src/Common/src/TypeSystem/Common/MethodDesc.cs
index 74c48d8eb..7103433b0 100644
--- a/src/Common/src/TypeSystem/Common/MethodDesc.cs
+++ b/src/Common/src/TypeSystem/Common/MethodDesc.cs
@@ -133,7 +133,32 @@ namespace Internal.TypeSystem
return TypeHashingAlgorithms.ComputeMethodSignatureHashCode(_returnType.GetHashCode(), _parameters);
}
+ public SignatureEnumerator GetEnumerator()
+ {
+ return new SignatureEnumerator(this);
+ }
+
public override TypeSystemContext Context => _returnType.Context;
+
+ public struct SignatureEnumerator
+ {
+ private int _index;
+ private MethodSignature _signature;
+
+ public SignatureEnumerator(MethodSignature signature)
+ {
+ _signature = signature;
+ _index = -1;
+ }
+
+ public TypeDesc Current => _signature[_index];
+
+ public bool MoveNext()
+ {
+ _index++;
+ return _index < _signature.Length;
+ }
+ }
}
/// <summary>
diff --git a/src/Common/src/TypeSystem/Common/PointerType.cs b/src/Common/src/TypeSystem/Common/PointerType.cs
index e0cd681b2..15e8adbde 100644
--- a/src/Common/src/TypeSystem/Common/PointerType.cs
+++ b/src/Common/src/TypeSystem/Common/PointerType.cs
@@ -35,7 +35,7 @@ namespace Internal.TypeSystem
flags |= TypeFlags.HasGenericVarianceComputed;
flags |= TypeFlags.HasFinalizerComputed;
- flags |= TypeFlags.IsByRefLikeComputed;
+ flags |= TypeFlags.AttributeCacheComputed;
return flags;
}
diff --git a/src/Common/src/TypeSystem/Common/TargetDetails.cs b/src/Common/src/TypeSystem/Common/TargetDetails.cs
index 31323e59b..01ede185f 100644
--- a/src/Common/src/TypeSystem/Common/TargetDetails.cs
+++ b/src/Common/src/TypeSystem/Common/TargetDetails.cs
@@ -18,7 +18,7 @@ namespace Internal.TypeSystem
ARM64,
X64,
X86,
- Wasm32
+ Wasm32,
}
/// <summary>
@@ -49,7 +49,11 @@ namespace Internal.TypeSystem
/// <summary>
/// Jit runtime ABI
/// </summary>
- Jit
+ Jit,
+ /// <summary>
+ /// Cross-platform portable C++ codegen
+ /// </summary>
+ CppCodegen,
}
/// <summary>
@@ -102,6 +106,14 @@ namespace Internal.TypeSystem
}
}
+ public bool SupportsRelativePointers
+ {
+ get
+ {
+ return Abi != TargetAbi.CppCodegen;
+ }
+ }
+
/// <summary>
/// Gets the maximum alignment to which something can be aligned
/// </summary>
@@ -128,17 +140,36 @@ namespace Internal.TypeSystem
}
/// <summary>
- /// Gets the minimum required method alignment.
+ /// Gets the minimum required alignment for methods whose address is visible
+ /// to managed code.
/// </summary>
public int MinimumFunctionAlignment
{
get
{
// We use a minimum alignment of 4 irrespective of the platform.
+ // This is to prevent confusing the method address with a fat function pointer.
return 4;
}
}
+ public int MinimumCodeAlignment
+ {
+ get
+ {
+ switch (Architecture)
+ {
+ case TargetArchitecture.ARM:
+ case TargetArchitecture.ARMEL:
+ return 2;
+ case TargetArchitecture.ARM64:
+ return 4;
+ default:
+ return 1;
+ }
+ }
+ }
+
public TargetDetails(TargetArchitecture architecture, TargetOS targetOS, TargetAbi abi)
{
Architecture = architecture;
@@ -204,7 +235,6 @@ namespace Internal.TypeSystem
{
case TargetArchitecture.ARM:
case TargetArchitecture.ARMEL:
- case TargetArchitecture.Wasm32:
// ARM supports two alignments for objects on the GC heap (4 byte and 8 byte)
if (fieldAlignment.IsIndeterminate)
return LayoutInt.Indeterminate;
@@ -217,6 +247,7 @@ namespace Internal.TypeSystem
case TargetArchitecture.ARM64:
return new LayoutInt(8);
case TargetArchitecture.X86:
+ case TargetArchitecture.Wasm32:
return new LayoutInt(4);
default:
throw new NotSupportedException();
diff --git a/src/Common/src/TypeSystem/Common/TypeDesc.cs b/src/Common/src/TypeSystem/Common/TypeDesc.cs
index a3bc755f2..d9110d148 100644
--- a/src/Common/src/TypeSystem/Common/TypeDesc.cs
+++ b/src/Common/src/TypeSystem/Common/TypeDesc.cs
@@ -626,7 +626,7 @@ namespace Internal.TypeSystem
{
get
{
- return (GetTypeFlags(TypeFlags.IsByRefLike | TypeFlags.IsByRefLikeComputed) & TypeFlags.IsByRefLike) != 0;
+ return (GetTypeFlags(TypeFlags.IsByRefLike | TypeFlags.AttributeCacheComputed) & TypeFlags.IsByRefLike) != 0;
}
}
}
diff --git a/src/Common/src/TypeSystem/Common/TypeFlags.cs b/src/Common/src/TypeSystem/Common/TypeFlags.cs
index c177cbe59..028a7356d 100644
--- a/src/Common/src/TypeSystem/Common/TypeFlags.cs
+++ b/src/Common/src/TypeSystem/Common/TypeFlags.cs
@@ -57,7 +57,8 @@ namespace Internal.TypeSystem
HasFinalizerComputed = 0x1000,
HasFinalizer = 0x2000,
- IsByRefLike = 0x4000,
- IsByRefLikeComputed = 0x8000,
+ IsByRefLike = 0x04000,
+ AttributeCacheComputed = 0x08000,
+ IsIntrinsic = 0x10000,
}
}
diff --git a/src/Common/src/TypeSystem/Common/TypeSystemContext.cs b/src/Common/src/TypeSystem/Common/TypeSystemContext.cs
index 4f9dbb141..23e2c0758 100644
--- a/src/Common/src/TypeSystem/Common/TypeSystemContext.cs
+++ b/src/Common/src/TypeSystem/Common/TypeSystemContext.cs
@@ -66,6 +66,13 @@ namespace Internal.TypeSystem
return null;
}
+ internal virtual ModuleDesc ResolveModule(ModuleDesc referencingModule, string fileName, bool throwIfNotFound = true)
+ {
+ if (throwIfNotFound)
+ throw new NotSupportedException();
+ return null;
+ }
+
//
// Array types
//
diff --git a/src/Common/src/TypeSystem/Common/UniversalCanonLayoutAlgorithm.cs b/src/Common/src/TypeSystem/Common/UniversalCanonLayoutAlgorithm.cs
index f6c475abd..42eb4197f 100644
--- a/src/Common/src/TypeSystem/Common/UniversalCanonLayoutAlgorithm.cs
+++ b/src/Common/src/TypeSystem/Common/UniversalCanonLayoutAlgorithm.cs
@@ -45,7 +45,8 @@ namespace Internal.TypeSystem
{
NonGcStatics = new StaticsBlock() { Size = LayoutInt.Zero, LargestAlignment = LayoutInt.Zero },
GcStatics = new StaticsBlock() { Size = LayoutInt.Zero, LargestAlignment = LayoutInt.Zero },
- ThreadStatics = new StaticsBlock() { Size = LayoutInt.Zero, LargestAlignment = LayoutInt.Zero },
+ ThreadNonGcStatics = new StaticsBlock() { Size = LayoutInt.Zero, LargestAlignment = LayoutInt.Zero },
+ ThreadGcStatics = new StaticsBlock() { Size = LayoutInt.Zero, LargestAlignment = LayoutInt.Zero },
Offsets = Array.Empty<FieldAndOffset>()
};
}
diff --git a/src/Common/src/TypeSystem/Common/Utilities/GCPointerMap.Algorithm.cs b/src/Common/src/TypeSystem/Common/Utilities/GCPointerMap.Algorithm.cs
index 188780b87..8f9a1cd34 100644
--- a/src/Common/src/TypeSystem/Common/Utilities/GCPointerMap.Algorithm.cs
+++ b/src/Common/src/TypeSystem/Common/Utilities/GCPointerMap.Algorithm.cs
@@ -52,6 +52,7 @@ namespace Internal.TypeSystem
}
}
+ Debug.Assert(builder.ToGCMap().Size * type.Context.Target.PointerSize >= type.GCStaticFieldSize.AsInt);
return builder.ToGCMap();
}
@@ -60,11 +61,11 @@ namespace Internal.TypeSystem
/// </summary>
public static GCPointerMap FromThreadStaticLayout(DefType type)
{
- GCPointerMapBuilder builder = new GCPointerMapBuilder(type.ThreadStaticFieldSize.AsInt, type.Context.Target.PointerSize);
+ GCPointerMapBuilder builder = new GCPointerMapBuilder(type.ThreadGcStaticFieldSize.AsInt, type.Context.Target.PointerSize);
foreach (FieldDesc field in type.GetFields())
{
- if (!field.IsStatic || field.HasRva || field.IsLiteral || !field.IsThreadStatic)
+ if (!field.IsStatic || field.HasRva || field.IsLiteral || !field.IsThreadStatic || !field.HasGCStaticBase)
continue;
TypeDesc fieldType = field.FieldType;
@@ -84,6 +85,7 @@ namespace Internal.TypeSystem
}
}
+ Debug.Assert(builder.ToGCMap().Size * type.Context.Target.PointerSize >= type.ThreadGcStaticFieldSize.AsInt);
return builder.ToGCMap();
}
diff --git a/src/Common/src/TypeSystem/Common/Utilities/GCPointerMap.cs b/src/Common/src/TypeSystem/Common/Utilities/GCPointerMap.cs
index 342e1f834..30a4aab3e 100644
--- a/src/Common/src/TypeSystem/Common/Utilities/GCPointerMap.cs
+++ b/src/Common/src/TypeSystem/Common/Utilities/GCPointerMap.cs
@@ -164,8 +164,9 @@ namespace Internal.TypeSystem
public GCPointerMapBuilder(int numBytes, int pointerSize)
{
- // Don't care about the remainder - the remainder is not big enough to hold a GC pointer.
- int numPointerSizedCells = numBytes / pointerSize;
+ // Align the size up. The size of the pointer map is used to infer the statics storage size that has
+ // to include space for non-GC statics smaller than pointer size.
+ int numPointerSizedCells = (numBytes + pointerSize - 1) / pointerSize;
if (numPointerSizedCells > 0)
{
@@ -219,7 +220,7 @@ namespace Internal.TypeSystem
public GCPointerMap ToGCMap()
{
Debug.Assert(_delta == 0);
- return new GCPointerMap(_gcFlags, _limit / _pointerSize);
+ return new GCPointerMap(_gcFlags, (_limit + _pointerSize - 1) / _pointerSize);
}
public BitEnumerator GetEnumerator()
diff --git a/src/Common/src/TypeSystem/Ecma/EcmaModule.cs b/src/Common/src/TypeSystem/Ecma/EcmaModule.cs
index 14b3d51b4..37f82ca03 100644
--- a/src/Common/src/TypeSystem/Ecma/EcmaModule.cs
+++ b/src/Common/src/TypeSystem/Ecma/EcmaModule.cs
@@ -9,8 +9,6 @@ using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable;
-using Internal.TypeSystem;
-
namespace Internal.TypeSystem.Ecma
{
public partial class EcmaModule : ModuleDesc
@@ -147,6 +145,10 @@ namespace Internal.TypeSystem.Ecma
item = _module;
break;
+ case HandleKind.ModuleReference:
+ item = _module.ResolveModuleReference((ModuleReferenceHandle)handle);
+ break;
+
default:
throw new BadImageFormatException("Unknown metadata token type: " + handle.Kind);
}
@@ -165,6 +167,13 @@ namespace Internal.TypeSystem.Ecma
}
}
+ private object ResolveModuleReference(ModuleReferenceHandle handle)
+ {
+ ModuleReference moduleReference = _metadataReader.GetModuleReference(handle);
+ string fileName = _metadataReader.GetString(moduleReference.Name);
+ return Context.ResolveModule(this, fileName);
+ }
+
private LockFreeReaderHashtable<EntityHandle, IEntityHandleObject> _resolvedTokens;
internal EcmaModule(TypeSystemContext context, PEReader peReader, MetadataReader metadataReader)
diff --git a/src/Common/src/TypeSystem/Ecma/EcmaType.cs b/src/Common/src/TypeSystem/Ecma/EcmaType.cs
index e2e840f8a..de9f467c9 100644
--- a/src/Common/src/TypeSystem/Ecma/EcmaType.cs
+++ b/src/Common/src/TypeSystem/Ecma/EcmaType.cs
@@ -242,12 +242,28 @@ namespace Internal.TypeSystem.Ecma
flags |= TypeFlags.HasFinalizer;
}
- if ((mask & TypeFlags.IsByRefLikeComputed) != 0)
+ if ((mask & TypeFlags.AttributeCacheComputed) != 0)
{
- flags |= TypeFlags.IsByRefLikeComputed;
+ MetadataReader reader = MetadataReader;
+ MetadataStringComparer stringComparer = reader.StringComparer;
+ bool isValueType = IsValueType;
- if (IsValueType && HasCustomAttribute("System.Runtime.CompilerServices", "IsByRefLikeAttribute"))
- flags |= TypeFlags.IsByRefLike;
+ flags |= TypeFlags.AttributeCacheComputed;
+
+ foreach (CustomAttributeHandle attributeHandle in _typeDefinition.GetCustomAttributes())
+ {
+ if (MetadataReader.GetAttributeNamespaceAndName(attributeHandle, out StringHandle namespaceHandle, out StringHandle nameHandle))
+ {
+ if (isValueType &&
+ stringComparer.Equals(nameHandle, "IsByRefLikeAttribute") &&
+ stringComparer.Equals(namespaceHandle, "System.Runtime.CompilerServices"))
+ flags |= TypeFlags.IsByRefLike;
+
+ if (stringComparer.Equals(nameHandle, "IntrinsicAttribute") &&
+ stringComparer.Equals(namespaceHandle, "System.Runtime.CompilerServices"))
+ flags |= TypeFlags.IsIntrinsic;
+ }
+ }
}
return flags;
diff --git a/src/Common/src/TypeSystem/IL/DelegateInfo.cs b/src/Common/src/TypeSystem/IL/DelegateInfo.cs
index 5322fc618..8b5fc4dfb 100644
--- a/src/Common/src/TypeSystem/IL/DelegateInfo.cs
+++ b/src/Common/src/TypeSystem/IL/DelegateInfo.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System;
using System.Collections.Generic;
using Internal.IL.Stubs;
@@ -17,13 +18,19 @@ namespace Internal.IL
/// </summary>
public class DelegateInfo
{
- private TypeDesc _delegateType;
+ private readonly TypeDesc _delegateType;
+ private readonly DelegateFeature _supportedFeatures;
private MethodSignature _signature;
private MethodDesc _getThunkMethod;
private DelegateThunkCollection _thunks;
+ public static bool SupportsDynamicInvoke(TypeSystemContext context)
+ {
+ return DynamicInvokeMethodThunk.SupportsDynamicInvoke(context);
+ }
+
/// <summary>
/// Gets the synthetic methods that support this delegate type.
/// </summary>
@@ -78,6 +85,14 @@ namespace Internal.IL
}
}
+ public DelegateFeature SupportedFeatures
+ {
+ get
+ {
+ return _supportedFeatures;
+ }
+ }
+
/// <summary>
/// Gets the type of the delegate.
/// </summary>
@@ -89,12 +104,13 @@ namespace Internal.IL
}
}
- public DelegateInfo(TypeDesc delegateType)
+ public DelegateInfo(TypeDesc delegateType, DelegateFeature features)
{
Debug.Assert(delegateType.IsDelegate);
Debug.Assert(delegateType.IsTypeDefinition);
_delegateType = delegateType;
+ _supportedFeatures = features;
}
}
@@ -119,11 +135,11 @@ namespace Internal.IL
_openStaticThunk = new DelegateInvokeOpenStaticThunk(owningDelegate);
_multicastThunk = new DelegateInvokeMulticastThunk(owningDelegate);
_closedStaticThunk = new DelegateInvokeClosedStaticThunk(owningDelegate);
- _invokeThunk = new DelegateDynamicInvokeThunk(owningDelegate);
_closedInstanceOverGeneric = new DelegateInvokeInstanceClosedOverGenericMethodThunk(owningDelegate);
// Methods that have a byref-like type in the signature cannot be invoked with the object array thunk.
// We would need to box the parameter and these can't be boxed.
+ // Neither can be methods that have pointers in the signature.
MethodSignature delegateSignature = owningDelegate.Signature;
bool generateObjectArrayThunk = true;
for (int i = 0; i < delegateSignature.Length; i++)
@@ -136,19 +152,34 @@ namespace Internal.IL
generateObjectArrayThunk = false;
break;
}
+ if (paramType.IsPointer || paramType.IsFunctionPointer)
+ {
+ generateObjectArrayThunk = false;
+ break;
+ }
}
TypeDesc normalizedReturnType = delegateSignature.ReturnType;
if (normalizedReturnType.IsByRef)
normalizedReturnType = ((ByRefType)normalizedReturnType).ParameterType;
if (!normalizedReturnType.IsSignatureVariable && normalizedReturnType.IsByRefLike)
generateObjectArrayThunk = false;
+ if (normalizedReturnType.IsPointer || normalizedReturnType.IsFunctionPointer)
+ generateObjectArrayThunk = false;
- if (generateObjectArrayThunk)
+ if ((owningDelegate.SupportedFeatures & DelegateFeature.ObjectArrayThunk) != 0 && generateObjectArrayThunk)
_invokeObjectArrayThunk = new DelegateInvokeObjectArrayThunk(owningDelegate);
+ //
+ // Check whether we have a reverse p/invoke thunk
+ //
+
if (!owningDelegate.Type.HasInstantiation && IsNativeCallingConventionCompatible(delegateSignature))
_reversePInvokeThunk = new DelegateReversePInvokeThunk(owningDelegate);
+ //
+ // Check whether we have an open instance thunk
+ //
+
if (delegateSignature.Length > 0)
{
TypeDesc firstParam = delegateSignature[0];
@@ -185,6 +216,16 @@ namespace Internal.IL
}
}
+ //
+ // Check whether we have a dynamic invoke stub
+ //
+
+ if ((owningDelegate.SupportedFeatures & DelegateFeature.DynamicInvoke) != 0 &&
+ DynamicInvokeMethodThunk.SupportsSignature(delegateSignature))
+ {
+ var sig = new DynamicInvokeMethodSignature(delegateSignature);
+ _invokeThunk = owningDelegate.Type.Context.GetDynamicInvokeThunk(sig);
+ }
}
#region Temporary interop logic
@@ -277,4 +318,11 @@ namespace Internal.IL
ReversePinvokeThunk = 6, // This may not exist
ObjectArrayThunk = 7, // This may not exist
}
+
+ [Flags]
+ public enum DelegateFeature
+ {
+ DynamicInvoke = 0x1,
+ ObjectArrayThunk = 0x2,
+ }
}
diff --git a/src/Common/src/TypeSystem/IL/ILImporter.cs b/src/Common/src/TypeSystem/IL/ILImporter.cs
index fbfdac072..9a28605a7 100644
--- a/src/Common/src/TypeSystem/IL/ILImporter.cs
+++ b/src/Common/src/TypeSystem/IL/ILImporter.cs
@@ -317,6 +317,7 @@ namespace Internal.IL
private void ImportBasicBlocks()
{
_pendingBasicBlocks = _basicBlocks[0];
+ _basicBlocks[0].State = BasicBlock.ImportState.IsPending;
while (_pendingBasicBlocks != null)
{
BasicBlock basicBlock = _pendingBasicBlocks;
diff --git a/src/Common/src/TypeSystem/IL/ILProvider.cs b/src/Common/src/TypeSystem/IL/ILProvider.cs
index d12904f38..eb1747beb 100644
--- a/src/Common/src/TypeSystem/IL/ILProvider.cs
+++ b/src/Common/src/TypeSystem/IL/ILProvider.cs
@@ -78,6 +78,16 @@ namespace Internal.IL
return GetCanonTypeIntrinsic.EmitIL(method);
}
break;
+ case "EEType":
+ {
+ if (owningType.Namespace == "Internal.Runtime" && method.Name == "get_SupportsRelativePointers")
+ {
+ ILOpcode value = method.Context.Target.SupportsRelativePointers ?
+ ILOpcode.ldc_i4_1 : ILOpcode.ldc_i4_0;
+ return new ILStubMethodIL(method, new byte[] { (byte)value, (byte)ILOpcode.ret }, Array.Empty<LocalVariableDefinition>(), null);
+ }
+ }
+ break;
}
return null;
@@ -202,7 +212,7 @@ namespace Internal.IL
TypeSystemContext context = elementType.Context;
MetadataType helperType = context.SystemModule.GetKnownType("Internal.IntrinsicSupport", "EqualityComparerHelpers");
- MethodDesc methodToCall = null;
+ MethodDesc methodToCall;
if (elementType.IsEnum)
{
methodToCall = helperType.GetKnownMethod("EnumOnlyEquals", null).MakeInstantiatedMethod(elementType);
@@ -215,18 +225,19 @@ namespace Internal.IL
{
methodToCall = helperType.GetKnownMethod("StructOnlyEqualsIEquatable", null).MakeInstantiatedMethod(elementType);
}
-
- if (methodToCall != null)
+ else
{
- return new ILStubMethodIL(method, new byte[]
- {
- (byte)ILOpcode.ldarg_0,
- (byte)ILOpcode.ldarg_1,
- (byte)ILOpcode.call, 1, 0, 0, 0,
- (byte)ILOpcode.ret
- },
- Array.Empty<LocalVariableDefinition>(), new object[] { methodToCall });
+ methodToCall = helperType.GetKnownMethod("StructOnlyNormalEquals", null).MakeInstantiatedMethod(elementType);
}
+
+ return new ILStubMethodIL(method, new byte[]
+ {
+ (byte)ILOpcode.ldarg_0,
+ (byte)ILOpcode.ldarg_1,
+ (byte)ILOpcode.call, 1, 0, 0, 0,
+ (byte)ILOpcode.ret
+ },
+ Array.Empty<LocalVariableDefinition>(), new object[] { methodToCall });
}
}
}
@@ -246,7 +257,7 @@ namespace Internal.IL
if (((MetadataType)method.OwningType).HasCustomAttribute("System.Runtime.InteropServices", "McgIntrinsicsAttribute"))
{
var name = method.Name;
- if (name == "Call")
+ if (name == "Call" || name.StartsWith("StdCall"))
{
return CalliIntrinsic.EmitIL(method);
}
diff --git a/src/Common/src/TypeSystem/IL/Stubs/CalliIntrinsic.cs b/src/Common/src/TypeSystem/IL/Stubs/CalliIntrinsic.cs
index 28ae8b621..2a39b7779 100644
--- a/src/Common/src/TypeSystem/IL/Stubs/CalliIntrinsic.cs
+++ b/src/Common/src/TypeSystem/IL/Stubs/CalliIntrinsic.cs
@@ -18,7 +18,7 @@ namespace Internal.IL.Stubs
{
public static MethodIL EmitIL(MethodDesc target)
{
- Debug.Assert(target.Name == "Call");
+ Debug.Assert(target.Name == "Call" || target.Name.StartsWith("StdCall"));
Debug.Assert(target.Signature.Length > 0
&& target.Signature[0] == target.Context.GetWellKnownType(WellKnownType.IntPtr));
@@ -44,7 +44,11 @@ namespace Internal.IL.Stubs
parameters[i - 1] = template[i];
}
- var signature = new MethodSignature(template.Flags, 0, returnType, parameters);
+ MethodSignatureFlags flags = template.Flags;
+ if (target.Name == "StdCall")
+ flags |= MethodSignatureFlags.UnmanagedCallingConventionStdCall;
+
+ var signature = new MethodSignature(flags, 0, returnType, parameters);
codeStream.Emit(ILOpcode.calli, emitter.NewToken(signature));
codeStream.Emit(ILOpcode.ret);
diff --git a/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Mangling.cs b/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Mangling.cs
new file mode 100644
index 000000000..5bb37b622
--- /dev/null
+++ b/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Mangling.cs
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Internal.TypeSystem;
+
+namespace Internal.IL.Stubs
+{
+ public partial class CalliMarshallingMethodThunk : IPrefixMangledSignature
+ {
+ MethodSignature IPrefixMangledSignature.BaseSignature
+ {
+ get
+ {
+ return _targetSignature;
+ }
+ }
+
+ string IPrefixMangledSignature.Prefix
+ {
+ get
+ {
+ return "Calli";
+ }
+ }
+ }
+}
diff --git a/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Sorting.cs b/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Sorting.cs
new file mode 100644
index 000000000..2ac126d11
--- /dev/null
+++ b/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.Sorting.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.TypeSystem;
+
+namespace Internal.IL.Stubs
+{
+ // Functionality related to deterministic ordering of methods
+ partial class CalliMarshallingMethodThunk
+ {
+ protected internal override int ClassCode => 1594107963;
+
+ protected internal override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer)
+ {
+ var otherMethod = (CalliMarshallingMethodThunk)other;
+ return comparer.Compare(_targetSignature, otherMethod._targetSignature);
+ }
+ }
+}
diff --git a/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.cs b/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.cs
new file mode 100644
index 000000000..11489bb83
--- /dev/null
+++ b/src/Common/src/TypeSystem/IL/Stubs/CalliMarshallingMethodThunk.cs
@@ -0,0 +1,96 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Internal.TypeSystem;
+using Internal.TypeSystem.Interop;
+using Debug = System.Diagnostics.Debug;
+using Internal.TypeSystem.Ecma;
+
+namespace Internal.IL.Stubs
+{
+ /// <summary>
+ /// Thunk to marshal calli PInvoke parameters and invoke the appropriate function pointer
+ /// </summary>
+ public partial class CalliMarshallingMethodThunk : ILStubMethod
+ {
+ private readonly MethodSignature _targetSignature;
+ private readonly InteropStateManager _interopStateManager;
+ private readonly TypeDesc _owningType;
+
+ private MethodSignature _signature;
+
+ public CalliMarshallingMethodThunk(MethodSignature targetSignature, TypeDesc owningType,
+ InteropStateManager interopStateManager)
+ {
+ _targetSignature = targetSignature;
+ _owningType = owningType;
+ _interopStateManager = interopStateManager;
+ }
+
+ public MethodSignature TargetSignature
+ {
+ get
+ {
+ return _targetSignature;
+ }
+ }
+
+ public override TypeSystemContext Context
+ {
+ get
+ {
+ return _owningType.Context;
+ }
+ }
+
+ public override TypeDesc OwningType
+ {
+ get
+ {
+ return _owningType;
+ }
+ }
+
+ public override MethodSignature Signature
+ {
+ get
+ {
+ if (_signature == null)
+ {
+ // Prepend fnptr argument to the signature
+ TypeDesc[] parameterTypes = new TypeDesc[_targetSignature.Length + 1];
+
+ for (int i = 0; i < _targetSignature.Length; i++)
+ parameterTypes[i] = _targetSignature[i];
+ parameterTypes[parameterTypes.Length - 1] = Context.GetWellKnownType(WellKnownType.IntPtr);
+
+ _signature = new MethodSignature(MethodSignatureFlags.Static, 0, _targetSignature.ReturnType, parameterTypes);
+ }
+ return _signature;
+ }
+ }
+
+ public override string Name
+ {
+ get
+ {
+ return "CalliMarshallingMethodThunk";
+ }
+ }
+
+ public override bool IsPInvoke
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ public override MethodIL EmitIL()
+ {
+ return PInvokeILEmitter.EmitIL(this, default(PInvokeILEmitterConfiguration), _interopStateManager);
+ }
+ }
+}
diff --git a/src/Common/src/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.Mangling.cs b/src/Common/src/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.Mangling.cs
index 7813d0318..bd140239c 100644
--- a/src/Common/src/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.Mangling.cs
+++ b/src/Common/src/TypeSystem/IL/Stubs/DelegateMarshallingMethodThunk.Mangling.cs
@@ -7,9 +7,6 @@ using Internal.TypeSystem;
namespace Internal.IL.Stubs
{
- /// <summary>
- /// contains functionality related to name mangling
- /// </summary>
public partial class DelegateMarshallingMethodThunk : IPrefixMangledType
{
TypeDesc IPrefixMangledType.BaseType
diff --git a/src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.Sorting.cs b/src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.Sorting.cs
index f30a11c9c..d921c9c3b 100644
--- a/src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.Sorting.cs
+++ b/src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.Sorting.cs
@@ -51,17 +51,6 @@ namespace Internal.IL.Stubs
protected internal override int ClassCode => 1993292344;
}
- partial class DelegateDynamicInvokeThunk
- {
- protected internal override int ClassCode => -1127289330;
-
- protected internal override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer)
- {
- var otherMethod = (DelegateDynamicInvokeThunk)other;
- return comparer.Compare(_delegateInfo.Type, otherMethod._delegateInfo.Type);
- }
- }
-
partial class DelegateGetThunkMethodOverride
{
protected internal override int ClassCode => -321263379;
diff --git a/src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.cs b/src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.cs
index af8cb9a05..a4e4b8896 100644
--- a/src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.cs
+++ b/src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.cs
@@ -187,11 +187,20 @@ namespace Internal.IL.Stubs
// Call a helper to get the actual method target
codeStream.EmitLdArg(0);
- codeStream.EmitLdArg(1);
- if (boxThisType != null)
+
+ if (Signature[0].IsByRef)
+ {
+ codeStream.Emit(ILOpcode.ldnull);
+ }
+ else
{
- codeStream.Emit(ILOpcode.box, emitter.NewToken(boxThisType));
+ codeStream.EmitLdArg(1);
+ if (boxThisType != null)
+ {
+ codeStream.Emit(ILOpcode.box, emitter.NewToken(boxThisType));
+ }
}
+
codeStream.Emit(ILOpcode.call, emitter.NewToken(SystemDelegateType.GetKnownMethod("GetActualTargetFunctionPointer", null)));
MethodSignature targetSignature = new MethodSignature(0, 0, Signature.ReturnType, parameters);
@@ -555,14 +564,13 @@ namespace Internal.IL.Stubs
codeStream.EmitLdc(i);
codeStream.EmitLdArg(i + 1);
- TypeDesc boxableParamType = DelegateDynamicInvokeThunk.ConvertToBoxableType(paramType);
- ILToken boxableParamToken = emitter.NewToken(boxableParamType);
+ ILToken paramToken = emitter.NewToken(paramType);
if (paramIsByRef)
{
- codeStream.Emit(ILOpcode.ldobj, boxableParamToken);
+ codeStream.Emit(ILOpcode.ldobj, paramToken);
}
- codeStream.Emit(ILOpcode.box, boxableParamToken);
+ codeStream.Emit(ILOpcode.box, paramToken);
codeStream.Emit(ILOpcode.stelem_ref);
}
}
@@ -616,16 +624,15 @@ namespace Internal.IL.Stubs
if (paramType.IsByRef)
{
paramType = ((ByRefType)paramType).ParameterType;
- TypeDesc boxableParamType = DelegateDynamicInvokeThunk.ConvertToBoxableType(paramType);
- ILToken boxableParamToken = emitter.NewToken(boxableParamType);
+ ILToken paramToken = emitter.NewToken(paramType);
// Update parameter
codeStream.EmitLdArg(i + 1);
codeStream.EmitLdLoc(argsLocal);
codeStream.EmitLdc(i);
codeStream.Emit(ILOpcode.ldelem_ref);
- codeStream.Emit(ILOpcode.unbox_any, boxableParamToken);
- codeStream.Emit(ILOpcode.stobj, boxableParamToken);
+ codeStream.Emit(ILOpcode.unbox_any, paramToken);
+ codeStream.Emit(ILOpcode.stobj, paramToken);
}
}
// ilgen.Emit(OperationCode.Endfinally);
@@ -635,9 +642,8 @@ namespace Internal.IL.Stubs
if (hasReturnValue)
{
- TypeDesc boxableReturnType = DelegateDynamicInvokeThunk.ConvertToBoxableType(Signature.ReturnType);
codeStream.EmitLdLoc(retLocal);
- codeStream.Emit(ILOpcode.unbox_any, emitter.NewToken(boxableReturnType));
+ codeStream.Emit(ILOpcode.unbox_any, emitter.NewToken(Signature.ReturnType));
}
codeStream.Emit(ILOpcode.ret);
@@ -655,213 +661,6 @@ namespace Internal.IL.Stubs
}
/// <summary>
- /// Delegate thunk that supports Delegate.DynamicInvoke. This thunk has heavy dependencies on the
- /// general dynamic invocation infrastructure in System.InvokeUtils and gets called from there
- /// at runtime. See comments in System.InvokeUtils for a more thorough explanation.
- /// </summary>
- public sealed partial class DelegateDynamicInvokeThunk : ILStubMethod
- {
- private DelegateInfo _delegateInfo;
- private MethodSignature _signature;
-
- public DelegateDynamicInvokeThunk(DelegateInfo delegateInfo)
- {
- _delegateInfo = delegateInfo;
- }
-
- public override TypeSystemContext Context
- {
- get
- {
- return _delegateInfo.Type.Context;
- }
- }
-
- public override TypeDesc OwningType
- {
- get
- {
- return _delegateInfo.Type;
- }
- }
-
- public override MethodSignature Signature
- {
- get
- {
- if (_signature == null)
- {
- _signature = new MethodSignature(0, 0,
- Context.GetWellKnownType(WellKnownType.Object),
- new TypeDesc[] {
- Context.GetWellKnownType(WellKnownType.Object),
- Context.GetWellKnownType(WellKnownType.IntPtr),
- ArgSetupStateType.MakeByRefType() });
- }
- return _signature;
- }
- }
-
- public override Instantiation Instantiation
- {
- get
- {
- return Instantiation.Empty;
- }
- }
-
- public override string Name
- {
- get
- {
- return "DynamicInvokeImpl";
- }
- }
-
- private MetadataType InvokeUtilsType
- {
- get
- {
- return Context.SystemModule.GetKnownType("System", "InvokeUtils");
- }
- }
-
- private MetadataType ArgSetupStateType
- {
- get
- {
- return InvokeUtilsType.GetNestedType("ArgSetupState");
- }
- }
-
- public override MethodIL EmitIL()
- {
- ILEmitter emitter = new ILEmitter();
- ILCodeStream argSetupStream = emitter.NewCodeStream();
- ILCodeStream callSiteSetupStream = emitter.NewCodeStream();
-
- // This function will look like
- //
- // !For each parameter to the delegate
- // !if (parameter is In Parameter)
- // localX is TypeOfParameterX&
- // ldtoken TypeOfParameterX
- // call DynamicInvokeParamHelperIn(RuntimeTypeHandle)
- // stloc localX
- // !else
- // localX is TypeOfParameter
- // ldtoken TypeOfParameterX
- // call DynamicInvokeParamHelperRef(RuntimeTypeHandle)
- // stloc localX
-
- // ldarg.3
- // call DynamicInvokeArgSetupComplete(ref ArgSetupState)
-
- // *** Second instruction stream starts here ***
-
- // ldarg.1 // Load this pointer
- // !For each parameter
- // !if (parameter is In Parameter)
- // ldloc localX
- // ldobj TypeOfParameterX
- // !else
- // ldloc localX
- // ldarg.1
- // calli ReturnType thiscall(TypeOfParameter1, ...)
- // !if ((ReturnType == void)
- // ldnull
- // !else if (ReturnType is a byref)
- // ldobj StripByRef(ReturnType)
- // box StripByRef(ReturnType)
- // !else
- // box ReturnType
- // ret
-
- callSiteSetupStream.EmitLdArg(1);
-
- MethodSignature delegateSignature = _delegateInfo.Signature;
-
- TypeDesc[] targetMethodParameters = new TypeDesc[delegateSignature.Length];
-
- for (int paramIndex = 0; paramIndex < delegateSignature.Length; paramIndex++)
- {
- TypeDesc paramType = delegateSignature[paramIndex];
- TypeDesc localType = paramType;
-
- targetMethodParameters[paramIndex] = paramType;
-
- if (localType.IsByRef)
- {
- // Strip ByRef
- localType = ((ByRefType)localType).ParameterType;
- }
- else
- {
- // Only if this is not a ByRef, convert the parameter type to something boxable.
- // Everything but pointer types are boxable.
- localType = ConvertToBoxableType(localType);
- }
-
- ILLocalVariable local = emitter.NewLocal(localType.MakeByRefType());
-
- callSiteSetupStream.EmitLdLoc(local);
-
- argSetupStream.Emit(ILOpcode.ldtoken, emitter.NewToken(localType));
-
- if (paramType.IsByRef)
- {
- argSetupStream.Emit(ILOpcode.call, emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeParamHelperRef", null)));
- }
- else
- {
- argSetupStream.Emit(ILOpcode.call, emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeParamHelperIn", null)));
-
- callSiteSetupStream.Emit(ILOpcode.ldobj, emitter.NewToken(paramType));
- }
- argSetupStream.EmitStLoc(local);
- }
-
- argSetupStream.EmitLdArg(3);
- argSetupStream.Emit(ILOpcode.call, emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeArgSetupComplete", null)));
-
- callSiteSetupStream.EmitLdArg(2);
-
- MethodSignature targetMethodSig = new MethodSignature(0, 0, delegateSignature.ReturnType, targetMethodParameters);
-
- callSiteSetupStream.Emit(ILOpcode.calli, emitter.NewToken(targetMethodSig));
-
- if (delegateSignature.ReturnType.IsVoid)
- {
- callSiteSetupStream.Emit(ILOpcode.ldnull);
- }
- else if (delegateSignature.ReturnType.IsByRef)
- {
- TypeDesc targetType = ((ByRefType)delegateSignature.ReturnType).ParameterType;
- callSiteSetupStream.Emit(ILOpcode.ldobj, emitter.NewToken(targetType));
- callSiteSetupStream.Emit(ILOpcode.box, emitter.NewToken(targetType));
- }
- else
- {
- callSiteSetupStream.Emit(ILOpcode.box, emitter.NewToken(delegateSignature.ReturnType));
- }
-
- callSiteSetupStream.Emit(ILOpcode.ret);
-
- return emitter.Link(this);
- }
-
- internal static TypeDesc ConvertToBoxableType(TypeDesc type)
- {
- if (type.IsPointer || type.IsFunctionPointer)
- {
- return type.Context.GetWellKnownType(WellKnownType.IntPtr);
- }
-
- return type;
- }
- }
-
- /// <summary>
/// Synthetic method override of "IntPtr Delegate.GetThunk(Int32)". This method is injected
/// into all delegate types and provides means for System.Delegate to access the various thunks
/// generated by the compiler.
@@ -939,7 +738,25 @@ namespace Internal.IL.Stubs
{
codeStream.EmitLabel(labels[(int)i]);
- codeStream.Emit(ILOpcode.ldftn, emitter.NewToken(thunk.InstantiateAsOpen()));
+ if (i == DelegateThunkKind.DelegateInvokeThunk)
+ {
+ // Dynamic invoke thunk is special since we're calling into a shared helper
+ MethodDesc targetMethod;
+ if (thunk.HasInstantiation)
+ {
+ TypeDesc[] inst = DynamicInvokeMethodThunk.GetThunkInstantiationForMethod(_delegateInfo.Type.InstantiateAsOpen().GetMethod("Invoke", null));
+ targetMethod = Context.GetInstantiatedMethod(thunk, new Instantiation(inst));
+ }
+ else
+ {
+ targetMethod = thunk;
+ }
+ codeStream.Emit(ILOpcode.ldftn, emitter.NewToken(targetMethod));
+ }
+ else
+ {
+ codeStream.Emit(ILOpcode.ldftn, emitter.NewToken(thunk.InstantiateAsOpen()));
+ }
codeStream.Emit(ILOpcode.ret);
}
}
diff --git a/src/Common/src/TypeSystem/IL/Stubs/DynamicInvokeMethodThunk.Sorting.cs b/src/Common/src/TypeSystem/IL/Stubs/DynamicInvokeMethodThunk.Sorting.cs
index 990433113..d9c937f05 100644
--- a/src/Common/src/TypeSystem/IL/Stubs/DynamicInvokeMethodThunk.Sorting.cs
+++ b/src/Common/src/TypeSystem/IL/Stubs/DynamicInvokeMethodThunk.Sorting.cs
@@ -12,9 +12,9 @@ namespace Internal.IL.Stubs
// Functionality related to determinstic ordering of types
partial class DynamicInvokeMethodThunk
{
- protected override int ClassCode => -1980933220;
+ protected internal override int ClassCode => -1980933220;
- protected override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer)
+ protected internal override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer)
{
return CompareTo((DynamicInvokeMethodThunk)other);
}
@@ -25,13 +25,23 @@ namespace Internal.IL.Stubs
if (result != 0)
return result;
- result = (_targetSignature.HasReturnValue ? 1 : 0) - (otherMethod._targetSignature.HasReturnValue ? 1 : 0);
+ DynamicInvokeMethodParameterKind thisReturnType = _targetSignature.ReturnType;
+ result = (int)thisReturnType - (int)otherMethod._targetSignature.ReturnType;
+ if (result != 0)
+ return result;
+
+ result = _targetSignature.GetNumerOfReturnTypePointerIndirections() - otherMethod._targetSignature.GetNumerOfReturnTypePointerIndirections();
if (result != 0)
return result;
for (int i = 0; i < _targetSignature.Length; i++)
{
- result = (int)_targetSignature[i] - (int)otherMethod._targetSignature[i];
+ DynamicInvokeMethodParameterKind thisParamType = _targetSignature[i];
+ result = (int)thisParamType - (int)otherMethod._targetSignature[i];
+ if (result != 0)
+ return result;
+
+ result = _targetSignature.GetNumberOfParameterPointerIndirections(i) - otherMethod._targetSignature.GetNumberOfParameterPointerIndirections(i);
if (result != 0)
return result;
}
@@ -42,9 +52,9 @@ namespace Internal.IL.Stubs
partial class DynamicInvokeThunkGenericParameter
{
- protected override int ClassCode => -234393261;
+ protected internal override int ClassCode => -234393261;
- protected override int CompareToImpl(TypeDesc other, TypeSystemComparer comparer)
+ protected internal override int CompareToImpl(TypeDesc other, TypeSystemComparer comparer)
{
var otherType = (DynamicInvokeThunkGenericParameter)other;
int result = Index - otherType.Index;
@@ -55,4 +65,4 @@ namespace Internal.IL.Stubs
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/Common/src/TypeSystem/IL/Stubs/DynamicInvokeMethodThunk.cs b/src/Common/src/TypeSystem/IL/Stubs/DynamicInvokeMethodThunk.cs
index 68c89d880..510b300c5 100644
--- a/src/Common/src/TypeSystem/IL/Stubs/DynamicInvokeMethodThunk.cs
+++ b/src/Common/src/TypeSystem/IL/Stubs/DynamicInvokeMethodThunk.cs
@@ -18,7 +18,7 @@ namespace Internal.IL.Stubs
/// dependencies on the general dynamic invocation infrastructure in System.InvokeUtils and gets called from there
/// at runtime. See comments in System.InvokeUtils for a more thorough explanation.
/// </summary>
- internal partial class DynamicInvokeMethodThunk : ILStubMethod
+ public partial class DynamicInvokeMethodThunk : ILStubMethod
{
private TypeDesc _owningType;
private DynamicInvokeMethodSignature _targetSignature;
@@ -32,11 +32,127 @@ namespace Internal.IL.Stubs
_targetSignature = signature;
}
- public static bool SupportsThunks(TypeSystemContext context)
+ internal static bool SupportsDynamicInvoke(TypeSystemContext context)
{
return context.SystemModule.GetType("System", "InvokeUtils", false) != null;
}
+ private static TypeDesc UnwrapByRef(TypeDesc type)
+ {
+ if (type.IsByRef)
+ return ((ByRefType)type).ParameterType;
+ return type;
+ }
+
+ public static bool SupportsSignature(MethodSignature signature)
+ {
+ // ----------------------------------------------------------------
+ // TODO: function pointer types are odd: https://github.com/dotnet/corert/issues/1929
+ // ----------------------------------------------------------------
+
+ if (UnwrapByRef(signature.ReturnType).IsFunctionPointer)
+ return false;
+
+ for (int i = 0; i < signature.Length; i++)
+ if (UnwrapByRef(signature[i]).IsFunctionPointer)
+ return false;
+
+ // ----------------------------------------------------------------
+ // Methods that return ByRef-like types or take them by reference can't be reflection invoked
+ // ----------------------------------------------------------------
+
+ if (!signature.ReturnType.IsSignatureVariable && UnwrapByRef(signature.ReturnType).IsByRefLike)
+ return false;
+
+ for (int i = 0; i < signature.Length; i++)
+ {
+ ByRefType paramType = signature[i] as ByRefType;
+ if (paramType != null && !paramType.ParameterType.IsSignatureVariable && UnwrapByRef(paramType.ParameterType).IsByRefLike)
+ return false;
+ }
+
+ return true;
+ }
+
+ public static TypeDesc[] GetThunkInstantiationForMethod(MethodDesc method)
+ {
+ MethodSignature sig = method.Signature;
+
+ ParameterMetadata[] paramMetadata = null;
+ TypeDesc[] instantiation = new TypeDesc[sig.ReturnType.IsVoid ? sig.Length : sig.Length + 1];
+
+ for (int i = 0; i < sig.Length; i++)
+ {
+ TypeDesc parameterType = sig[i];
+ if (parameterType.IsByRef)
+ {
+ // strip ByRefType off the parameter (the method already has ByRef in the signature)
+ parameterType = ((ByRefType)parameterType).ParameterType;
+
+ // Strip off all the pointers. Pointers are not valid instantiation arguments and the thunk compensates for that
+ // by being specialized for the specific pointer depth.
+ while (parameterType.IsPointer)
+ parameterType = ((PointerType)parameterType).ParameterType;
+ }
+ else if (parameterType.IsPointer)
+ {
+ // Strip off all the pointers. Pointers are not valid instantiation arguments and the thunk compensates for that
+ // by being specialized for the specific pointer depth.
+ while (parameterType.IsPointer)
+ parameterType = ((PointerType)parameterType).ParameterType;
+ }
+ else if (parameterType.IsEnum)
+ {
+ // If the invoke method takes an enum as an input parameter and there is no default value for
+ // that paramter, we don't need to specialize on the exact enum type (we only need to specialize
+ // on the underlying integral type of the enum.)
+ if (paramMetadata == null)
+ paramMetadata = method.GetParameterMetadata();
+
+ bool hasDefaultValue = false;
+ foreach (var p in paramMetadata)
+ {
+ // Parameter metadata indexes are 1-based (0 is reserved for return "parameter")
+ if (p.Index == (i + 1) && p.HasDefault)
+ {
+ hasDefaultValue = true;
+ break;
+ }
+ }
+
+ if (!hasDefaultValue)
+ parameterType = parameterType.UnderlyingType;
+ }
+
+ instantiation[i] = parameterType;
+ }
+
+ if (!sig.ReturnType.IsVoid)
+ {
+ TypeDesc returnType = sig.ReturnType;
+
+ // strip ByRefType off the return type (the method already has ByRef in the signature)
+ if (returnType.IsByRef)
+ returnType = ((ByRefType)returnType).ParameterType;
+
+ // If the invoke method return an object reference, we don't need to specialize on the
+ // exact type of the object reference, as the behavior is not different.
+ if ((returnType.IsDefType && !returnType.IsValueType) || returnType.IsArray)
+ {
+ returnType = method.Context.GetWellKnownType(WellKnownType.Object);
+ }
+
+ // Strip off all the pointers. Pointers are not valid instantiation arguments and the thunk compensates for that
+ // by being specialized for the specific pointer depth.
+ while (returnType.IsPointer)
+ returnType = ((PointerType)returnType).ParameterType;
+
+ instantiation[sig.Length] = returnType;
+ }
+
+ return instantiation;
+ }
+
public override TypeSystemContext Context
{
get
@@ -69,6 +185,14 @@ namespace Internal.IL.Stubs
}
}
+ public DynamicInvokeMethodSignature TargetSignature
+ {
+ get
+ {
+ return _targetSignature;
+ }
+ }
+
public override MethodSignature Signature
{
get
@@ -121,13 +245,54 @@ namespace Internal.IL.Stubs
{
StringBuilder sb = new StringBuilder("InvokeRet");
- if (_targetSignature.HasReturnValue)
- sb.Append('O');
- else
- sb.Append('V');
+ switch (_targetSignature.ReturnType)
+ {
+ case DynamicInvokeMethodParameterKind.None:
+ sb.Append('V');
+ break;
+ case DynamicInvokeMethodParameterKind.Pointer:
+ sb.Append('P');
+ for (int i = 0; i < _targetSignature.GetNumerOfReturnTypePointerIndirections() - 1; i++)
+ sb.Append('p');
+ break;
+ case DynamicInvokeMethodParameterKind.Reference:
+ sb.Append("R");
+ for (int i = 0; i < _targetSignature.GetNumerOfReturnTypePointerIndirections(); i++)
+ sb.Append('p');
+ break;
+ case DynamicInvokeMethodParameterKind.Value:
+ sb.Append('O');
+ break;
+ default:
+ Debug.Fail("Unreachable");
+ break;
+ }
for (int i = 0; i < _targetSignature.Length; i++)
- sb.Append(_targetSignature[i] == DynamicInvokeMethodParameterKind.Value ? 'I' : 'R');
+ {
+ switch (_targetSignature[i])
+ {
+ case DynamicInvokeMethodParameterKind.Pointer:
+ sb.Append('P');
+
+ for (int j = 0; j < _targetSignature.GetNumberOfParameterPointerIndirections(i) - 1; j++)
+ sb.Append('p');
+
+ break;
+ case DynamicInvokeMethodParameterKind.Reference:
+ sb.Append("R");
+
+ for (int j = 0; j < _targetSignature.GetNumberOfParameterPointerIndirections(i); j++)
+ sb.Append('p');
+ break;
+ case DynamicInvokeMethodParameterKind.Value:
+ sb.Append("I");
+ break;
+ default:
+ Debug.Fail("Unreachable");
+ break;
+ }
+ }
return sb.ToString();
}
@@ -139,6 +304,7 @@ namespace Internal.IL.Stubs
ILCodeStream argSetupStream = emitter.NewCodeStream();
ILCodeStream thisCallSiteSetupStream = emitter.NewCodeStream();
ILCodeStream staticCallSiteSetupStream = emitter.NewCodeStream();
+ ILCodeStream returnCodeStream = emitter.NewCodeStream();
// This function will look like
//
@@ -171,11 +337,7 @@ namespace Internal.IL.Stubs
// ldloc localX
// ldarg.1
// calli ReturnType thiscall(TypeOfParameter1, ...)
- // !if ((ReturnType == void)
- // ldnull
- // !else
- // box ReturnType
- // ret
+ // br Process_return
// *** Static call instruction stream starts here ***
@@ -188,13 +350,30 @@ namespace Internal.IL.Stubs
// ldloc localX
// ldarg.1
// calli ReturnType (TypeOfParameter1, ...)
+
+ // *** Return code stream starts here ***
+
+ // Process_return:
+ // !if (ReturnType is Byref)
+ // dup
+ // brfalse ByRefNull
+ // ldobj ReturnType
// !if ((ReturnType == void)
// ldnull
+ // !elif (ReturnType is pointer)
+ // System.Reflection.Pointer.Box(ReturnType)
// !else
// box ReturnType
// ret
+ //
+ // !if (ReturnType is ByRef)
+ // ByRefNull:
+ // pop
+ // call InvokeUtils.get_NullByRefValueSentinel
+ // ret
ILCodeLabel lStaticCall = emitter.NewCodeLabel();
+ ILCodeLabel lProcessReturn = emitter.NewCodeLabel();
thisCallSiteSetupStream.EmitLdArg(3); // targetIsThisCall
thisCallSiteSetupStream.Emit(ILOpcode.brfalse, lStaticCall);
staticCallSiteSetupStream.EmitLabel(lStaticCall);
@@ -211,6 +390,11 @@ namespace Internal.IL.Stubs
for (int paramIndex = 0; paramIndex < _targetSignature.Length; paramIndex++)
{
TypeDesc paramType = Context.GetSignatureVariable(paramIndex, true);
+ DynamicInvokeMethodParameterKind paramKind = _targetSignature[paramIndex];
+
+ for (int i = 0; i < _targetSignature.GetNumberOfParameterPointerIndirections(paramIndex); i++)
+ paramType = paramType.MakePointerType();
+
ILToken tokParamType = emitter.NewToken(paramType);
ILLocalVariable local = emitter.NewLocal(paramType.MakeByRefType());
@@ -219,7 +403,7 @@ namespace Internal.IL.Stubs
argSetupStream.Emit(ILOpcode.ldtoken, tokParamType);
- if (_targetSignature[paramIndex] == DynamicInvokeMethodParameterKind.Reference)
+ if (paramKind == DynamicInvokeMethodParameterKind.Reference)
{
argSetupStream.Emit(ILOpcode.call, tokDynamicInvokeParamHelperRef);
@@ -243,30 +427,74 @@ namespace Internal.IL.Stubs
thisCallSiteSetupStream.EmitLdArg(1); // methodToCall
staticCallSiteSetupStream.EmitLdArg(1); // methodToCall
- TypeDesc returnType = _targetSignature.HasReturnValue ?
+ DynamicInvokeMethodParameterKind returnKind = _targetSignature.ReturnType;
+ TypeDesc returnType = returnKind != DynamicInvokeMethodParameterKind.None ?
Context.GetSignatureVariable(_targetSignature.Length, true) :
Context.GetWellKnownType(WellKnownType.Void);
+ for (int i = 0; i < _targetSignature.GetNumerOfReturnTypePointerIndirections(); i++)
+ returnType = returnType.MakePointerType();
+
+ if (returnKind == DynamicInvokeMethodParameterKind.Reference)
+ returnType = returnType.MakeByRefType();
+
MethodSignature thisCallMethodSig = new MethodSignature(0, 0, returnType, targetMethodSignature);
thisCallSiteSetupStream.Emit(ILOpcode.calli, emitter.NewToken(thisCallMethodSig));
+ thisCallSiteSetupStream.Emit(ILOpcode.br, lProcessReturn);
MethodSignature staticCallMethodSig = new MethodSignature(MethodSignatureFlags.Static, 0, returnType, targetMethodSignature);
staticCallSiteSetupStream.Emit(ILOpcode.calli, emitter.NewToken(staticCallMethodSig));
- if (_targetSignature.HasReturnValue)
+ returnCodeStream.EmitLabel(lProcessReturn);
+
+ ILCodeLabel lByRefReturnNull = null;
+
+ if (returnKind == DynamicInvokeMethodParameterKind.None)
{
- ILToken tokReturnType = emitter.NewToken(returnType);
- thisCallSiteSetupStream.Emit(ILOpcode.box, tokReturnType);
- staticCallSiteSetupStream.Emit(ILOpcode.box, tokReturnType);
+ returnCodeStream.Emit(ILOpcode.ldnull);
}
else
{
- thisCallSiteSetupStream.Emit(ILOpcode.ldnull);
- staticCallSiteSetupStream.Emit(ILOpcode.ldnull);
+ TypeDesc returnTypeForBoxing = returnType;
+
+ if (returnType.IsByRef)
+ {
+ // If this is a byref return, we need to dereference first
+ returnTypeForBoxing = ((ByRefType)returnType).ParameterType;
+ lByRefReturnNull = emitter.NewCodeLabel();
+ returnCodeStream.Emit(ILOpcode.dup);
+ returnCodeStream.Emit(ILOpcode.brfalse, lByRefReturnNull);
+ returnCodeStream.Emit(ILOpcode.ldobj, emitter.NewToken(returnTypeForBoxing));
+ }
+
+ if (returnTypeForBoxing.IsPointer)
+ {
+ // Pointers box differently
+ returnCodeStream.Emit(ILOpcode.ldtoken, emitter.NewToken(returnTypeForBoxing));
+ MethodDesc getTypeFromHandleMethod =
+ Context.SystemModule.GetKnownType("System", "Type").GetKnownMethod("GetTypeFromHandle", null);
+ returnCodeStream.Emit(ILOpcode.call, emitter.NewToken(getTypeFromHandleMethod));
+
+ MethodDesc pointerBoxMethod =
+ Context.SystemModule.GetKnownType("System.Reflection", "Pointer").GetKnownMethod("Box", null);
+ returnCodeStream.Emit(ILOpcode.call, emitter.NewToken(pointerBoxMethod));
+ }
+ else
+ {
+ ILToken tokReturnType = emitter.NewToken(returnTypeForBoxing);
+ returnCodeStream.Emit(ILOpcode.box, tokReturnType);
+ }
}
- thisCallSiteSetupStream.Emit(ILOpcode.ret);
- staticCallSiteSetupStream.Emit(ILOpcode.ret);
+ returnCodeStream.Emit(ILOpcode.ret);
+
+ if (lByRefReturnNull != null)
+ {
+ returnCodeStream.EmitLabel(lByRefReturnNull);
+ returnCodeStream.Emit(ILOpcode.pop);
+ returnCodeStream.Emit(ILOpcode.call, emitter.NewToken(InvokeUtilsType.GetKnownMethod("get_NullByRefValueSentinel", null)));
+ returnCodeStream.Emit(ILOpcode.ret);
+ }
return emitter.Link(this);
}
@@ -309,15 +537,18 @@ namespace Internal.IL.Stubs
None,
Value,
Reference,
+ Pointer,
}
/// <summary>
/// Wraps a <see cref="MethodSignature"/> to reduce it's fidelity.
/// </summary>
- internal struct DynamicInvokeMethodSignature : IEquatable<DynamicInvokeMethodSignature>
+ public struct DynamicInvokeMethodSignature : IEquatable<DynamicInvokeMethodSignature>
{
private MethodSignature _signature;
+ public TypeSystemContext Context => _signature.ReturnType.Context;
+
public bool HasReturnValue
{
get
@@ -334,21 +565,66 @@ namespace Internal.IL.Stubs
}
}
- public DynamicInvokeMethodParameterKind this[int index]
+ internal DynamicInvokeMethodParameterKind this[int index]
{
get
{
- return _signature[index].IsByRef ?
- DynamicInvokeMethodParameterKind.Reference :
- DynamicInvokeMethodParameterKind.Value;
+ TypeDesc type = _signature[index];
+
+ if (type.IsByRef)
+ return DynamicInvokeMethodParameterKind.Reference;
+ else if (type.IsPointer)
+ return DynamicInvokeMethodParameterKind.Pointer;
+ else
+ return DynamicInvokeMethodParameterKind.Value;
+ }
+ }
+
+ public static int GetNumberOfIndirections(TypeDesc type)
+ {
+ // Strip byrefness off. This is to support "ref void**"-style signatures.
+ if (type.IsByRef)
+ type = ((ByRefType)type).ParameterType;
+
+ int result = 0;
+ while (type.IsPointer)
+ {
+ result++;
+ type = ((PointerType)type).ParameterType;
+ }
+
+ return result;
+ }
+
+ public int GetNumberOfParameterPointerIndirections(int paramIndex)
+ {
+ return GetNumberOfIndirections(_signature[paramIndex]);
+ }
+
+ public int GetNumerOfReturnTypePointerIndirections()
+ {
+ return GetNumberOfIndirections(_signature.ReturnType);
+ }
+
+ internal DynamicInvokeMethodParameterKind ReturnType
+ {
+ get
+ {
+ TypeDesc type = _signature.ReturnType;
+ if (type.IsPointer)
+ return DynamicInvokeMethodParameterKind.Pointer;
+ else if (type.IsVoid)
+ return DynamicInvokeMethodParameterKind.None;
+ else if (type.IsByRef)
+ return DynamicInvokeMethodParameterKind.Reference;
+ else
+ return DynamicInvokeMethodParameterKind.Value;
}
}
public DynamicInvokeMethodSignature(MethodSignature concreteSignature)
{
- // ByRef returns should have been filtered out elsewhere. We don't handle them
- // because reflection can't invoke such methods.
- Debug.Assert(!concreteSignature.ReturnType.IsByRef);
+ Debug.Assert(DynamicInvokeMethodThunk.SupportsSignature(concreteSignature));
_signature = concreteSignature;
}
@@ -359,7 +635,7 @@ namespace Internal.IL.Stubs
public override int GetHashCode()
{
- int hashCode = HasReturnValue ? 17 : 23;
+ int hashCode = (int)this.ReturnType * 0x5498341 + 0x832424;
for (int i = 0; i < Length; i++)
{
@@ -372,7 +648,11 @@ namespace Internal.IL.Stubs
public bool Equals(DynamicInvokeMethodSignature other)
{
- if (HasReturnValue != other.HasReturnValue)
+ DynamicInvokeMethodParameterKind thisReturnKind = ReturnType;
+ if (thisReturnKind != other.ReturnType)
+ return false;
+
+ if (GetNumerOfReturnTypePointerIndirections() != other.GetNumerOfReturnTypePointerIndirections())
return false;
if (Length != other.Length)
@@ -380,7 +660,11 @@ namespace Internal.IL.Stubs
for (int i = 0; i < Length; i++)
{
- if (this[i] != other[i])
+ DynamicInvokeMethodParameterKind thisParamKind = this[i];
+ if (thisParamKind != other[i])
+ return false;
+
+ if (GetNumberOfParameterPointerIndirections(i) != other.GetNumberOfParameterPointerIndirections(i))
return false;
}
diff --git a/src/Common/src/TypeSystem/IL/Stubs/ILEmitter.cs b/src/Common/src/TypeSystem/IL/Stubs/ILEmitter.cs
index 042636f41..45627bd1d 100644
--- a/src/Common/src/TypeSystem/IL/Stubs/ILEmitter.cs
+++ b/src/Common/src/TypeSystem/IL/Stubs/ILEmitter.cs
@@ -253,6 +253,8 @@ namespace Internal.IL.Stubs
break;
case TypeFlags.ValueType:
case TypeFlags.Nullable:
+ case TypeFlags.SignatureMethodVariable:
+ case TypeFlags.SignatureTypeVariable:
Emit(ILOpcode.ldobj, _emitter.NewToken(type));
break;
default:
diff --git a/src/Common/src/TypeSystem/IL/Stubs/PInvokeILEmitter.cs b/src/Common/src/TypeSystem/IL/Stubs/PInvokeILEmitter.cs
index fa503b742..7620bda5b 100644
--- a/src/Common/src/TypeSystem/IL/Stubs/PInvokeILEmitter.cs
+++ b/src/Common/src/TypeSystem/IL/Stubs/PInvokeILEmitter.cs
@@ -40,12 +40,10 @@ namespace Internal.IL.Stubs
// targetMethod could be either a PInvoke or a DelegateMarshallingMethodThunk
// ForwardNativeFunctionWrapper method thunks are marked as PInvokes, so it is
// important to check them first here so that we get the right flags.
- //
- DelegateMarshallingMethodThunk delegateThunk = _targetMethod as DelegateMarshallingMethodThunk;
-
- if (delegateThunk != null)
+ //
+ if (_targetMethod is DelegateMarshallingMethodThunk delegateMethod)
{
- _flags = ((EcmaType)delegateThunk.DelegateType).GetDelegatePInvokeFlags();
+ _flags = ((EcmaType)delegateMethod.DelegateType).GetDelegatePInvokeFlags();
}
else
{
@@ -57,9 +55,21 @@ namespace Internal.IL.Stubs
private static Marshaller[] InitializeMarshallers(MethodDesc targetMethod, InteropStateManager interopStateManager, PInvokeFlags flags)
{
- bool isDelegate = targetMethod is DelegateMarshallingMethodThunk;
- MethodSignature methodSig = isDelegate ? ((DelegateMarshallingMethodThunk)targetMethod).DelegateSignature : targetMethod.Signature;
- MarshalDirection direction = isDelegate ? ((DelegateMarshallingMethodThunk)targetMethod).Direction: MarshalDirection.Forward;
+ MarshalDirection direction = MarshalDirection.Forward;
+ MethodSignature methodSig;
+ switch (targetMethod)
+ {
+ case DelegateMarshallingMethodThunk delegateMethod:
+ methodSig = delegateMethod.DelegateSignature;
+ direction = delegateMethod.Direction;
+ break;
+ case CalliMarshallingMethodThunk calliMethod:
+ methodSig = calliMethod.TargetSignature;
+ break;
+ default:
+ methodSig = targetMethod.Signature;
+ break;
+ }
int indexOffset = 0;
if (!methodSig.IsStatic && direction == MarshalDirection.Forward)
{
@@ -282,6 +292,27 @@ namespace Internal.IL.Stubs
}
}
+ private void EmitCalli(PInvokeILCodeStreams ilCodeStreams, CalliMarshallingMethodThunk calliThunk)
+ {
+ ILEmitter emitter = ilCodeStreams.Emitter;
+ ILCodeStream callsiteSetupCodeStream = ilCodeStreams.CallsiteSetupCodeStream;
+
+ TypeDesc nativeReturnType = _marshallers[0].NativeParameterType;
+ TypeDesc[] nativeParameterTypes = new TypeDesc[_marshallers.Length - 1];
+
+ for (int i = 1; i < _marshallers.Length; i++)
+ {
+ nativeParameterTypes[i - 1] = _marshallers[i].NativeParameterType;
+ }
+
+ MethodSignature nativeSig = new MethodSignature(
+ calliThunk.TargetSignature.Flags, 0, nativeReturnType,
+ nativeParameterTypes);
+
+ callsiteSetupCodeStream.EmitLdArg(calliThunk.TargetSignature.Length);
+ callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(nativeSig));
+ }
+
private MethodIL EmitIL()
{
PInvokeILCodeStreams pInvokeILCodeStreams = new PInvokeILCodeStreams();
@@ -295,20 +326,23 @@ namespace Internal.IL.Stubs
}
// make the call
- DelegateMarshallingMethodThunk delegateMethod = _targetMethod as DelegateMarshallingMethodThunk;
- if (delegateMethod != null)
- {
- EmitDelegateCall(delegateMethod, pInvokeILCodeStreams);
- }
- else
+ switch (_targetMethod)
{
- EmitPInvokeCall(pInvokeILCodeStreams);
+ case DelegateMarshallingMethodThunk delegateMethod:
+ EmitDelegateCall(delegateMethod, pInvokeILCodeStreams);
+ break;
+ case CalliMarshallingMethodThunk calliMethod:
+ EmitCalli(pInvokeILCodeStreams, calliMethod);
+ break;
+ default:
+ EmitPInvokeCall(pInvokeILCodeStreams);
+ break;
}
_marshallers[0].LoadReturnValue(unmarshallingCodestream);
unmarshallingCodestream.Emit(ILOpcode.ret);
- return new PInvokeILStubMethodIL((ILStubMethodIL)emitter.Link(_targetMethod), IsStubRequired());
+ return new PInvokeILStubMethodIL((ILStubMethodIL)emitter.Link(_targetMethod), IsStubRequired());
}
public static MethodIL EmitIL(MethodDesc method,
@@ -342,11 +376,14 @@ namespace Internal.IL.Stubs
return true;
}
- if (MarshalHelpers.UseLazyResolution(_targetMethod, _importMetadata.Module,
- _pInvokeILEmitterConfiguration))
+ if (_pInvokeILEmitterConfiguration != null)
{
- return true;
+ if (MarshalHelpers.UseLazyResolution(_targetMethod, _importMetadata.Module, _pInvokeILEmitterConfiguration))
+ {
+ return true;
+ }
}
+
if (_flags.SetLastError)
{
return true;
diff --git a/src/Common/src/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs b/src/Common/src/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs
index 650b244c1..dd4f182de 100644
--- a/src/Common/src/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs
+++ b/src/Common/src/TypeSystem/IL/Stubs/PInvokeLazyFixupField.cs
@@ -109,5 +109,13 @@ namespace Internal.IL.Stubs
{
return false;
}
+
+ public override string Name
+ {
+ get
+ {
+ return _targetMethod.Name;
+ }
+ }
}
}
diff --git a/src/Common/src/TypeSystem/IL/Stubs/PInvokeTargetNativeMethod.cs b/src/Common/src/TypeSystem/IL/Stubs/PInvokeTargetNativeMethod.cs
index 2a2cae4e8..5aab575a2 100644
--- a/src/Common/src/TypeSystem/IL/Stubs/PInvokeTargetNativeMethod.cs
+++ b/src/Common/src/TypeSystem/IL/Stubs/PInvokeTargetNativeMethod.cs
@@ -72,6 +72,15 @@ namespace Internal.IL.Stubs
}
}
+ public override bool IsNoInlining
+ {
+ get
+ {
+ // This method does not have real IL body. NoInlining stops the JIT asking for it.
+ return true;
+ }
+ }
+
public override PInvokeMetadata GetPInvokeMethodMetadata()
{
return _declMethod.GetPInvokeMethodMetadata();
diff --git a/src/Common/src/TypeSystem/IL/Stubs/StructMarshallingThunk.cs b/src/Common/src/TypeSystem/IL/Stubs/StructMarshallingThunk.cs
index 6625e3b9a..e5360b37c 100644
--- a/src/Common/src/TypeSystem/IL/Stubs/StructMarshallingThunk.cs
+++ b/src/Common/src/TypeSystem/IL/Stubs/StructMarshallingThunk.cs
@@ -14,7 +14,7 @@ namespace Internal.IL.Stubs
public enum StructMarshallingThunkType : byte
{
ManagedToNative = 1,
- NativeToManage = 2,
+ NativeToManaged = 2,
Cleanup = 4
}
@@ -72,19 +72,29 @@ namespace Internal.IL.Stubs
{
if (_signature == null)
{
- TypeDesc[] parameters;
- if (ThunkType == StructMarshallingThunkType.Cleanup)
+ TypeDesc[] parameters = null;
+ switch (ThunkType)
{
- parameters = new TypeDesc[] {
- NativeType.MakeByRefType()
- };
- }
- else
- {
- parameters = new TypeDesc[] {
- ManagedType.MakeByRefType(),
- NativeType.MakeByRefType()
- };
+ case StructMarshallingThunkType.ManagedToNative:
+ parameters = new TypeDesc[] {
+ ManagedType.IsValueType ? (TypeDesc)ManagedType.MakeByRefType() : ManagedType,
+ NativeType.MakeByRefType()
+ };
+ break;
+ case StructMarshallingThunkType.NativeToManaged:
+ parameters = new TypeDesc[] {
+ NativeType.MakeByRefType(),
+ ManagedType.IsValueType ? (TypeDesc)ManagedType.MakeByRefType() : ManagedType
+ };
+ break;
+ case StructMarshallingThunkType.Cleanup:
+ parameters = new TypeDesc[] {
+ NativeType.MakeByRefType()
+ };
+ break;
+ default:
+ System.Diagnostics.Debug.Fail("Unexpected Struct marshalling thunk type");
+ break;
}
_signature = new MethodSignature(MethodSignatureFlags.Static, 0, Context.GetWellKnownType(WellKnownType.Void), parameters);
}
@@ -100,7 +110,7 @@ namespace Internal.IL.Stubs
{
case StructMarshallingThunkType.ManagedToNative:
return "ManagedToNative";
- case StructMarshallingThunkType.NativeToManage:
+ case StructMarshallingThunkType.NativeToManaged:
return "NativeToManaged";
case StructMarshallingThunkType.Cleanup:
return "Cleanup";
@@ -147,7 +157,7 @@ namespace Internal.IL.Stubs
marshallers[index] = Marshaller.CreateMarshaller(field.FieldType,
MarshallerType.Field,
marshalAsDescriptors[index],
- (ThunkType == StructMarshallingThunkType.NativeToManage) ? MarshalDirection.Reverse : MarshalDirection.Forward,
+ (ThunkType == StructMarshallingThunkType.NativeToManaged) ? MarshalDirection.Reverse : MarshalDirection.Forward,
marshallers,
_interopStateManager,
index,
@@ -204,9 +214,9 @@ namespace Internal.IL.Stubs
{
LoadFieldValueFromArg(0, managedField, pInvokeILCodeStreams);
}
- else if (ThunkType == StructMarshallingThunkType.NativeToManage)
+ else if (ThunkType == StructMarshallingThunkType.NativeToManaged)
{
- LoadFieldValueFromArg(1, nativeField, pInvokeILCodeStreams);
+ LoadFieldValueFromArg(0, nativeField, pInvokeILCodeStreams);
}
_marshallers[index++].EmitMarshallingIL(pInvokeILCodeStreams);
@@ -215,9 +225,9 @@ namespace Internal.IL.Stubs
{
StoreFieldValueFromArg(1, nativeField, pInvokeILCodeStreams);
}
- else if (ThunkType == StructMarshallingThunkType.NativeToManage)
+ else if (ThunkType == StructMarshallingThunkType.NativeToManaged)
{
- StoreFieldValueFromArg(0, managedField, pInvokeILCodeStreams);
+ StoreFieldValueFromArg(1, managedField, pInvokeILCodeStreams);
}
}
}
diff --git a/src/Common/src/TypeSystem/IL/TypeSystemContext.DelegateInfo.cs b/src/Common/src/TypeSystem/IL/TypeSystemContext.DelegateInfo.cs
index 4f186e219..a835b47d0 100644
--- a/src/Common/src/TypeSystem/IL/TypeSystemContext.DelegateInfo.cs
+++ b/src/Common/src/TypeSystem/IL/TypeSystemContext.DelegateInfo.cs
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Collections.Generic;
using Internal.IL;
@@ -13,6 +12,10 @@ namespace Internal.TypeSystem
{
private class DelegateInfoHashtable : LockFreeReaderHashtable<TypeDesc, DelegateInfo>
{
+ private enum CoreLibSupportLevel { Unknown, Supported, Unsupported }
+
+ private CoreLibSupportLevel _supportLevel;
+
protected override int GetKeyHashCode(TypeDesc key)
{
return key.GetHashCode();
@@ -31,7 +34,18 @@ namespace Internal.TypeSystem
}
protected override DelegateInfo CreateValueFromKey(TypeDesc key)
{
- return new DelegateInfo(key);
+ if (_supportLevel == CoreLibSupportLevel.Unknown)
+ {
+ // Check if the core library supports dynamic invoke.
+ _supportLevel = DelegateInfo.SupportsDynamicInvoke(key.Context) ?
+ CoreLibSupportLevel.Supported : CoreLibSupportLevel.Unsupported;
+ }
+
+ DelegateFeature supportedFeatures = _supportLevel == CoreLibSupportLevel.Supported ?
+ DelegateFeature.DynamicInvoke | DelegateFeature.ObjectArrayThunk : 0;
+
+
+ return new DelegateInfo(key, supportedFeatures);
}
}
diff --git a/src/Common/src/TypeSystem/IL/TypeSystemContext.DynamicInvoke.cs b/src/Common/src/TypeSystem/IL/TypeSystemContext.DynamicInvoke.cs
new file mode 100644
index 000000000..cdad3d9ef
--- /dev/null
+++ b/src/Common/src/TypeSystem/IL/TypeSystemContext.DynamicInvoke.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.IL.Stubs;
+
+using Debug = System.Diagnostics.Debug;
+
+namespace Internal.TypeSystem
+{
+ partial class TypeSystemContext
+ {
+ private class DynamicInvokeThunkHashtable : LockFreeReaderHashtable<DynamicInvokeMethodSignature, DynamicInvokeMethodThunk>
+ {
+ protected override bool CompareKeyToValue(DynamicInvokeMethodSignature key, DynamicInvokeMethodThunk value) => key.Equals(value.TargetSignature);
+ protected override bool CompareValueToValue(DynamicInvokeMethodThunk value1, DynamicInvokeMethodThunk value2) => value1.TargetSignature.Equals(value2.TargetSignature) && value1.OwningType == value2.OwningType;
+ protected override int GetKeyHashCode(DynamicInvokeMethodSignature key) => key.GetHashCode();
+ protected override int GetValueHashCode(DynamicInvokeMethodThunk value) => value.TargetSignature.GetHashCode();
+ protected override DynamicInvokeMethodThunk CreateValueFromKey(DynamicInvokeMethodSignature key)
+ {
+ return new DynamicInvokeMethodThunk(key.Context.GeneratedAssembly.GetGlobalModuleType(), key);
+ }
+ }
+ DynamicInvokeThunkHashtable _dynamicInvokeThunks = new DynamicInvokeThunkHashtable();
+
+ public MethodDesc GetDynamicInvokeThunk(DynamicInvokeMethodSignature signature)
+ {
+ return _dynamicInvokeThunks.GetOrCreateValue(signature);
+ }
+ }
+}
diff --git a/src/Common/src/TypeSystem/IL/TypeSystemContext.GeneratedAssembly.Sorting.cs b/src/Common/src/TypeSystem/IL/TypeSystemContext.GeneratedAssembly.Sorting.cs
new file mode 100644
index 000000000..5c3301262
--- /dev/null
+++ b/src/Common/src/TypeSystem/IL/TypeSystemContext.GeneratedAssembly.Sorting.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace Internal.TypeSystem
+{
+ partial class TypeSystemContext
+ {
+ // Functionality related to determinstic ordering of types and members
+ partial class CompilerGeneratedType : MetadataType
+ {
+ protected internal override int ClassCode => -1036681447;
+
+ protected internal override int CompareToImpl(TypeDesc other, TypeSystemComparer comparer)
+ {
+ // Should be a singleton
+ throw new NotSupportedException();
+ }
+ }
+ }
+}
diff --git a/src/Common/src/TypeSystem/IL/TypeSystemContext.GeneratedAssembly.cs b/src/Common/src/TypeSystem/IL/TypeSystemContext.GeneratedAssembly.cs
new file mode 100644
index 000000000..5b3e59616
--- /dev/null
+++ b/src/Common/src/TypeSystem/IL/TypeSystemContext.GeneratedAssembly.cs
@@ -0,0 +1,252 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+
+using TypeHashingAlgorithms = Internal.NativeFormat.TypeHashingAlgorithms;
+using Interlocked = System.Threading.Interlocked;
+using AssemblyName = System.Reflection.AssemblyName;
+using Debug = System.Diagnostics.Debug;
+
+namespace Internal.TypeSystem
+{
+ partial class TypeSystemContext
+ {
+ private ModuleDesc _generatedAssembly;
+
+ public ModuleDesc GeneratedAssembly
+ {
+ get
+ {
+ if (_generatedAssembly == null)
+ {
+ Interlocked.CompareExchange(ref _generatedAssembly, new CompilerGeneratedAssembly(this), null);
+ }
+
+ return _generatedAssembly;
+ }
+ }
+
+ private class CompilerGeneratedAssembly : ModuleDesc, IAssemblyDesc
+ {
+ private MetadataType _globalModuleType;
+
+ public CompilerGeneratedAssembly(TypeSystemContext context)
+ : base(context)
+ {
+ _globalModuleType = new CompilerGeneratedType(this, "<Module>");
+ }
+
+ public override IEnumerable<MetadataType> GetAllTypes()
+ {
+ return Array.Empty<MetadataType>();
+ }
+
+ public override MetadataType GetGlobalModuleType()
+ {
+ return _globalModuleType;
+ }
+
+ public AssemblyName GetName()
+ {
+ return new AssemblyName("System.Private.CompilerGenerated");
+ }
+
+ public override MetadataType GetType(string nameSpace, string name, bool throwIfNotFound = true)
+ {
+ Debug.Fail("Resolving a TypeRef in the compiler generated assembly?");
+
+ if (throwIfNotFound)
+ ThrowHelper.ThrowTypeLoadException(nameSpace, name, this);
+
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// A pseudo-type that owns helper methods generated by the compiler.
+ /// This type should never be allocated (we should never see an EEType for it).
+ /// </summary>
+ internal sealed partial class CompilerGeneratedType : MetadataType
+ {
+ private int _hashcode;
+
+ public CompilerGeneratedType(ModuleDesc module, string name)
+ {
+ Module = module;
+ Name = name;
+ }
+
+ public override TypeSystemContext Context
+ {
+ get
+ {
+ return Module.Context;
+ }
+ }
+
+ public override string Name
+ {
+ get;
+ }
+
+ public override string Namespace
+ {
+ get
+ {
+ return "Internal.CompilerGenerated";
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ if (_hashcode != 0)
+ return _hashcode;
+ return InitializeHashCode();
+ }
+
+ private int InitializeHashCode()
+ {
+ string ns = Namespace;
+ var hashCodeBuilder = new TypeHashingAlgorithms.HashCodeBuilder(ns);
+ if (ns.Length > 0)
+ hashCodeBuilder.Append(".");
+ hashCodeBuilder.Append(Name);
+ _hashcode = hashCodeBuilder.ToHashCode();
+
+ return _hashcode;
+ }
+
+ public override bool IsCanonicalSubtype(CanonicalFormKind policy)
+ {
+ Debug.Assert(!HasInstantiation, "Why is this generic?");
+ return false;
+ }
+
+ protected override TypeFlags ComputeTypeFlags(TypeFlags mask)
+ {
+ return TypeFlags.Class |
+ TypeFlags.HasGenericVarianceComputed |
+ TypeFlags.HasStaticConstructorComputed |
+ TypeFlags.HasFinalizerComputed |
+ TypeFlags.AttributeCacheComputed;
+ }
+
+ public override ClassLayoutMetadata GetClassLayout()
+ {
+ return new ClassLayoutMetadata
+ {
+ Offsets = null,
+ PackingSize = 0,
+ Size = 0,
+ };
+ }
+
+ public override bool HasCustomAttribute(string attributeNamespace, string attributeName)
+ {
+ return false;
+ }
+
+ public override IEnumerable<MetadataType> GetNestedTypes()
+ {
+ return Array.Empty<MetadataType>();
+ }
+
+ public override MetadataType GetNestedType(string name)
+ {
+ return null;
+ }
+
+ protected override MethodImplRecord[] ComputeVirtualMethodImplsForType()
+ {
+ return Array.Empty<MethodImplRecord>();
+ }
+
+ public override MethodImplRecord[] FindMethodsImplWithMatchingDeclName(string name)
+ {
+ return Array.Empty<MethodImplRecord>();
+ }
+
+ public override ModuleDesc Module
+ {
+ get;
+ }
+
+ public override PInvokeStringFormat PInvokeStringFormat
+ {
+ get
+ {
+ return PInvokeStringFormat.AutoClass;
+ }
+ }
+
+ public override bool IsExplicitLayout
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public override bool IsSequentialLayout
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public override bool IsBeforeFieldInit
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public override MetadataType MetadataBaseType
+ {
+ get
+ {
+ // Since this type should never be allocated and only serves the purpose of grouping things,
+ // it can act like a <Module> type and have no base type.
+ return null;
+ }
+ }
+
+ public override bool IsSealed
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ public override bool IsAbstract
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public override DefType ContainingType
+ {
+ get
+ {
+ return null;
+ }
+ }
+
+ public override DefType[] ExplicitlyImplementedInterfaces
+ {
+ get
+ {
+ return Array.Empty<DefType>();
+ }
+ }
+ }
+ }
+}
diff --git a/src/Common/src/TypeSystem/IL/TypeSystemContext.ValueTypeMethods.cs b/src/Common/src/TypeSystem/IL/TypeSystemContext.ValueTypeMethods.cs
index a1487a5ac..0b8b9cfde 100644
--- a/src/Common/src/TypeSystem/IL/TypeSystemContext.ValueTypeMethods.cs
+++ b/src/Common/src/TypeSystem/IL/TypeSystemContext.ValueTypeMethods.cs
@@ -37,9 +37,6 @@ namespace Internal.TypeSystem
{
MethodDesc getFieldHelperMethod = _valueTypeMethodHashtable.GetOrCreateValue((DefType)valueTypeDefinition);
- // Check that System.ValueType has the method we're overriding.
- Debug.Assert(valueTypeDefinition.BaseType.GetMethod(getFieldHelperMethod.Name, null) != null);
-
if (valueType != valueTypeDefinition)
{
yield return GetMethodForInstantiatedType(getFieldHelperMethod, (InstantiatedType)valueType);
diff --git a/src/Common/src/TypeSystem/Interop/IL/InlineArrayType.cs b/src/Common/src/TypeSystem/Interop/IL/InlineArrayType.cs
index d7412081f..6f7c711b0 100644
--- a/src/Common/src/TypeSystem/Interop/IL/InlineArrayType.cs
+++ b/src/Common/src/TypeSystem/Interop/IL/InlineArrayType.cs
@@ -219,7 +219,7 @@ namespace Internal.TypeSystem.Interop
}
flags |= TypeFlags.HasFinalizerComputed;
- flags |= TypeFlags.IsByRefLikeComputed;
+ flags |= TypeFlags.AttributeCacheComputed;
return flags;
}
diff --git a/src/Common/src/TypeSystem/Interop/IL/MarshalHelpers.cs b/src/Common/src/TypeSystem/Interop/IL/MarshalHelpers.cs
index a65a6a3a6..00ba8fda5 100644
--- a/src/Common/src/TypeSystem/Interop/IL/MarshalHelpers.cs
+++ b/src/Common/src/TypeSystem/Interop/IL/MarshalHelpers.cs
@@ -66,8 +66,13 @@ namespace Internal.TypeSystem.Interop
typeDesc = typeDesc.GetParameterType();
}
- if (typeDesc.Category != TypeFlags.ValueType)
+ typeDesc = typeDesc.UnderlyingType;
+
+ // TODO: There are primitive types which require marshalling, such as bool, char.
+ if (typeDesc.IsPrimitive)
+ {
return false;
+ }
MetadataType type = typeDesc as MetadataType;
if (type == null)
diff --git a/src/Common/src/TypeSystem/Interop/IL/Marshaller.cs b/src/Common/src/TypeSystem/Interop/IL/Marshaller.cs
index ef75539f1..d7e88915d 100644
--- a/src/Common/src/TypeSystem/Interop/IL/Marshaller.cs
+++ b/src/Common/src/TypeSystem/Interop/IL/Marshaller.cs
@@ -718,6 +718,9 @@ namespace Internal.TypeSystem.Interop
PropagateToByRefArg(_ilCodeStreams.UnmarshallingCodestream, _managedHome);
}
}
+
+ // TODO This should be in finally block
+ // https://github.com/dotnet/corert/issues/6075
EmitCleanupManaged(_ilCodeStreams.UnmarshallingCodestream);
}
@@ -1634,9 +1637,9 @@ namespace Internal.TypeSystem.Interop
}
- class SafeHandleMarshaller : ReferenceMarshaller
+ class SafeHandleMarshaller : Marshaller
{
- protected override void AllocNativeToManaged(ILCodeStream codeStream)
+ private void AllocSafeHandle(ILCodeStream codeStream)
{
var ctor = ManagedType.GetParameterlessConstructor();
if (ctor == null)
@@ -1651,11 +1654,29 @@ namespace Internal.TypeSystem.Interop
codeStream.Emit(ILOpcode.ldstr, emitter.NewToken(String.Format("'{0}' does not have a default constructor. Subclasses of SafeHandle must have a default constructor to support marshaling a Windows HANDLE into managed code.", name)));
codeStream.Emit(ILOpcode.newobj, emitter.NewToken(exceptionCtor));
codeStream.Emit(ILOpcode.throw_);
+ return;
}
- else
- {
- base.AllocNativeToManaged(codeStream);
- }
+
+ codeStream.Emit(ILOpcode.newobj, _ilCodeStreams.Emitter.NewToken(ctor));
+ }
+
+ protected override void EmitMarshalReturnValueManagedToNative()
+ {
+ ILEmitter emitter = _ilCodeStreams.Emitter;
+ ILCodeStream marshallingCodeStream = _ilCodeStreams.MarshallingCodeStream;
+ ILCodeStream returnValueMarshallingCodeStream = _ilCodeStreams.ReturnValueMarshallingCodeStream;
+
+ SetupArgumentsForReturnValueMarshalling();
+
+ AllocSafeHandle(marshallingCodeStream);
+ StoreManagedValue(marshallingCodeStream);
+
+ StoreNativeValue(returnValueMarshallingCodeStream);
+
+ LoadManagedValue(returnValueMarshallingCodeStream);
+ LoadNativeValue(returnValueMarshallingCodeStream);
+ returnValueMarshallingCodeStream.Emit(ILOpcode.call, emitter.NewToken(
+ InteropTypes.GetSafeHandle(Context).GetKnownMethod("SetHandle", null)));
}
protected override void EmitMarshalArgumentManagedToNative()
@@ -1672,42 +1693,13 @@ namespace Internal.TypeSystem.Interop
PropagateFromByRefArg(marshallingCodeStream, _managedHome);
}
- // TODO: https://github.com/dotnet/corert/issues/3291
- // We don't support [IN,OUT] together yet, either IN or OUT.
- if (Out && In)
- {
- throw new NotSupportedException("Marshalling an argument as both in and out not yet implemented");
- }
-
var safeHandleType = InteropTypes.GetSafeHandle(Context);
- if (Out && IsManagedByRef)
+ if (In)
{
- // 1) If this is an output parameter we need to preallocate a SafeHandle to wrap the new native handle value. We
- // must allocate this before the native call to avoid a failure point when we already have a native resource
- // allocated. We must allocate a new SafeHandle even if we have one on input since both input and output native
- // handles need to be tracked and released by a SafeHandle.
- // 2) Initialize a local IntPtr that will be passed to the native call.
- // 3) After the native call, the new handle value is written into the output SafeHandle and that SafeHandle
- // is propagated back to the caller.
- var vOutValue = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.IntPtr));
- var vSafeHandle = emitter.NewLocal(ManagedType);
- marshallingCodeStream.Emit(ILOpcode.newobj, emitter.NewToken(ManagedType.GetParameterlessConstructor()));
- marshallingCodeStream.EmitStLoc(vSafeHandle);
- _ilCodeStreams.CallsiteSetupCodeStream.EmitLdLoca(vOutValue);
-
- unmarshallingCodeStream.EmitLdLoc(vSafeHandle);
- unmarshallingCodeStream.EmitLdLoc(vOutValue);
- unmarshallingCodeStream.Emit(ILOpcode.call, emitter.NewToken(
- safeHandleType.GetKnownMethod("SetHandle", null)));
-
- unmarshallingCodeStream.EmitLdLoc(vSafeHandle);
- StoreManagedValue(unmarshallingCodeStream);
+ if (IsManagedByRef)
+ PropagateFromByRefArg(marshallingCodeStream, _managedHome);
- PropagateToByRefArg(unmarshallingCodeStream, _managedHome);
- }
- else
- {
var vAddRefed = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Boolean));
LoadManagedValue(marshallingCodeStream);
marshallingCodeStream.EmitLdLoca(vAddRefed);
@@ -1719,44 +1711,56 @@ namespace Internal.TypeSystem.Interop
safeHandleType.GetKnownMethod("DangerousGetHandle", null)));
StoreNativeValue(marshallingCodeStream);
- // TODO: This should be inside finally block and only executed it the handle was addrefed
+ // TODO: This should be inside finally block and only executed if the handle was addrefed
+ // https://github.com/dotnet/corert/issues/6075
LoadManagedValue(unmarshallingCodeStream);
unmarshallingCodeStream.Emit(ILOpcode.call, emitter.NewToken(
safeHandleType.GetKnownMethod("DangerousRelease", null)));
-
- LoadNativeArg(_ilCodeStreams.CallsiteSetupCodeStream);
}
- }
+ if (Out && IsManagedByRef)
+ {
+ // 1) If this is an output parameter we need to preallocate a SafeHandle to wrap the new native handle value. We
+ // must allocate this before the native call to avoid a failure point when we already have a native resource
+ // allocated. We must allocate a new SafeHandle even if we have one on input since both input and output native
+ // handles need to be tracked and released by a SafeHandle.
+ // 2) Initialize a local IntPtr that will be passed to the native call.
+ // 3) After the native call, the new handle value is written into the output SafeHandle and that SafeHandle
+ // is propagated back to the caller.
+ var vSafeHandle = emitter.NewLocal(ManagedType);
+ AllocSafeHandle(marshallingCodeStream);
+ marshallingCodeStream.EmitStLoc(vSafeHandle);
- protected override void TransformNativeToManaged(ILCodeStream codeStream)
- {
- LoadManagedValue(codeStream);
- LoadNativeValue(codeStream);
- codeStream.Emit(ILOpcode.call, _ilCodeStreams.Emitter.NewToken(
- InteropTypes.GetSafeHandle(Context).GetKnownMethod("SetHandle", null)));
- }
- }
+ var lSkipPropagation = emitter.NewCodeLabel();
+ if (In)
+ {
+ // Propagate the value only if it has changed
+ ILLocalVariable vOriginalValue = emitter.NewLocal(NativeType);
+ LoadNativeValue(marshallingCodeStream);
+ marshallingCodeStream.EmitStLoc(vOriginalValue);
+
+ unmarshallingCodeStream.EmitLdLoc(vOriginalValue);
+ LoadNativeValue(unmarshallingCodeStream);
+ unmarshallingCodeStream.Emit(ILOpcode.beq, lSkipPropagation);
+ }
- class ReferenceMarshaller : Marshaller
- {
- protected override void AllocNativeToManaged(ILCodeStream codeStream)
- {
- var emitter = _ilCodeStreams.Emitter;
- var lNull = emitter.NewCodeLabel();
+ unmarshallingCodeStream.EmitLdLoc(vSafeHandle);
+ LoadNativeValue(unmarshallingCodeStream);
+ unmarshallingCodeStream.Emit(ILOpcode.call, emitter.NewToken(
+ safeHandleType.GetKnownMethod("SetHandle", null)));
- // Check for null
- LoadNativeValue(codeStream);
- codeStream.Emit(ILOpcode.brfalse, lNull);
+ unmarshallingCodeStream.EmitLdArg(Index - 1);
+ unmarshallingCodeStream.EmitLdLoc(vSafeHandle);
+ unmarshallingCodeStream.EmitStInd(ManagedType);
- codeStream.Emit(ILOpcode.newobj, emitter.NewToken(
- ManagedType.GetParameterlessConstructor()));
- StoreManagedValue(codeStream);
- codeStream.EmitLabel(lNull);
+ unmarshallingCodeStream.EmitLabel(lSkipPropagation);
+ }
+
+ LoadNativeArg(callsiteCodeStream);
}
}
- class StringBuilderMarshaller : ReferenceMarshaller
+ class StringBuilderMarshaller : Marshaller
{
private bool _isAnsi;
public StringBuilderMarshaller(bool isAnsi)
@@ -1778,6 +1782,21 @@ namespace Internal.TypeSystem.Interop
Context.GetHelperEntryPoint("InteropHelpers", "CoTaskMemFree")));
}
+ protected override void AllocNativeToManaged(ILCodeStream codeStream)
+ {
+ var emitter = _ilCodeStreams.Emitter;
+ var lNull = emitter.NewCodeLabel();
+
+ // Check for null
+ LoadNativeValue(codeStream);
+ codeStream.Emit(ILOpcode.brfalse, lNull);
+
+ codeStream.Emit(ILOpcode.newobj, emitter.NewToken(
+ ManagedType.GetParameterlessConstructor()));
+ StoreManagedValue(codeStream);
+ codeStream.EmitLabel(lNull);
+ }
+
protected override void AllocManagedToNative(ILCodeStream codeStream)
{
ILEmitter emitter = _ilCodeStreams.Emitter;
@@ -1877,8 +1896,8 @@ namespace Internal.TypeSystem.Interop
protected override void TransformNativeToManaged(ILCodeStream codeStream)
{
- LoadManagedAddr(codeStream);
LoadNativeAddr(codeStream);
+ LoadManagedAddr(codeStream);
codeStream.Emit(ILOpcode.call, _ilCodeStreams.Emitter.NewToken(
InteropStateManager.GetStructMarshallingNativeToManagedThunk(ManagedType)));
}
@@ -2072,7 +2091,7 @@ namespace Internal.TypeSystem.Interop
var managedElementType = ((ArrayType)ManagedType).ElementType;
ILLocalVariable vLength = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Int32));
- codeStream.EmitLdArg(0);
+ codeStream.EmitLdArg(1);
// load the length
EmitElementCount(codeStream, MarshalDirection.Reverse);
codeStream.EmitStLoc(vLength);
@@ -2092,13 +2111,13 @@ namespace Internal.TypeSystem.Interop
codeStream.EmitLabel(lLoopHeader);
// load managed type
- codeStream.EmitLdArg(0);
+ codeStream.EmitLdArg(1);
codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(_managedField));
codeStream.EmitLdLoc(vIndex);
// load native type
- codeStream.EmitLdArg(1);
+ codeStream.EmitLdArg(0);
codeStream.Emit(ILOpcode.ldflda, emitter.NewToken(_nativeField));
codeStream.EmitLdLoc(vIndex);
@@ -2172,9 +2191,9 @@ namespace Internal.TypeSystem.Interop
ILEmitter emitter = _ilCodeStreams.Emitter;
ILCodeStream codeStream = _ilCodeStreams.UnmarshallingCodestream;
- codeStream.EmitLdArg(0);
-
codeStream.EmitLdArg(1);
+
+ codeStream.EmitLdArg(0);
codeStream.Emit(ILOpcode.ldflda, emitter.NewToken(_nativeField));
codeStream.Emit(ILOpcode.conv_u);
diff --git a/src/Common/src/TypeSystem/Interop/IL/NativeStructType.cs b/src/Common/src/TypeSystem/Interop/IL/NativeStructType.cs
index 87fb167a6..41b80e191 100644
--- a/src/Common/src/TypeSystem/Interop/IL/NativeStructType.cs
+++ b/src/Common/src/TypeSystem/Interop/IL/NativeStructType.cs
@@ -148,7 +148,6 @@ namespace Internal.TypeSystem.Interop
public NativeStructType(ModuleDesc owningModule, MetadataType managedStructType, InteropStateManager interopStateManager)
{
Debug.Assert(managedStructType.IsTypeDefinition);
- Debug.Assert(managedStructType.IsValueType);
Debug.Assert(!managedStructType.IsGenericDefinition);
Module = owningModule;
@@ -301,7 +300,7 @@ namespace Internal.TypeSystem.Interop
}
flags |= TypeFlags.HasFinalizerComputed;
- flags |= TypeFlags.IsByRefLikeComputed;
+ flags |= TypeFlags.AttributeCacheComputed;
return flags;
}
diff --git a/src/Common/src/TypeSystem/Interop/IL/PInvokeDelegateWrapper.cs b/src/Common/src/TypeSystem/Interop/IL/PInvokeDelegateWrapper.cs
index 3ff100bf4..5d95c8461 100644
--- a/src/Common/src/TypeSystem/Interop/IL/PInvokeDelegateWrapper.cs
+++ b/src/Common/src/TypeSystem/Interop/IL/PInvokeDelegateWrapper.cs
@@ -204,7 +204,7 @@ namespace Internal.TypeSystem.Interop
}
flags |= TypeFlags.HasFinalizerComputed;
- flags |= TypeFlags.IsByRefLikeComputed;
+ flags |= TypeFlags.AttributeCacheComputed;
return flags;
}
diff --git a/src/Common/src/TypeSystem/Interop/InteropStateManager.cs b/src/Common/src/TypeSystem/Interop/InteropStateManager.cs
index aeed8f19a..3e71c1382 100644
--- a/src/Common/src/TypeSystem/Interop/InteropStateManager.cs
+++ b/src/Common/src/TypeSystem/Interop/InteropStateManager.cs
@@ -22,6 +22,7 @@ namespace Internal.TypeSystem
private readonly PInvokeDelegateWrapperHashtable _pInvokeDelegateWrapperHashtable;
private readonly InlineArrayHashTable _inlineArrayHashtable;
private readonly PInvokeLazyFixupFieldHashtable _pInvokeLazyFixupFieldHashtable;
+ private readonly PInvokeCalliHashtable _pInvokeCalliHashtable;
public InteropStateManager(ModuleDesc generatedAssembly)
{
@@ -33,6 +34,7 @@ namespace Internal.TypeSystem
_pInvokeDelegateWrapperHashtable = new PInvokeDelegateWrapperHashtable(this, _generatedAssembly);
_inlineArrayHashtable = new InlineArrayHashTable(this, _generatedAssembly);
_pInvokeLazyFixupFieldHashtable = new PInvokeLazyFixupFieldHashtable(_generatedAssembly.GetGlobalModuleType());
+ _pInvokeCalliHashtable = new PInvokeCalliHashtable(this, _generatedAssembly.GetGlobalModuleType());
}
//
// Delegate Marshalling Stubs
@@ -155,8 +157,7 @@ namespace Internal.TypeSystem
Debug.Assert(managedType is MetadataType);
-
- var methodKey = new StructMarshallingThunkKey((MetadataType)managedType, StructMarshallingThunkType.NativeToManage);
+ var methodKey = new StructMarshallingThunkKey((MetadataType)managedType, StructMarshallingThunkType.NativeToManaged);
return _structMarshallingThunkHashtable.GetOrCreateValue(methodKey);
}
@@ -172,7 +173,6 @@ namespace Internal.TypeSystem
Debug.Assert(managedType is MetadataType);
-
var methodKey = new StructMarshallingThunkKey((MetadataType)managedType, StructMarshallingThunkType.Cleanup);
return _structMarshallingThunkHashtable.GetOrCreateValue(methodKey);
}
@@ -187,6 +187,11 @@ namespace Internal.TypeSystem
return _pInvokeLazyFixupFieldHashtable.GetOrCreateValue(method);
}
+ public MethodDesc GetPInvokeCalliStub(MethodSignature signature)
+ {
+ return _pInvokeCalliHashtable.GetOrCreateValue(signature);
+ }
+
private class NativeStructTypeHashtable : LockFreeReaderHashtable<MetadataType, NativeStructType>
{
protected override int GetKeyHashCode(MetadataType key)
@@ -473,5 +478,42 @@ namespace Internal.TypeSystem
_owningType = owningType;
}
}
+
+ private class PInvokeCalliHashtable : LockFreeReaderHashtable<MethodSignature, CalliMarshallingMethodThunk>
+ {
+ private readonly InteropStateManager _interopStateManager;
+ private readonly TypeDesc _owningType;
+
+ protected override int GetKeyHashCode(MethodSignature key)
+ {
+ return key.GetHashCode();
+ }
+
+ protected override int GetValueHashCode(CalliMarshallingMethodThunk value)
+ {
+ return value.TargetSignature.GetHashCode();
+ }
+
+ protected override bool CompareKeyToValue(MethodSignature key, CalliMarshallingMethodThunk value)
+ {
+ return key.Equals(value.TargetSignature);
+ }
+
+ protected override bool CompareValueToValue(CalliMarshallingMethodThunk value1, CalliMarshallingMethodThunk value2)
+ {
+ return value1.TargetSignature.Equals(value2.TargetSignature);
+ }
+
+ protected override CalliMarshallingMethodThunk CreateValueFromKey(MethodSignature key)
+ {
+ return new CalliMarshallingMethodThunk(key, _owningType, _interopStateManager);
+ }
+
+ public PInvokeCalliHashtable(InteropStateManager interopStateManager, TypeDesc owningType)
+ {
+ _interopStateManager = interopStateManager;
+ _owningType = owningType;
+ }
+ }
}
}
diff --git a/src/Common/src/TypeSystem/Interop/MethodDesc.Interop.cs b/src/Common/src/TypeSystem/Interop/MethodDesc.Interop.cs
index 78e29e25e..46f364cd9 100644
--- a/src/Common/src/TypeSystem/Interop/MethodDesc.Interop.cs
+++ b/src/Common/src/TypeSystem/Interop/MethodDesc.Interop.cs
@@ -101,7 +101,7 @@ namespace Internal.TypeSystem
ThrowOnUnmappableCharMask = 12288
}
- public struct PInvokeFlags
+ public struct PInvokeFlags : IEquatable<PInvokeFlags>, IComparable<PInvokeFlags>
{
private PInvokeAttributes _attributes;
public PInvokeAttributes Attributes
@@ -279,7 +279,26 @@ namespace Internal.TypeSystem
}
}
}
-
+
+ public int CompareTo(PInvokeFlags other)
+ {
+ return Attributes.CompareTo(other.Attributes);
+ }
+
+ public bool Equals(PInvokeFlags other)
+ {
+ return Attributes == other.Attributes;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return obj is PInvokeFlags other && Equals(other);
+ }
+
+ public override int GetHashCode()
+ {
+ return Attributes.GetHashCode();
+ }
}
/// <summary>
diff --git a/src/Common/src/TypeSystem/Mangling/IPrefixMangledSignature.cs b/src/Common/src/TypeSystem/Mangling/IPrefixMangledSignature.cs
new file mode 100644
index 000000000..3dabbc53a
--- /dev/null
+++ b/src/Common/src/TypeSystem/Mangling/IPrefixMangledSignature.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Internal.TypeSystem
+{
+ /// <summary>
+ /// When implemented by a <see cref="MethodDesc"/>, instructs a name mangler to use the same mangled name
+ /// as another entity while prepending a specific prefix to that mangled name.
+ /// </summary>
+ public interface IPrefixMangledSignature
+ {
+ /// <summary>
+ /// Signature whose mangled name to use.
+ /// </summary>
+ MethodSignature BaseSignature { get; }
+
+ /// <summary>
+ /// Prefix to apply when mangling.
+ /// </summary>
+ string Prefix { get; }
+ }
+}
diff --git a/src/Common/src/TypeSystem/NativeFormat/NativeFormatMetadataUnit.cs b/src/Common/src/TypeSystem/NativeFormat/NativeFormatMetadataUnit.cs
index 298e8431e..d4e9718ee 100644
--- a/src/Common/src/TypeSystem/NativeFormat/NativeFormatMetadataUnit.cs
+++ b/src/Common/src/TypeSystem/NativeFormat/NativeFormatMetadataUnit.cs
@@ -502,7 +502,7 @@ namespace Internal.TypeSystem.NativeFormat
AssemblyBindResult bindResult;
RuntimeAssemblyName assemblyName = AssemblyNameParser.Parse(assemblyNameString);
Exception failureException;
- if (!AssemblyBinderImplementation.Instance.Bind(assemblyName, out bindResult, out failureException))
+ if (!AssemblyBinderImplementation.Instance.Bind(assemblyName, cacheMissedLookups: true, out bindResult, out failureException))
{
throw failureException;
}
diff --git a/src/Common/src/TypeSystem/NativeFormat/NativeFormatType.cs b/src/Common/src/TypeSystem/NativeFormat/NativeFormatType.cs
index 6b4cb5902..cde2d125e 100644
--- a/src/Common/src/TypeSystem/NativeFormat/NativeFormatType.cs
+++ b/src/Common/src/TypeSystem/NativeFormat/NativeFormatType.cs
@@ -287,9 +287,9 @@ namespace Internal.TypeSystem.NativeFormat
flags |= TypeFlags.HasFinalizer;
}
- if ((mask & TypeFlags.IsByRefLikeComputed) != 0)
+ if ((mask & TypeFlags.AttributeCacheComputed) != 0)
{
- flags |= TypeFlags.IsByRefLikeComputed;
+ flags |= TypeFlags.AttributeCacheComputed;
if (IsValueType && HasCustomAttribute("System.Runtime.CompilerServices", "IsByRefLikeAttribute"))
flags |= TypeFlags.IsByRefLike;
diff --git a/src/Common/src/TypeSystem/RuntimeDetermined/RuntimeDeterminedType.cs b/src/Common/src/TypeSystem/RuntimeDetermined/RuntimeDeterminedType.cs
index 096fb1c0b..48abf8286 100644
--- a/src/Common/src/TypeSystem/RuntimeDetermined/RuntimeDeterminedType.cs
+++ b/src/Common/src/TypeSystem/RuntimeDetermined/RuntimeDeterminedType.cs
@@ -137,7 +137,7 @@ namespace Internal.TypeSystem
flags |= _rawCanonType.GetTypeFlags(mask);
}
- if ((mask & TypeFlags.IsByRefLikeComputed) != 0)
+ if ((mask & TypeFlags.AttributeCacheComputed) != 0)
{
flags |= _rawCanonType.GetTypeFlags(mask);
}
diff --git a/src/Common/src/TypeSystem/TypesDebugInfoWriter/DebugInfoWriter.cs b/src/Common/src/TypeSystem/TypesDebugInfoWriter/DebugInfoWriter.cs
index a2640d757..2b6cef29f 100644
--- a/src/Common/src/TypeSystem/TypesDebugInfoWriter/DebugInfoWriter.cs
+++ b/src/Common/src/TypeSystem/TypesDebugInfoWriter/DebugInfoWriter.cs
@@ -540,7 +540,8 @@ namespace Internal.TypeSystem.TypesDebugInfo
return classTypeIndex;
}
- public uint GetCompleteClassTypeIndex(ClassTypeDescriptor classTypeDescriptor, ClassFieldsTypeDescriptor classFieldsTypeDescriptior, DataFieldDescriptor[] fields)
+ public uint GetCompleteClassTypeIndex(ClassTypeDescriptor classTypeDescriptor, ClassFieldsTypeDescriptor classFieldsTypeDescriptior,
+ DataFieldDescriptor[] fields, StaticDataFieldDescriptor[] statics)
{
FieldListInProgress fieldList = default(FieldListInProgress);
if ((classTypeDescriptor.BaseClassId != 0) || (fields != null && fields.Length > 0) || (classTypeDescriptor.IsStruct == 0))
@@ -676,8 +677,8 @@ namespace Internal.TypeSystem.TypesDebugInfo
uint recordSize = 12 + DebugInfoBlob.StringLengthEncoded(name);
_blob.WriteWORD(checked((ushort)(_blob.DWORDAlignedSize(recordSize) - 2))); // don't include size of 'length' in 'length'
_blob.WriteLeafKind(LeafKind.LF_MFUNC_ID);
- _blob.WriteDWORD(memberIdDescriptor.MemberFunction);
_blob.WriteDWORD(memberIdDescriptor.ParentClass);
+ _blob.WriteDWORD(memberIdDescriptor.MemberFunction);
_blob.WriteString(name);
_blob.AlignToDWORD();
VerifyBlobEligibleToBeBetweenRecords();
diff --git a/src/Common/src/TypeSystem/TypesDebugInfoWriter/TypesDebugInfoWriter.cs b/src/Common/src/TypeSystem/TypesDebugInfoWriter/TypesDebugInfoWriter.cs
index dd57f1924..133a18d70 100644
--- a/src/Common/src/TypeSystem/TypesDebugInfoWriter/TypesDebugInfoWriter.cs
+++ b/src/Common/src/TypeSystem/TypesDebugInfoWriter/TypesDebugInfoWriter.cs
@@ -12,7 +12,8 @@ namespace Internal.TypeSystem.TypesDebugInfo
uint GetClassTypeIndex(ClassTypeDescriptor classTypeDescriptor);
- uint GetCompleteClassTypeIndex(ClassTypeDescriptor classTypeDescriptor, ClassFieldsTypeDescriptor classFieldsTypeDescriptor, DataFieldDescriptor[] fields);
+ uint GetCompleteClassTypeIndex(ClassTypeDescriptor classTypeDescriptor, ClassFieldsTypeDescriptor classFieldsTypeDescriptor,
+ DataFieldDescriptor[] fields, StaticDataFieldDescriptor[] statics);
uint GetArrayTypeIndex(ClassTypeDescriptor classDescriptor, ArrayTypeDescriptor arrayTypeDescriprtor);
@@ -22,6 +23,8 @@ namespace Internal.TypeSystem.TypesDebugInfo
uint GetMemberFunctionId(MemberFunctionIdTypeDescriptor memberIdDescriptor);
+ uint GetPrimitiveTypeIndex(TypeDesc type);
+
string GetMangledName(TypeDesc type);
}
@@ -46,6 +49,7 @@ namespace Internal.TypeSystem.TypesDebugInfo
public int IsStruct;
public string Name;
public uint BaseClassId;
+ public ulong InstanceSize;
}
[StructLayout(LayoutKind.Sequential)]
@@ -57,6 +61,14 @@ namespace Internal.TypeSystem.TypesDebugInfo
}
[StructLayout(LayoutKind.Sequential)]
+ public struct StaticDataFieldDescriptor
+ {
+ public string StaticDataName;
+ public ulong StaticOffset;
+ public int IsStaticDataInObject;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
public struct ClassFieldsTypeDescriptor
{
public ulong Size;
diff --git a/src/Common/test-runtime/XUnit.Runtime.depproj b/src/Common/test-runtime/XUnit.Runtime.depproj
index 5f1674de3..0d3b67d6e 100644
--- a/src/Common/test-runtime/XUnit.Runtime.depproj
+++ b/src/Common/test-runtime/XUnit.Runtime.depproj
@@ -5,32 +5,93 @@
This RID value doesn't really matter, since the assets we are copying are not RID specific, so defaulting to Windows here
-->
<RuntimeIdentifiers>win-x64</RuntimeIdentifiers>
- <TargetFramework>netcoreapp2.0</TargetFramework>
+ <TargetFramework>netcoreapp2.1</TargetFramework>
<RidSpecificAssets>true</RidSpecificAssets>
<OutputPath>$(RuntimePath)</OutputPath>
+ <XUnitRunnerPackageId>xunit.runner.console</XUnitRunnerPackageId>
+ <XUnitRunner>xunit.console</XUnitRunner>
+ <XUnitTestAdapterPackageId>xunit.runner.visualstudio</XUnitTestAdapterPackageId>
+ <XUnitAdapter>xunit.runner.visualstudio.dotnetcore.testadapter</XUnitAdapter>
+ <TestPlatformHostPackageId>microsoft.testplatform.testhost</TestPlatformHostPackageId>
+ <TestPlatformHost>testhost</TestPlatformHost>
+ <!-- In case the project language is not set -->
+ <Language Condition="'$(Language)' == ''">unknown</Language>
<!-- Don't warn if some dependencies were rolled forward -->
<NoWarn>$(NoWarn);NU1603</NoWarn>
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="xunit.console.netcore">
- <Version>1.0.3-prerelease-00921-01</Version>
+ <PackageReference Include="xunit">
+ <Version>$(XUnitPackageVersion)</Version>
</PackageReference>
- <PackageReference Include="Microsoft.DotNet.BuildTools.TestSuite">
- <Version>$(XunitNetcoreExtensionsVersion)</Version>
+ <PackageReference Include="$(XUnitRunnerPackageId)">
+ <Version>$(XUnitPackageVersion)</Version>
</PackageReference>
- <PackageReference Include="Microsoft.xunit.netcore.extensions">
- <Version>$(XunitNetcoreExtensionsVersion)</Version>
+ <PackageReference Include="Microsoft.DotNet.XUnitExtensions">
+ <Version>$(MicrosoftDotNetXUnitExtensionsVersion)</Version>
+ </PackageReference>
+ <PackageReference Include="$(XUnitTestAdapterPackageId)">
+ <Version>$(XUnitPackageVersion)</Version>
+ </PackageReference>
+ <PackageReference Include="Microsoft.NET.Test.Sdk">
+ <Version>$(MicrosoftDotNetTestSdkVersion)</Version>
+ </PackageReference>
+ <PackageReference Include="Microsoft.TestPlatform.ObjectModel">
+ <Version>$(MicrosoftDotNetTestSdkVersion)</Version>
+ </PackageReference>
+ <PackageReference Include="$(TestPlatformHostPackageId)">
+ <Version>$(MicrosoftDotNetTestSdkVersion)</Version>
+ </PackageReference>
+ <PackageReference Include="Microsoft.Extensions.DependencyModel">
+ <Version>2.0.4</Version>
+ </PackageReference>
+ <PackageReference Include="Newtonsoft.Json">
+ <Version>9.0.1</Version>
</PackageReference>
</ItemGroup>
+ <Target Name="AddTestPlatformDependenciesNetCore" BeforeTargets="ResolveReferences">
+ <Error Condition="!Exists('$(PackagesDir)$(XUnitRunnerPackageId)\$(XUnitPackageVersion)\tools\netcoreapp2.0\$(XUnitRunner).dll')"
+ Text="Error: looks the package $(PackagesDir)$(XUnitRunnerPackageId)\$(XUnitPackageVersion) not restored or missing $(XUnitRunner).dll."
+ />
+ <Error Condition="!Exists('$(PackagesDir)$(XUnitTestAdapterPackageId)\$(XUnitPackageVersion)\build\netcoreapp1.0\$(XUnitAdapter).dll')"
+ Text="Error: looks the package $(PackagesDir)$(XUnitTestAdapterPackageId)\$(XUnitPackageVersion) not restored or missing $(XUnitAdapter).dll."
+ />
+ <Error Condition="!Exists('$(PackagesDir)$(TestPlatformHostPackageId)\$(MicrosoftDotNetTestSdkVersion)\lib\netstandard1.5\$(TestPlatformHost).dll')"
+ Text="Error: looks the package $(PackagesDir)$(TestPlatformHostPackageId)\$(MicrosoftDotNetTestSdkVersion) not restored or missing $(TestPlatformHost).dll."
+ />
+ <ItemGroup>
+ <ReferenceCopyLocalPaths Include="$(PackagesDir)$(XUnitRunnerPackageId)\$(XUnitPackageVersion)\tools\netcoreapp2.0\*.*">
+ <Private>false</Private>
+ <NuGetPackageId>$(XUnitRunnerPackageId)</NuGetPackageId>
+ <NuGetPackageVersion>$(XUnitPackageVersion)</NuGetPackageVersion>
+ </ReferenceCopyLocalPaths>
+ <ReferenceCopyLocalPaths Include="$(PackagesDir)$(XUnitTestAdapterPackageId)\$(XUnitPackageVersion)\build\netcoreapp1.0\*.*">
+ <Private>false</Private>
+ <NuGetPackageId>$(XUnitTestAdapterPackageId)</NuGetPackageId>
+ <NuGetPackageVersion>$(XUnitPackageVersion)</NuGetPackageVersion>
+ </ReferenceCopyLocalPaths>
+ <ReferenceCopyLocalPaths Include="$(PackagesDir)$(TestPlatformHostPackageId)\$(MicrosoftDotNetTestSdkVersion)\lib\netstandard1.5\$(TestPlatformHost).dll">
+ <Private>false</Private>
+ <NuGetPackageId>$(TestPlatformHostPackageId)</NuGetPackageId>
+ <NuGetPackageVersion>$(MicrosoftDotNetTestSdkVersion)</NuGetPackageVersion>
+ </ReferenceCopyLocalPaths>
+ </ItemGroup>
+ </Target>
<ItemGroup>
- <PackageToInclude Include="xunit.abstractions"/>
- <PackageToInclude Include="xunit.assert"/>
- <PackageToInclude Include="xunit.extensibility.core"/>
- <PackageToInclude Include="xunit.extensibility.execution"/>
- <PackageToInclude Include="xunit.runner.utility"/>
- <PackageToInclude Include="Microsoft.xunit.netcore.extensions"/>
- <PackageToInclude Include="xunit.console.netcore" />
- </ItemGroup>
+ <!-- xunit core -->
+ <PackageToInclude Include="xunit.abstractions" />
+ <PackageToInclude Include="xunit.assert" />
+ <PackageToInclude Include="xunit.extensibility.core" />
+ <PackageToInclude Include="xunit.extensibility.execution" />
+ <PackageToInclude Include="xunit.runner.utility" />
+ <PackageToInclude Include="Microsoft.DotNet.XUnitExtensions" />
+
+ <!-- test sdk -->
+ <PackageToInclude Include="Microsoft.NET.Test.Sdk" />
+ <PackageToInclude Include="Microsoft.TestPlatform.TestHost" />
+ <PackageToInclude Include="Microsoft.TestPlatform.ObjectModel" />
+ <PackageToInclude Include="Microsoft.Extensions.DependencyModel" />
+ <PackageToInclude Include="Newtonsoft.Json" />
+ </ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
diff --git a/src/Framework/Framework-native.depproj b/src/Framework/Framework-native.depproj
index cc3093531..a83f57d93 100644
--- a/src/Framework/Framework-native.depproj
+++ b/src/Framework/Framework-native.depproj
@@ -6,8 +6,8 @@
</PropertyGroup>
<PropertyGroup>
- <NuGetTargetMoniker>.NETCoreApp,Version=v2.0</NuGetTargetMoniker>
- <TargetFramework>netcoreapp2.0</TargetFramework>
+ <NuGetTargetMoniker>.NETCoreApp,Version=v2.1</NuGetTargetMoniker>
+ <TargetFramework>netcoreapp2.1</TargetFramework>
<RuntimeIdentifiers>$(NuPkgRid)</RuntimeIdentifiers>
<RidSpecificAssets>true</RidSpecificAssets>
</PropertyGroup>
diff --git a/src/Framework/Framework-uapaot.depproj b/src/Framework/Framework-uapaot.depproj
index ab8e28d15..47fc83e40 100644
--- a/src/Framework/Framework-uapaot.depproj
+++ b/src/Framework/Framework-uapaot.depproj
@@ -19,10 +19,13 @@
</ItemGroup>
<ItemGroup>
+ <!-- System.Runtime.InteropServices implementation has to be forwarded to System.Private.Interop -->
+ <!-- TODO https://github.com/dotnet/corert/issues/3231 -->
+ <FileToInclude Include="System.Runtime.InteropServices" />
+ <FileToInclude Include="mscorlib" />
+
<!-- Pickup a few selected aot-specific files from uapaot instead -->
<FileToInclude Include="System.Linq.Expressions" />
- <FileToInclude Include="System.Reflection.Primitives" />
- <FileToInclude Include="System.Runtime.InteropServices" />
<FileToInclude Include="System.Text.RegularExpressions" />
<FileToInclude Include="System.Private.Xml" />
<FileToInclude Include="System.Private.Xml.Linq" />
diff --git a/src/Framework/Framework.depproj b/src/Framework/Framework.depproj
index e994ff425..d72b2e1a0 100644
--- a/src/Framework/Framework.depproj
+++ b/src/Framework/Framework.depproj
@@ -5,8 +5,8 @@
</PropertyGroup>
<PropertyGroup>
- <NuGetTargetMoniker>.NETCoreApp,Version=v2.1</NuGetTargetMoniker>
- <TargetFramework>netcoreapp2.1</TargetFramework>
+ <NuGetTargetMoniker>.NETCoreApp,Version=v3.0</NuGetTargetMoniker>
+ <TargetFramework>netcoreapp3.0</TargetFramework>
<RuntimeIdentifiers>$(NuPkgRid)</RuntimeIdentifiers>
<RidSpecificAssets>true</RidSpecificAssets>
</PropertyGroup>
@@ -29,22 +29,30 @@
</ItemGroup>
<ItemGroup>
+ <!-- System.Runtime.InteropServices implementation has to be forwarded to System.Private.Interop -->
+ <!-- TODO https://github.com/dotnet/corert/issues/3231 -->
+ <FileToExclude Include="System.Runtime.InteropServices" />
+ <FileToExclude Include="mscorlib" />
+
<!-- Pickup a few selected aot-specific files from uapaot instead -->
<FileToExclude Include="System.Linq.Expressions" />
- <FileToExclude Include="System.Reflection.Primitives" />
- <FileToExclude Include="System.Runtime.InteropServices" />
<FileToExclude Include="System.Text.RegularExpressions" />
+ <FileToExclude Include="System.Private.Xml" />
+ <FileToExclude Include="System.Private.Xml.Linq" />
<!-- TODO: Upstack framework -->
<FileToExclude Include="System.Private.DataContractSerialization" />
- <FileToExclude Include="System.Private.Xml" />
<FileToExclude Include="System.Reflection.DispatchProxy" />
- <FileToExclude Include="System.Private.Xml.Linq" />
<FileToExclude Include="System.Data.Common" />
<FileToExclude Include="System.Diagnostics.StackTrace" />
- <!-- TODO: Unmanaged -->
- <FileToExclude Include="clrcompression" />
+ <!-- TODO: WinRT -->
+ <FileToExclude Include="System.Runtime.InteropServices.WindowsRuntime" />
+ <FileToExclude Include="System.Runtime.WindowsRuntime" />
+ <FileToExclude Include="System.Runtime.WindowsRuntime.UI.Xaml" />
+
+ <!-- TODO: https://github.com/dotnet/corert/issues/5496 -->
+ <!-- <FileToExclude Include="clrcompression" /> -->
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/ILCompiler.Build.Tasks/src/ComputeManagedAssemblies.cs b/src/ILCompiler.Build.Tasks/src/ComputeManagedAssemblies.cs
index 0e4998ece..e1435b0c6 100644
--- a/src/ILCompiler.Build.Tasks/src/ComputeManagedAssemblies.cs
+++ b/src/ILCompiler.Build.Tasks/src/ComputeManagedAssemblies.cs
@@ -24,7 +24,7 @@ namespace Build.Tasks
}
/// <summary>
- /// The CoreRT-specific System.Private.* assemblies that must be used instead of the netcoreapp2.0 versions.
+ /// The CoreRT-specific System.Private.* assemblies that must be used instead of the netcoreapp2.1 versions.
/// </summary>
[Required]
public ITaskItem[] SdkAssemblies
diff --git a/src/ILCompiler.Compiler/src/Compiler/AnalysisBasedMetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/AnalysisBasedMetadataManager.cs
index 3a51c070d..1f2224d5d 100644
--- a/src/ILCompiler.Compiler/src/Compiler/AnalysisBasedMetadataManager.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/AnalysisBasedMetadataManager.cs
@@ -25,16 +25,17 @@ namespace ILCompiler
private readonly Dictionary<FieldDesc, MetadataCategory> _reflectableFields = new Dictionary<FieldDesc, MetadataCategory>();
public AnalysisBasedMetadataManager(
- ModuleDesc generatedAssembly,
CompilerTypeSystemContext typeSystemContext,
MetadataBlockingPolicy blockingPolicy,
+ ManifestResourceBlockingPolicy resourceBlockingPolicy,
string logFile,
StackTraceEmissionPolicy stackTracePolicy,
+ DynamicInvokeThunkGenerationPolicy invokeThunkGenerationPolicy,
IEnumerable<ModuleDesc> modulesWithMetadata,
IEnumerable<ReflectableEntity<TypeDesc>> reflectableTypes,
IEnumerable<ReflectableEntity<MethodDesc>> reflectableMethods,
IEnumerable<ReflectableEntity<FieldDesc>> reflectableFields)
- : base(generatedAssembly, typeSystemContext, blockingPolicy, logFile, stackTracePolicy)
+ : base(typeSystemContext, blockingPolicy, resourceBlockingPolicy, logFile, stackTracePolicy, invokeThunkGenerationPolicy)
{
_modulesWithMetadata = new List<ModuleDesc>(modulesWithMetadata);
diff --git a/src/ILCompiler.Compiler/src/Compiler/Compilation.cs b/src/ILCompiler.Compiler/src/Compiler/Compilation.cs
index d686a0d7b..b697d3020 100644
--- a/src/ILCompiler.Compiler/src/Compiler/Compilation.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/Compilation.cs
@@ -58,7 +58,7 @@ namespace ILCompiler
foreach (var rootProvider in compilationRoots)
rootProvider.AddCompilationRoots(rootingService);
- MetadataType globalModuleGeneratedType = nodeFactory.CompilationModuleGroup.GeneratedAssembly.GetGlobalModuleType();
+ MetadataType globalModuleGeneratedType = nodeFactory.TypeSystemContext.GeneratedAssembly.GetGlobalModuleType();
_typeGetTypeMethodThunks = new TypeGetTypeMethodThunkCache(globalModuleGeneratedType);
_assemblyGetExecutingAssemblyMethodThunks = new AssemblyGetExecutingAssemblyMethodThunkCache(globalModuleGeneratedType);
_methodBaseGetCurrentMethodThunks = new MethodBaseGetCurrentMethodThunkCache();
@@ -90,6 +90,12 @@ namespace ILCompiler
public DelegateCreationInfo GetDelegateCtor(TypeDesc delegateType, MethodDesc target, bool followVirtualDispatch)
{
+ // If we're creating a delegate to a virtual method that cannot be overriden, devirtualize.
+ // This is not just an optimization - it's required for correctness in the presence of sealed
+ // vtable slots.
+ if (followVirtualDispatch && (target.IsFinal || target.OwningType.IsSealed()))
+ followVirtualDispatch = false;
+
return DelegateCreationInfo.Create(delegateType, target, NodeFactory, followVirtualDispatch);
}
@@ -102,7 +108,7 @@ namespace ILCompiler
{
var pInvokeFixup = (PInvokeLazyFixupField)field;
PInvokeMetadata metadata = pInvokeFixup.PInvokeMetadata;
- return NodeFactory.PInvokeMethodFixup(metadata.Module, metadata.Name);
+ return NodeFactory.PInvokeMethodFixup(metadata.Module, metadata.Name, metadata.Flags);
}
else
{
@@ -360,7 +366,7 @@ namespace ILCompiler
Debug.Assert(!type.IsGenericDefinition);
MetadataType metadataType = type as MetadataType;
- if (metadataType != null && metadataType.ThreadStaticFieldSize.AsInt > 0)
+ if (metadataType != null && metadataType.ThreadGcStaticFieldSize.AsInt > 0)
{
_graph.AddRoot(_factory.TypeThreadStaticIndex(metadataType), reason);
@@ -413,7 +419,16 @@ namespace ILCompiler
public void RootModuleMetadata(ModuleDesc module, string reason)
{
- _graph.AddRoot(_factory.ModuleMetadata(module), reason);
+ // RootModuleMetadata is kind of a hack - this is pretty much only used to force include
+ // type forwarders from assemblies metadata generator would normally not look at.
+ // This will go away when the temporary RD.XML parser goes away.
+ if (_factory.MetadataManager is UsageBasedMetadataManager)
+ _graph.AddRoot(_factory.ModuleMetadata(module), reason);
+ }
+
+ public void RootReadOnlyDataBlob(byte[] data, int alignment, string reason, string exportName)
+ {
+ _graph.AddRoot(_factory.ReadOnlyDataBlob(exportName, data, alignment), reason);
}
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/CompilationModuleGroup.cs b/src/ILCompiler.Compiler/src/Compiler/CompilationModuleGroup.cs
index 8fa73ff20..edc9b076a 100644
--- a/src/ILCompiler.Compiler/src/Compiler/CompilationModuleGroup.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/CompilationModuleGroup.cs
@@ -22,17 +22,6 @@ namespace ILCompiler
public abstract class CompilationModuleGroup
{
/// <summary>
- /// Gets the synthetic assembly that holds types generated by the compiler as part of the compilation process.
- /// Types and members that declare this module as their owning module are always generated.
- /// </summary>
- public ModuleDesc GeneratedAssembly { get; }
-
- public CompilationModuleGroup(TypeSystemContext context)
- {
- GeneratedAssembly = new CompilerGeneratedAssembly(context);
- }
-
- /// <summary>
/// If true, "type" is in the set of input assemblies being compiled
/// </summary>
public abstract bool ContainsType(TypeDesc type);
@@ -49,6 +38,10 @@ namespace ILCompiler
/// </summary>
public abstract bool ContainsMethodDictionary(MethodDesc method);
/// <summary>
+ /// If true, "method" is imported from the set of reference assemblies
+ /// </summary>
+ public abstract bool ImportsMethod(MethodDesc method, bool unboxingStub);
+ /// <summary>
/// If true, "type" is exported by the set of input assemblies being compiled
/// </summary>
public abstract ExportForm GetExportTypeForm(TypeDesc type);
@@ -94,41 +87,5 @@ namespace ILCompiler
/// accessed through the target platform's import mechanism (ie, Import Address Table on Windows)
/// </summary>
public abstract bool CanHaveReferenceThroughImportTable { get; }
-
- private class CompilerGeneratedAssembly : ModuleDesc, IAssemblyDesc
- {
- private MetadataType _globalModuleType;
-
- public CompilerGeneratedAssembly(TypeSystemContext context)
- : base(context)
- {
- _globalModuleType = new CompilerGeneratedType(this, "<Module>");
- }
-
- public override IEnumerable<MetadataType> GetAllTypes()
- {
- return Array.Empty<MetadataType>();
- }
-
- public override MetadataType GetGlobalModuleType()
- {
- return _globalModuleType;
- }
-
- public AssemblyName GetName()
- {
- return new AssemblyName("System.Private.CompilerGenerated");
- }
-
- public override MetadataType GetType(string nameSpace, string name, bool throwIfNotFound = true)
- {
- Debug.Fail("Resolving a TypeRef in the compiler generated assembly?");
-
- if (throwIfNotFound)
- ThrowHelper.ThrowTypeLoadException(nameSpace, name, this);
-
- return null;
- }
- }
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedType.Sorting.cs b/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedType.Sorting.cs
deleted file mode 100644
index 99457b98f..000000000
--- a/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedType.Sorting.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-
-using Internal.TypeSystem;
-
-namespace ILCompiler
-{
- // Functionality related to determinstic ordering of types and members
- internal sealed partial class CompilerGeneratedType : MetadataType
- {
- protected override int ClassCode => -1036681447;
-
- protected override int CompareToImpl(TypeDesc other, TypeSystemComparer comparer)
- {
- // Should be a singleton
- throw new NotSupportedException();
- }
- }
-}
diff --git a/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedType.cs b/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedType.cs
deleted file mode 100644
index 7bbd0aa45..000000000
--- a/src/ILCompiler.Compiler/src/Compiler/CompilerGeneratedType.cs
+++ /dev/null
@@ -1,198 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Collections.Generic;
-
-using Internal.TypeSystem;
-
-using Debug = System.Diagnostics.Debug;
-using TypeHashingAlgorithms = Internal.NativeFormat.TypeHashingAlgorithms;
-
-namespace ILCompiler
-{
- /// <summary>
- /// A pseudo-type that owns helper methods generated by the compiler.
- /// This type should never be allocated (we should never see an EEType for it).
- /// </summary>
- internal sealed partial class CompilerGeneratedType : MetadataType
- {
- private int _hashcode;
-
- public CompilerGeneratedType(ModuleDesc module, string name)
- {
- Module = module;
- Name = name;
- }
-
- public override TypeSystemContext Context
- {
- get
- {
- return Module.Context;
- }
- }
-
- public override string Name
- {
- get;
- }
-
- public override string Namespace
- {
- get
- {
- return "Internal.CompilerGenerated";
- }
- }
-
- public override int GetHashCode()
- {
- if (_hashcode != 0)
- return _hashcode;
- return InitializeHashCode();
- }
-
- private int InitializeHashCode()
- {
- string ns = Namespace;
- var hashCodeBuilder = new TypeHashingAlgorithms.HashCodeBuilder(ns);
- if (ns.Length > 0)
- hashCodeBuilder.Append(".");
- hashCodeBuilder.Append(Name);
- _hashcode = hashCodeBuilder.ToHashCode();
-
- return _hashcode;
- }
-
- public override bool IsCanonicalSubtype(CanonicalFormKind policy)
- {
- Debug.Assert(!HasInstantiation, "Why is this generic?");
- return false;
- }
-
- protected override TypeFlags ComputeTypeFlags(TypeFlags mask)
- {
- return TypeFlags.Class |
- TypeFlags.HasGenericVarianceComputed |
- TypeFlags.HasStaticConstructorComputed |
- TypeFlags.HasFinalizerComputed |
- TypeFlags.IsByRefLikeComputed;
- }
-
- public override ClassLayoutMetadata GetClassLayout()
- {
- return new ClassLayoutMetadata
- {
- Offsets = null,
- PackingSize = 0,
- Size = 0,
- };
- }
-
- public override bool HasCustomAttribute(string attributeNamespace, string attributeName)
- {
- return false;
- }
-
- public override IEnumerable<MetadataType> GetNestedTypes()
- {
- return Array.Empty<MetadataType>();
- }
-
- public override MetadataType GetNestedType(string name)
- {
- return null;
- }
-
- protected override MethodImplRecord[] ComputeVirtualMethodImplsForType()
- {
- return Array.Empty<MethodImplRecord>();
- }
-
- public override MethodImplRecord[] FindMethodsImplWithMatchingDeclName(string name)
- {
- return Array.Empty<MethodImplRecord>();
- }
-
- public override ModuleDesc Module
- {
- get;
- }
-
- public override PInvokeStringFormat PInvokeStringFormat
- {
- get
- {
- return PInvokeStringFormat.AutoClass;
- }
- }
-
- public override bool IsExplicitLayout
- {
- get
- {
- return false;
- }
- }
-
- public override bool IsSequentialLayout
- {
- get
- {
- return false;
- }
- }
-
- public override bool IsBeforeFieldInit
- {
- get
- {
- return false;
- }
- }
-
- public override MetadataType MetadataBaseType
- {
- get
- {
- // Since this type should never be allocated and only serves the purpose of grouping things,
- // it can act like a <Module> type and have no base type.
- return null;
- }
- }
-
- public override bool IsSealed
- {
- get
- {
- return true;
- }
- }
-
- public override bool IsAbstract
- {
- get
- {
- return false;
- }
- }
-
- public override DefType ContainingType
- {
- get
- {
- return null;
- }
- }
-
- public override DefType[] ExplicitlyImplementedInterfaces
- {
- get
- {
- return Array.Empty<DefType>();
- }
- }
- }
-}
diff --git a/src/ILCompiler.Compiler/src/Compiler/CompilerMetadataFieldLayoutAlgorithm.cs b/src/ILCompiler.Compiler/src/Compiler/CompilerMetadataFieldLayoutAlgorithm.cs
index 1d6d2c870..48daeab70 100644
--- a/src/ILCompiler.Compiler/src/Compiler/CompilerMetadataFieldLayoutAlgorithm.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/CompilerMetadataFieldLayoutAlgorithm.cs
@@ -7,6 +7,8 @@ using System.Collections.Generic;
using Internal.TypeSystem;
+using Debug = System.Diagnostics.Debug;
+
namespace ILCompiler
{
internal class CompilerMetadataFieldLayoutAlgorithm : MetadataFieldLayoutAlgorithm
@@ -15,7 +17,7 @@ namespace ILCompiler
{
// GC statics start with a pointer to the "EEType" that signals the size and GCDesc to the GC
layout.GcStatics.Size = context.Target.LayoutPointerSize;
- layout.ThreadStatics.Size = context.Target.LayoutPointerSize;
+ layout.ThreadGcStatics.Size = context.Target.LayoutPointerSize;
}
protected override void FinalizeRuntimeSpecificStaticFieldLayout(TypeSystemContext context, ref ComputedStaticFieldLayout layout)
@@ -26,10 +28,14 @@ namespace ILCompiler
{
layout.GcStatics.Size = LayoutInt.Zero;
}
- if (layout.ThreadStatics.Size == context.Target.LayoutPointerSize)
+ if (layout.ThreadGcStatics.Size == context.Target.LayoutPointerSize)
{
- layout.ThreadStatics.Size = LayoutInt.Zero;
+ layout.ThreadGcStatics.Size = LayoutInt.Zero;
}
+
+ // CoreRT makes no distinction between Gc / non-Gc thread statics. All are placed into ThreadGcStatics since thread statics
+ // are typically rare.
+ Debug.Assert(layout.ThreadNonGcStatics.Size == LayoutInt.Zero);
}
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.BoxedTypes.cs b/src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.BoxedTypes.cs
index 9b8bd363c..71b9720fc 100644
--- a/src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.BoxedTypes.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.BoxedTypes.cs
@@ -290,7 +290,17 @@ namespace ILCompiler
Module = owningModule;
ValueTypeRepresented = valuetype;
- BoxedValue = new BoxedValueField(this);
+
+ // Unboxing thunks for byref-like types don't make sense. Byref-like types cannot be boxed.
+ // We still allow these to exist in the system, because it's easier than trying to prevent
+ // their creation. We create them as if they existed (in lieu of e.g. pointing all of them
+ // to the same __unreachable method body) so that the various places that store pointers to
+ // them because they want to be able to extract the target instance method can use the same
+ // mechanism they use for everything else at runtime.
+ // The main difference is that the "Boxed_ValueType" version has no fields. Reference types
+ // cannot have byref-like fields.
+ if (!valuetype.IsByRefLike)
+ BoxedValue = new BoxedValueField(this);
}
public override ClassLayoutMetadata GetClassLayout() => default(ClassLayoutMetadata);
@@ -325,14 +335,14 @@ namespace ILCompiler
}
flags |= TypeFlags.HasFinalizerComputed;
- flags |= TypeFlags.IsByRefLikeComputed;
+ flags |= TypeFlags.AttributeCacheComputed;
return flags;
}
public override FieldDesc GetField(string name)
{
- if (name == BoxedValueFieldName)
+ if (name == BoxedValueFieldName && BoxedValue != null)
return BoxedValue;
return null;
@@ -340,7 +350,10 @@ namespace ILCompiler
public override IEnumerable<FieldDesc> GetFields()
{
- yield return BoxedValue;
+ if (BoxedValue != null)
+ return new FieldDesc[] { BoxedValue };
+
+ return Array.Empty<FieldDesc>();
}
/// <summary>
@@ -439,6 +452,15 @@ namespace ILCompiler
public override MethodIL EmitIL()
{
+ if (_owningType.BoxedValue == null)
+ {
+ // If this is the fake unboxing thunk for ByRef-like types, just make a method that throws.
+ return new ILStubMethodIL(this,
+ new byte[] { (byte)ILOpcode.ldnull, (byte)ILOpcode.throw_ },
+ Array.Empty<LocalVariableDefinition>(),
+ Array.Empty<object>());
+ }
+
// Generate the unboxing stub. This loosely corresponds to following C#:
// return BoxedValue.InstanceMethod(this.m_pEEType, [rest of parameters])
@@ -507,6 +529,15 @@ namespace ILCompiler
public override MethodIL EmitIL()
{
+ if (_owningType.BoxedValue == null)
+ {
+ // If this is the fake unboxing thunk for ByRef-like types, just make a method that throws.
+ return new ILStubMethodIL(this,
+ new byte[] { (byte)ILOpcode.ldnull, (byte)ILOpcode.throw_ },
+ Array.Empty<LocalVariableDefinition>(),
+ Array.Empty<object>());
+ }
+
// Generate the unboxing stub. This loosely corresponds to following C#:
// return BoxedValue.InstanceMethod([rest of parameters])
diff --git a/src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.Mangling.cs b/src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.Mangling.cs
index 720f06114..ace374f04 100644
--- a/src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.Mangling.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.Mangling.cs
@@ -47,5 +47,24 @@ namespace ILCompiler
}
}
}
+
+ partial class UnboxingThunk : IPrefixMangledMethod
+ {
+ MethodDesc IPrefixMangledMethod.BaseMethod
+ {
+ get
+ {
+ return _targetMethod;
+ }
+ }
+
+ string IPrefixMangledMethod.Prefix
+ {
+ get
+ {
+ return "unbox";
+ }
+ }
+ }
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.cs b/src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.cs
index 4feb7a582..6f4710561 100644
--- a/src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/CompilerTypeSystemContext.cs
@@ -424,6 +424,9 @@ namespace ILCompiler
{
Debug.Assert(field.IsStatic);
+ if (field.IsThreadStatic)
+ return true;
+
TypeDesc fieldType = field.FieldType;
if (fieldType.IsValueType)
return ((DefType)fieldType).ContainsGCPointers;
@@ -499,17 +502,23 @@ namespace ILCompiler
// method table.
public long UniversalCanonReflectionMethodRootHeuristic_InstantiationCount { get; }
+ // To avoid infinite generic recursion issues during debug type record generation, attempt to
+ // use canonical form for types with high generic complexity.
+ public long MaxGenericDepthOfDebugRecord { get; }
+
public SharedGenericsConfiguration()
{
UniversalCanonGVMReflectionRootHeuristic_InstantiationCount = 4;
UniversalCanonGVMDepthHeuristic_NonCanonDepth = 2;
UniversalCanonGVMDepthHeuristic_CanonDepth = 1;
- // Unlike the GVM heuristics which are intended to kick in aggresively
+ // Unlike the GVM heuristics which are intended to kick in aggressively
// this heuristic exists to make it so that a fair amount of generic
// expansion is allowed. Numbers are chosen to allow a fairly large
// amount of generic expansion before trimming.
UniversalCanonReflectionMethodRootHeuristic_InstantiationCount = 1024;
+
+ MaxGenericDepthOfDebugRecord = 15;
}
};
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/CoreRTNameMangler.cs b/src/ILCompiler.Compiler/src/Compiler/CoreRTNameMangler.cs
index 86cac8dc0..8c5636c21 100644
--- a/src/ILCompiler.Compiler/src/Compiler/CoreRTNameMangler.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/CoreRTNameMangler.cs
@@ -331,7 +331,13 @@ namespace ILCompiler
}
else
{
+ // This is a type definition. Since we didn't fall in the `is EcmaType` case above,
+ // it's likely a compiler-generated type.
mangledName = SanitizeName(((DefType)type).GetFullName(), true);
+
+ // Always generate a fully qualified name
+ if (_mangleForCplusPlus)
+ mangledName = "::" + mangledName;
}
break;
}
@@ -404,6 +410,35 @@ namespace ILCompiler
return sb.ToUtf8String();
}
+ private Utf8String GetPrefixMangledSignatureName(IPrefixMangledSignature prefixMangledSignature)
+ {
+ Utf8StringBuilder sb = new Utf8StringBuilder();
+ sb.Append(EnterNameScopeSequence).Append(prefixMangledSignature.Prefix).Append(ExitNameScopeSequence);
+
+ var signature = prefixMangledSignature.BaseSignature;
+ sb.Append(signature.Flags.ToStringInvariant());
+
+ sb.Append(EnterNameScopeSequence);
+
+ string sigRetTypeName = GetMangledTypeName(signature.ReturnType);
+ if (_mangleForCplusPlus)
+ sigRetTypeName = sigRetTypeName.Replace("::", "_");
+ sb.Append(sigRetTypeName);
+
+ for (int i = 0; i < signature.Length; i++)
+ {
+ sb.Append("__");
+ string sigArgName = GetMangledTypeName(signature[i]);
+ if (_mangleForCplusPlus)
+ sigArgName = sigArgName.Replace("::", "_");
+ sb.Append(sigArgName);
+ }
+
+ sb.Append(ExitNameScopeSequence);
+
+ return sb.ToUtf8String();
+ }
+
private Utf8String GetPrefixMangledMethodName(IPrefixMangledMethod prefixMangledMetod)
{
Utf8StringBuilder sb = new Utf8StringBuilder();
@@ -491,6 +526,10 @@ namespace ILCompiler
{
utf8MangledName = GetPrefixMangledTypeName((IPrefixMangledType)method);
}
+ else if (method is IPrefixMangledSignature)
+ {
+ utf8MangledName = GetPrefixMangledSignatureName((IPrefixMangledSignature)method);
+ }
else
{
// Assume that Name is unique for all other methods
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayMapNode.cs
index 4f8c8ba46..bd42d69ad 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayMapNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayMapNode.cs
@@ -78,6 +78,6 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.ArrayMapNode;
+ public override int ClassCode => (int)ObjectNodeOrder.ArrayMapNode;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfEmbeddedDataNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfEmbeddedDataNode.cs
index 927710fad..131ae249f 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfEmbeddedDataNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfEmbeddedDataNode.cs
@@ -108,6 +108,6 @@ namespace ILCompiler.DependencyAnalysis
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.ArrayOfEmbeddedDataNode;
+ public override int ClassCode => (int)ObjectNodeOrder.ArrayOfEmbeddedDataNode;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs
index 45271af23..3082f9ffc 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs
@@ -51,7 +51,7 @@ namespace ILCompiler.DependencyAnalysis
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.ArrayOfEmbeddedPointersNode;
+ public override int ClassCode => (int)ObjectNodeOrder.ArrayOfEmbeddedPointersNode;
private class PointerIndirectionNodeComparer : IComparer<EmbeddedPointerIndirectionNode<TTarget>>
{
@@ -96,7 +96,7 @@ namespace ILCompiler.DependencyAnalysis
};
}
- protected internal override int ClassCode => -66002498;
+ public override int ClassCode => -66002498;
}
private class EmbeddedPointerIndirectionWithSymbolNode : SimpleEmbeddedPointerIndirectionNode, ISymbolDefinitionNode
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfFrozenObjectsNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfFrozenObjectsNode.cs
index 70349bdbf..847eb27be 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfFrozenObjectsNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfFrozenObjectsNode.cs
@@ -42,6 +42,6 @@ namespace ILCompiler.DependencyAnalysis
builder.EmitZeroPointer();
}
- protected internal override int ClassCode => -1771336339;
+ public override int ClassCode => -1771336339;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/AssemblyStubNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/AssemblyStubNode.cs
index db568a3e8..0bc9db8c6 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/AssemblyStubNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/AssemblyStubNode.cs
@@ -16,6 +16,12 @@ namespace ILCompiler.DependencyAnalysis
{
}
+ /// <summary>
+ /// Gets a value indicating whether the stub's address is visible from managed code
+ /// and could be a target of a managed calli.
+ /// </summary>
+ protected virtual bool IsVisibleFromManagedCode => true;
+
public override ObjectNodeSection Section => ObjectNodeSection.TextSection;
public override bool StaticDependenciesAreComputed => true;
@@ -26,19 +32,26 @@ namespace ILCompiler.DependencyAnalysis
public override ObjectData GetData(NodeFactory factory, bool relocsOnly)
{
+ // If the address is expected to be visible from managed code, we need to align
+ // at the managed code boundaries to prevent the stub from being confused with
+ // a fat fuction pointer. Otherwise we can align tighter.
+ int alignment = IsVisibleFromManagedCode ?
+ factory.Target.MinimumFunctionAlignment :
+ factory.Target.MinimumCodeAlignment;
+
switch (factory.Target.Architecture)
{
case TargetArchitecture.X64:
X64.X64Emitter x64Emitter = new X64.X64Emitter(factory, relocsOnly);
EmitCode(factory, ref x64Emitter, relocsOnly);
- x64Emitter.Builder.RequireInitialAlignment(factory.Target.MinimumFunctionAlignment);
+ x64Emitter.Builder.RequireInitialAlignment(alignment);
x64Emitter.Builder.AddSymbol(this);
return x64Emitter.Builder.ToObjectData();
case TargetArchitecture.X86:
X86.X86Emitter x86Emitter = new X86.X86Emitter(factory, relocsOnly);
EmitCode(factory, ref x86Emitter, relocsOnly);
- x86Emitter.Builder.RequireInitialAlignment(factory.Target.MinimumFunctionAlignment);
+ x86Emitter.Builder.RequireInitialAlignment(alignment);
x86Emitter.Builder.AddSymbol(this);
return x86Emitter.Builder.ToObjectData();
@@ -46,14 +59,14 @@ namespace ILCompiler.DependencyAnalysis
case TargetArchitecture.ARMEL:
ARM.ARMEmitter armEmitter = new ARM.ARMEmitter(factory, relocsOnly);
EmitCode(factory, ref armEmitter, relocsOnly);
- armEmitter.Builder.RequireInitialAlignment(factory.Target.MinimumFunctionAlignment);
+ armEmitter.Builder.RequireInitialAlignment(alignment);
armEmitter.Builder.AddSymbol(this);
return armEmitter.Builder.ToObjectData();
case TargetArchitecture.ARM64:
ARM64.ARM64Emitter arm64Emitter = new ARM64.ARM64Emitter(factory, relocsOnly);
EmitCode(factory, ref arm64Emitter, relocsOnly);
- arm64Emitter.Builder.RequireInitialAlignment(factory.Target.MinimumFunctionAlignment);
+ arm64Emitter.Builder.RequireInitialAlignment(alignment);
arm64Emitter.Builder.AddSymbol(this);
return arm64Emitter.Builder.ToObjectData();
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/BlobNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/BlobNode.cs
index 5f2b27f5c..083de9bde 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/BlobNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/BlobNode.cs
@@ -42,9 +42,9 @@ namespace ILCompiler.DependencyAnalysis
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
#if !SUPPORT_JIT
- protected internal override int ClassCode => -470351029;
+ public override int ClassCode => -470351029;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return _name.CompareTo(((BlobNode)other)._name);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/BlockReflectionTypeMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/BlockReflectionTypeMapNode.cs
index 95fa4b07e..b9ccd7b07 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/BlockReflectionTypeMapNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/BlockReflectionTypeMapNode.cs
@@ -83,6 +83,6 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.BlockReflectionTypeMapNode;
+ public override int ClassCode => (int)ObjectNodeOrder.BlockReflectionTypeMapNode;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalDefinitionEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalDefinitionEETypeNode.cs
index 520781f53..d1538a4a9 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalDefinitionEETypeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalDefinitionEETypeNode.cs
@@ -43,6 +43,6 @@ namespace ILCompiler.DependencyAnalysis
// Canonical definition types will have their base size set to the minimum
protected override int BaseSize => MinimumObjectSize;
- protected internal override int ClassCode => -1851030036;
+ public override int ClassCode => -1851030036;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs
index 2383df231..945e49c39 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs
@@ -27,7 +27,6 @@ namespace ILCompiler.DependencyAnalysis
Debug.Assert(type.IsCanonicalSubtype(CanonicalFormKind.Any));
Debug.Assert(type == type.ConvertToCanonForm(CanonicalFormKind.Specific));
Debug.Assert(!type.IsMdArray);
- Debug.Assert(!type.IsByRefLike);
}
public override bool StaticDependenciesAreComputed => true;
@@ -46,7 +45,7 @@ namespace ILCompiler.DependencyAnalysis
DefType closestDefType = _type.GetClosestDefType();
- if (_type.RuntimeInterfaces.Length > 0)
+ if (InterfaceDispatchMapNode.MightHaveInterfaceDispatchMap(_type, factory))
dependencyList.Add(factory.InterfaceDispatchMap(_type), "Canonical interface dispatch map");
dependencyList.Add(factory.VTable(closestDefType), "VTable");
@@ -62,6 +61,15 @@ namespace ILCompiler.DependencyAnalysis
AddDependenciesForUniversalGVMSupport(factory, _type, ref dependencyList);
}
+ // Keep track of the default constructor map dependency for this type if it has a default constructor
+ MethodDesc defaultCtor = closestDefType.GetDefaultConstructor();
+ if (defaultCtor != null)
+ {
+ dependencyList.Add(new DependencyListEntry(
+ factory.MethodEntrypoint(defaultCtor, closestDefType.IsValueType),
+ "DefaultConstructorNode"));
+ }
+
return dependencyList;
}
@@ -136,6 +144,6 @@ namespace ILCompiler.DependencyAnalysis
base.ComputeValueTypeFieldPadding();
}
- protected internal override int ClassCode => -1798018602;
+ public override int ClassCode => -1798018602;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ClassConstructorContextMap.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ClassConstructorContextMap.cs
index 0624ee1c6..1a62667db 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ClassConstructorContextMap.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ClassConstructorContextMap.cs
@@ -81,6 +81,6 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.ClassConstructorContextMap;
+ public override int ClassCode => (int)ObjectNodeOrder.ClassConstructorContextMap;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ClonedConstructedEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ClonedConstructedEETypeNode.cs
index d64319e90..7b7642938 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ClonedConstructedEETypeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ClonedConstructedEETypeNode.cs
@@ -15,7 +15,7 @@ namespace ILCompiler.DependencyAnalysis
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler) + " cloned";
- public override ObjectNode NodeForLinkage(NodeFactory factory) => this;
+ public override ISymbolNode NodeForLinkage(NodeFactory factory) => this;
//
// A cloned type must be named differently than the type it is a clone of so the linker
@@ -35,6 +35,6 @@ namespace ILCompiler.DependencyAnalysis
objData.EmitPointerReloc(factory.NecessaryTypeSymbol(_type));
}
- protected internal override int ClassCode => -288888778;
+ public override int ClassCode => -288888778;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CompilerComparer.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CompilerComparer.cs
index 2a564335e..250b32707 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CompilerComparer.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CompilerComparer.cs
@@ -10,9 +10,9 @@ using Internal.TypeSystem;
namespace ILCompiler.DependencyAnalysis
{
- public class CompilerComparer : TypeSystemComparer, IComparer<ISortableSymbolNode>
+ public class CompilerComparer : TypeSystemComparer, IComparer<ISortableNode>
{
- public int Compare(ISortableSymbolNode x, ISortableSymbolNode y)
+ public int Compare(ISortableNode x, ISortableNode y)
{
if (x == y)
{
@@ -35,7 +35,7 @@ namespace ILCompiler.DependencyAnalysis
else
{
Debug.Assert(x.GetType() != y.GetType());
- return codeX > codeY ? -1 : 1;
+ return codeY > codeX ? -1 : 1;
}
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs
index a835bc1f7..d145a8d26 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs
@@ -80,7 +80,7 @@ namespace ILCompiler.DependencyAnalysis
DefType closestDefType = _type.GetClosestDefType();
- if (_type.RuntimeInterfaces.Length > 0)
+ if (InterfaceDispatchMapNode.MightHaveInterfaceDispatchMap(_type, factory))
{
dependencyList.Add(factory.InterfaceDispatchMap(_type), "Interface dispatch map");
}
@@ -115,6 +115,22 @@ namespace ILCompiler.DependencyAnalysis
dependencyList.Add(factory.NativeLayout.TemplateTypeLayout(canonType), "Template Type Layout");
}
+ if (factory.TypeSystemContext.SupportsUniversalCanon)
+ {
+ foreach (var instantiationType in _type.Instantiation)
+ {
+ if (instantiationType.IsValueType)
+ {
+ // All valuetype generic parameters of a constructed type may be effectively constructed. This is generally not that
+ // critical, but in the presence of universal generics the compiler may generate a Box followed by calls to ToString,
+ // GetHashcode or Equals in ways that cannot otherwise be detected by dependency analysis. Thus force all struct type
+ // generic parameters to be considered constructed when walking dependencies of a constructed generic
+ dependencyList.Add(factory.ConstructedTypeSymbol(instantiationType.ConvertToCanonForm(CanonicalFormKind.Specific)),
+ "Struct generic parameters in constructed types may be assumed to be used as constructed in constructed generic types");
+ }
+ }
+ }
+
// Generated type contains generic virtual methods that will get added to the GVM tables
if (TypeGVMEntriesNode.TypeNeedsGVMTableEntries(_type))
{
@@ -135,6 +151,15 @@ namespace ILCompiler.DependencyAnalysis
factory.InteropStubManager.AddInterestingInteropConstructedTypeDependencies(ref dependencyList, factory, _type);
+ // Keep track of the default constructor map dependency for this type if it has a default constructor
+ MethodDesc defaultCtor = closestDefType.GetDefaultConstructor();
+ if (defaultCtor != null)
+ {
+ dependencyList.Add(new DependencyListEntry(
+ factory.MethodEntrypoint(defaultCtor.GetCanonMethodTarget(CanonicalFormKind.Specific), closestDefType.IsValueType),
+ "DefaultConstructorNode"));
+ }
+
return dependencyList;
}
@@ -179,10 +204,6 @@ namespace ILCompiler.DependencyAnalysis
if (type.IsCanonicalDefinitionType(CanonicalFormKind.Any))
return false;
- // Byref-like types have interior pointers and cannot be heap allocated.
- if (type.IsByRefLike)
- return false;
-
// The global "<Module>" type can never be allocated.
if (((MetadataType)type).IsModuleType)
return false;
@@ -199,6 +220,6 @@ namespace ILCompiler.DependencyAnalysis
ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
}
- protected internal override int ClassCode => 590142654;
+ public override int ClassCode => 590142654;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DefaultConstructorMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DefaultConstructorMapNode.cs
index 9f6735b88..bee2f4de6 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DefaultConstructorMapNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DefaultConstructorMapNode.cs
@@ -15,43 +15,6 @@ using ILCompiler.DependencyAnalysisFramework;
namespace ILCompiler.DependencyAnalysis
{
/// <summary>
- /// Dependency analysis node used to keep track of types needing an entry in the default
- /// constructor map hashtable
- /// </summary>
- internal sealed class DefaultConstructorFromLazyNode : DependencyNodeCore<NodeFactory>
- {
- public TypeDesc TypeNeedingDefaultCtor { get; }
-
- public DefaultConstructorFromLazyNode(TypeDesc type)
- {
- Debug.Assert(!type.IsRuntimeDeterminedSubtype);
- Debug.Assert(type == type.ConvertToCanonForm(CanonicalFormKind.Specific));
- Debug.Assert(type.GetDefaultConstructor() != null && !type.IsValueType);
-
- TypeNeedingDefaultCtor = type;
- }
-
- public override bool HasDynamicDependencies => false;
- public override bool HasConditionalStaticDependencies => false;
- public override bool InterestingForDynamicDependencyAnalysis => false;
- public override bool StaticDependenciesAreComputed => true;
- protected override string GetName(NodeFactory factory) => "__DefaultConstructorFromLazyNode_" + factory.NameMangler.GetMangledTypeName(TypeNeedingDefaultCtor);
- public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory context) => null;
- public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null;
-
- public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory context)
- {
- yield return new DependencyListEntry(
- context.MaximallyConstructableType(TypeNeedingDefaultCtor),
- "DefaultConstructorNode type");
-
- yield return new DependencyListEntry(
- context.MethodEntrypoint(TypeNeedingDefaultCtor.GetDefaultConstructor(), TypeNeedingDefaultCtor.IsValueType),
- "DefaultConstructorNode");
- }
- }
-
- /// <summary>
/// DefaultConstructorMap blob, containing information on default constructor entrypoints of all types used
/// by lazy generic instantiations.
/// </summary>
@@ -80,7 +43,7 @@ namespace ILCompiler.DependencyAnalysis
public override bool StaticDependenciesAreComputed => true;
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.DefaultConstructorMapNode;
+ public override int ClassCode => (int)ObjectNodeOrder.DefaultConstructorMapNode;
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
@@ -96,19 +59,22 @@ namespace ILCompiler.DependencyAnalysis
Section defaultConstructorHashtableSection = writer.NewSection();
defaultConstructorHashtableSection.Place(defaultConstructorHashtable);
- foreach (var ctorNeeded in factory.MetadataManager.GetDefaultConstructorsNeeded())
+ foreach (var type in factory.MetadataManager.GetTypesWithConstructedEETypes())
{
- MethodDesc defaultCtor = ctorNeeded.TypeNeedingDefaultCtor.GetDefaultConstructor();
- Debug.Assert(defaultCtor != null);
+ MethodDesc defaultCtor = type.GetDefaultConstructor();
+ if (defaultCtor == null)
+ continue;
+
+ defaultCtor = defaultCtor.GetCanonMethodTarget(CanonicalFormKind.Specific);
- ISymbolNode typeNode = factory.NecessaryTypeSymbol(ctorNeeded.TypeNeedingDefaultCtor);
+ ISymbolNode typeNode = factory.NecessaryTypeSymbol(type);
ISymbolNode defaultCtorNode = factory.MethodEntrypoint(defaultCtor, false);
Vertex vertex = writer.GetTuple(
writer.GetUnsignedConstant(_externalReferences.GetIndex(typeNode)),
writer.GetUnsignedConstant(_externalReferences.GetIndex(defaultCtorNode)));
- int hashCode = ctorNeeded.TypeNeedingDefaultCtor.GetHashCode();
+ int hashCode = type.GetHashCode();
defaultConstructorHashtable.Append((uint)hashCode, defaultConstructorHashtableSection.Place(vertex));
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DelegateMarshallingStubMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DelegateMarshallingStubMapNode.cs
index 11318ad2f..95f9588aa 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DelegateMarshallingStubMapNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DelegateMarshallingStubMapNode.cs
@@ -77,6 +77,6 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.DelegateMarshallingStubMapNode;
+ public override int ClassCode => (int)ObjectNodeOrder.DelegateMarshallingStubMapNode;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DynamicInvokeTemplateDataNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DynamicInvokeTemplateDataNode.cs
index d18e2eb59..01070faa2 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DynamicInvokeTemplateDataNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DynamicInvokeTemplateDataNode.cs
@@ -124,6 +124,6 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.DynamicInvokeTemplateDataNode;
+ public override int ClassCode => (int)ObjectNodeOrder.DynamicInvokeTemplateDataNode;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs
index dc09feaf8..8db7d5547 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs
@@ -56,7 +56,7 @@ namespace ILCompiler.DependencyAnalysis
/// |
/// [Pointer Size] | Pointer to the generic argument and variance info (optional)
/// </summary>
- public partial class EETypeNode : ObjectNode, IExportableSymbolNode, IEETypeNode, ISymbolDefinitionNode
+ public partial class EETypeNode : ObjectNode, IExportableSymbolNode, IEETypeNode, ISymbolDefinitionNode, ISymbolNodeWithLinkage
{
protected TypeDesc _type;
internal EETypeOptionalFieldsBuilder _optionalFieldsBuilder = new EETypeOptionalFieldsBuilder();
@@ -90,9 +90,9 @@ namespace ILCompiler.DependencyAnalysis
return false;
}
- public override ObjectNode NodeForLinkage(NodeFactory factory)
+ public virtual ISymbolNode NodeForLinkage(NodeFactory factory)
{
- return (ObjectNode)factory.NecessaryTypeSymbol(_type);
+ return factory.NecessaryTypeSymbol(_type);
}
public ExportForm GetExportForm(NodeFactory factory) => factory.CompilationModuleGroup.GetExportTypeForm(Type);
@@ -385,7 +385,19 @@ namespace ILCompiler.DependencyAnalysis
if (EmitVirtualSlotsAndInterfaces)
{
+ if (!_type.IsArrayTypeWithoutGenericInterfaces())
+ {
+ // Sealed vtables have relative pointers, so to minimize size, we build sealed vtables for the canonical types
+ dependencies.Add(new DependencyListEntry(factory.SealedVTable(_type.ConvertToCanonForm(CanonicalFormKind.Specific)), "Sealed Vtable"));
+ }
+
AddVirtualMethodUseDependencies(dependencies, factory);
+
+ // Also add the un-normalized vtable slices of implemented interfaces.
+ // This is important to do in the scanning phase so that the compilation phase can find
+ // vtable information for things like IEnumerator<List<__Canon>>.
+ foreach (TypeDesc intface in _type.RuntimeInterfaces)
+ dependencies.Add(factory.VTable(intface), "Interface vtable slice");
}
if (factory.CompilationModuleGroup.PresenceOfEETypeImpliesAllMethodsOnType(_type))
@@ -470,6 +482,7 @@ namespace ILCompiler.DependencyAnalysis
OutputFinalizerMethod(factory, ref objData);
OutputOptionalFields(factory, ref objData);
OutputNullableTypeParameter(factory, ref objData);
+ OutputSealedVTable(factory, relocsOnly, ref objData);
OutputGenericInstantiationDetails(factory, ref objData);
return objData.ToObjectData();
@@ -690,7 +703,7 @@ namespace ILCompiler.DependencyAnalysis
}
}
- protected virtual void OutputVirtualSlots(NodeFactory factory, ref ObjectDataBuilder objData, TypeDesc implType, TypeDesc declType, TypeDesc templateType, bool relocsOnly)
+ private void OutputVirtualSlots(NodeFactory factory, ref ObjectDataBuilder objData, TypeDesc implType, TypeDesc declType, TypeDesc templateType, bool relocsOnly)
{
Debug.Assert(EmitVirtualSlotsAndInterfaces);
@@ -759,6 +772,11 @@ namespace ILCompiler.DependencyAnalysis
MethodDesc implMethod = implType.GetClosestDefType().FindVirtualFunctionTargetMethodOnObjectType(declMethod);
+ // Final NewSlot methods cannot be overridden, and therefore can be placed in the sealed-vtable to reduce the size of the vtable
+ // of this type and any type that inherits from it.
+ if (declMethod.CanMethodBeInSealedVTable() && !declType.IsArrayTypeWithoutGenericInterfaces())
+ continue;
+
if (!implMethod.IsAbstract)
{
MethodDesc canonImplMethod = implMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
@@ -812,11 +830,32 @@ namespace ILCompiler.DependencyAnalysis
}
}
+ private void OutputSealedVTable(NodeFactory factory, bool relocsOnly, ref ObjectDataBuilder objData)
+ {
+ if (EmitVirtualSlotsAndInterfaces && !_type.IsArrayTypeWithoutGenericInterfaces())
+ {
+ // Sealed vtables have relative pointers, so to minimize size, we build sealed vtables for the canonical types
+ SealedVTableNode sealedVTable = factory.SealedVTable(_type.ConvertToCanonForm(CanonicalFormKind.Specific));
+
+ if (sealedVTable.BuildSealedVTableSlots(factory, relocsOnly) && sealedVTable.NumSealedVTableEntries > 0)
+ {
+ if (factory.Target.SupportsRelativePointers)
+ objData.EmitReloc(sealedVTable, RelocType.IMAGE_REL_BASED_RELPTR32);
+ else
+ objData.EmitPointerReloc(sealedVTable);
+ }
+ }
+ }
+
private void OutputGenericInstantiationDetails(NodeFactory factory, ref ObjectDataBuilder objData)
{
if (_type.HasInstantiation && !_type.IsTypeDefinition)
{
- objData.EmitPointerRelocOrIndirectionReference(factory.NecessaryTypeSymbol(_type.GetTypeDefinition()));
+ IEETypeNode typeDefNode = factory.NecessaryTypeSymbol(_type.GetTypeDefinition());
+ if (factory.Target.SupportsRelativePointers)
+ objData.EmitRelativeRelocOrIndirectionReference(typeDefNode);
+ else
+ objData.EmitPointerRelocOrIndirectionReference(typeDefNode);
GenericCompositionDetails details;
if (_type.GetTypeDefinition() == factory.ArrayOfTEnumeratorType)
@@ -834,7 +873,11 @@ namespace ILCompiler.DependencyAnalysis
else
details = new GenericCompositionDetails(_type);
- objData.EmitPointerReloc(factory.GenericComposition(details));
+ ISymbolNode compositionNode = factory.GenericComposition(details);
+ if (factory.Target.SupportsRelativePointers)
+ objData.EmitReloc(compositionNode, RelocType.IMAGE_REL_BASED_RELPTR32);
+ else
+ objData.EmitPointerReloc(compositionNode);
}
}
@@ -843,19 +886,19 @@ namespace ILCompiler.DependencyAnalysis
/// </summary>
protected internal virtual void ComputeOptionalEETypeFields(NodeFactory factory, bool relocsOnly)
{
- if (!relocsOnly && _type.RuntimeInterfaces.Length > 0 && factory.InterfaceDispatchMap(_type).Marked)
+ if (!relocsOnly && EmitVirtualSlotsAndInterfaces && InterfaceDispatchMapNode.MightHaveInterfaceDispatchMap(_type, factory))
{
_optionalFieldsBuilder.SetFieldValue(EETypeOptionalFieldTag.DispatchMap, checked((uint)factory.InterfaceDispatchMapIndirection(Type).IndexFromBeginningOfArray));
}
- ComputeRareFlags(factory);
+ ComputeRareFlags(factory, relocsOnly);
ComputeNullableValueOffset();
if (!relocsOnly)
ComputeICastableVirtualMethodSlots(factory);
ComputeValueTypeFieldPadding();
}
- void ComputeRareFlags(NodeFactory factory)
+ void ComputeRareFlags(NodeFactory factory, bool relocsOnly)
{
uint flags = 0;
@@ -882,7 +925,12 @@ namespace ILCompiler.DependencyAnalysis
flags |= (uint)EETypeRareFlags.RequiresAlign8Flag;
}
- if (metadataType != null && metadataType.IsHfa)
+ TargetArchitecture targetArch = _type.Context.Target.Architecture;
+ if (metadataType != null &&
+ (targetArch == TargetArchitecture.ARM ||
+ targetArch == TargetArchitecture.ARMEL ||
+ targetArch == TargetArchitecture.ARM64) &&
+ metadataType.IsHfa)
{
flags |= (uint)EETypeRareFlags.IsHFAFlag;
}
@@ -897,6 +945,13 @@ namespace ILCompiler.DependencyAnalysis
flags |= (uint)EETypeRareFlags.IsByRefLikeFlag;
}
+ if (EmitVirtualSlotsAndInterfaces && !_type.IsArrayTypeWithoutGenericInterfaces())
+ {
+ SealedVTableNode sealedVTable = factory.SealedVTable(_type.ConvertToCanonForm(CanonicalFormKind.Specific));
+ if (sealedVTable.BuildSealedVTableSlots(factory, relocsOnly) && sealedVTable.NumSealedVTableEntries > 0)
+ flags |= (uint)EETypeRareFlags.HasSealedVTableEntriesFlag;
+ }
+
if (flags != 0)
{
_optionalFieldsBuilder.SetFieldValue(EETypeOptionalFieldTag.RareFlags, flags);
@@ -945,13 +1000,14 @@ namespace ILCompiler.DependencyAnalysis
MethodDesc isInstMethodImpl = _type.ResolveInterfaceMethodTarget(isInstDecl);
MethodDesc getImplTypeMethodImpl = _type.ResolveInterfaceMethodTarget(getImplTypeDecl);
- int isInstMethodSlot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, isInstMethodImpl);
- int getImplTypeMethodSlot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, getImplTypeMethodImpl);
-
- Debug.Assert(isInstMethodSlot != -1 && getImplTypeMethodSlot != -1);
+ int isInstMethodSlot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, isInstMethodImpl, _type);
+ int getImplTypeMethodSlot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, getImplTypeMethodImpl, _type);
- _optionalFieldsBuilder.SetFieldValue(EETypeOptionalFieldTag.ICastableIsInstSlot, (uint)isInstMethodSlot);
- _optionalFieldsBuilder.SetFieldValue(EETypeOptionalFieldTag.ICastableGetImplTypeSlot, (uint)getImplTypeMethodSlot);
+ // Slots are usually -1, since these methods are usually in the sealed vtable of the base type.
+ if (isInstMethodSlot != -1)
+ _optionalFieldsBuilder.SetFieldValue(EETypeOptionalFieldTag.ICastableIsInstSlot, (uint)isInstMethodSlot);
+ if (getImplTypeMethodSlot != -1)
+ _optionalFieldsBuilder.SetFieldValue(EETypeOptionalFieldTag.ICastableGetImplTypeSlot, (uint)getImplTypeMethodSlot);
}
}
}
@@ -1200,20 +1256,13 @@ namespace ILCompiler.DependencyAnalysis
}
}
- protected internal override int ClassCode => 1521789141;
+ public override int ClassCode => 1521789141;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_type, ((EETypeNode)other)._type);
}
- int ISortableSymbolNode.ClassCode => ClassCode;
-
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
- {
- return CompareToImpl((ObjectNode)other, comparer);
- }
-
private struct SlotCounter
{
private int _startBytes;
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs
index 0cc9ef205..dbcaf76cf 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs
@@ -51,7 +51,7 @@ namespace ILCompiler.DependencyAnalysis
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly);
- objData.RequireInitialPointerAlignment();
+ objData.RequireInitialAlignment(1);
objData.AddSymbol(this);
if (!relocsOnly)
@@ -63,9 +63,9 @@ namespace ILCompiler.DependencyAnalysis
return objData.ToObjectData();
}
- protected internal override int ClassCode => 821718028;
+ public override int ClassCode => 821718028;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return SortableDependencyNode.CompareImpl(_owner, ((EETypeOptionalFieldsNode)other)._owner, comparer);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedDataContainerNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedDataContainerNode.cs
index bc9d9975d..0cffffac1 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedDataContainerNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedDataContainerNode.cs
@@ -26,9 +26,9 @@ namespace ILCompiler.DependencyAnalysis
_endSymbol = new ObjectAndOffsetSymbolNode(this, 0, endSymbolMangledName, true);
}
- protected internal override int ClassCode => -1410622237;
+ public override int ClassCode => -1410622237;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return _startSymbolMangledName.CompareTo(((EmbeddedDataContainerNode)other)._startSymbolMangledName);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs
index 766a73706..45d05c9bc 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs
@@ -47,9 +47,9 @@ namespace ILCompiler.DependencyAnalysis
Target.AppendMangledName(nameMangler, sb);
}
- int ISortableSymbolNode.ClassCode => -2055384490;
+ public override int ClassCode => -2055384490;
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_targetNode, ((EmbeddedPointerIndirectionNode<TTarget>)other)._targetNode);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs
index d1dffa4b0..b4bf6659e 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs
@@ -152,6 +152,6 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.ExactMethodInstantiationsNode;
+ public override int ClassCode => (int)ObjectNodeOrder.ExactMethodInstantiationsNode;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternMethodSymbolNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternMethodSymbolNode.cs
index 7602151b9..8efd6fe27 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternMethodSymbolNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternMethodSymbolNode.cs
@@ -28,5 +28,7 @@ namespace ILCompiler.DependencyAnalysis
return _method;
}
}
+
+ public override int ClassCode => -729061105;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternSymbolNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternSymbolNode.cs
index f35a57d1c..0aee4c8db 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternSymbolNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternSymbolNode.cs
@@ -14,7 +14,7 @@ namespace ILCompiler.DependencyAnalysis
/// <summary>
/// Represents a symbol that is defined externally and statically linked to the output obj file.
/// </summary>
- public class ExternSymbolNode : DependencyNodeCore<NodeFactory>, ISortableSymbolNode
+ public class ExternSymbolNode : SortableDependencyNode, ISortableSymbolNode
{
private Utf8String _name;
@@ -42,9 +42,9 @@ namespace ILCompiler.DependencyAnalysis
public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null;
#if !SUPPORT_JIT
- int ISortableSymbolNode.ClassCode => 1092559304;
+ public override int ClassCode => 1092559304;
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return _name.CompareTo(((ExternSymbolNode)other)._name);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternalReferencesTableNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternalReferencesTableNode.cs
index 84c17aab5..d37a4be95 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternalReferencesTableNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternalReferencesTableNode.cs
@@ -123,9 +123,8 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.ExternalReferencesTableNode;
-
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int ClassCode => (int)ObjectNodeOrder.ExternalReferencesTableNode;
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return string.Compare(_blobName, ((ExternalReferencesTableNode)other)._blobName);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FatFunctionPointerNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FatFunctionPointerNode.cs
index a4127e63d..3016536ce 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FatFunctionPointerNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FatFunctionPointerNode.cs
@@ -97,9 +97,9 @@ namespace ILCompiler.DependencyAnalysis
return builder.ToObjectData();
}
- protected internal override int ClassCode => 190463489;
+ public override int ClassCode => 190463489;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
var compare = _isUnboxingStub.CompareTo(((FatFunctionPointerNode)other)._isUnboxingStub);
if (compare != 0)
@@ -107,12 +107,5 @@ namespace ILCompiler.DependencyAnalysis
return comparer.Compare(Method, ((FatFunctionPointerNode)other).Method);
}
-
- int ISortableSymbolNode.ClassCode => ClassCode;
-
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
- {
- return CompareToImpl((ObjectNode)other, comparer);
- }
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FrozenArrayNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FrozenArrayNode.cs
index 23b0992bd..8d210f5c1 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FrozenArrayNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FrozenArrayNode.cs
@@ -101,9 +101,9 @@ namespace ILCompiler.DependencyAnalysis
factory.FrozenSegmentRegion.AddEmbeddedObject(this);
}
- protected internal override int ClassCode => 1789429316;
+ public override int ClassCode => 1789429316;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return _preInitFieldInfo.CompareTo(((FrozenArrayNode)other)._preInitFieldInfo, comparer);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FrozenStringNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FrozenStringNode.cs
index 1fa63fc51..f1b3467c2 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FrozenStringNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FrozenStringNode.cs
@@ -91,9 +91,9 @@ namespace ILCompiler.DependencyAnalysis
factory.FrozenSegmentRegion.AddEmbeddedObject(this);
}
- protected internal override int ClassCode => -1733946122;
+ public override int ClassCode => -1733946122;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return string.CompareOrdinal(_data, ((FrozenStringNode)other)._data);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticDescNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticDescNode.cs
index 07d482d3e..4ff2e737a 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticDescNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticDescNode.cs
@@ -13,7 +13,7 @@ using Debug = System.Diagnostics.Debug;
namespace ILCompiler.DependencyAnalysis
{
- public class GCStaticDescNode : EmbeddedObjectNode, ISymbolDefinitionNode
+ public class GCStaticDescNode : EmbeddedObjectNode, ISymbolDefinitionNode, ISortableSymbolNode
{
private MetadataType _type;
private GCPointerMap _gcMap;
@@ -177,21 +177,23 @@ namespace ILCompiler.DependencyAnalysis
return compare != 0 ? compare : comparer.Compare(_type, other._type);
}
- protected internal override int ClassCode => 2142332918;
-
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public sealed override int ClassCode => 2142332918;
+
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
- return comparer.Compare(_type, ((GCStaticDescNode)other)._type);
+ return CompareTo((GCStaticDescNode)other, comparer);
}
}
public class GCStaticDescRegionNode : ArrayOfEmbeddedDataNode<GCStaticDescNode>
{
- public GCStaticDescRegionNode(string startSymbolMangledName, string endSymbolMangledName)
- : base(startSymbolMangledName, endSymbolMangledName, null)
+ public GCStaticDescRegionNode(string startSymbolMangledName, string endSymbolMangledName, IComparer<GCStaticDescNode> nodeSorter)
+ : base(startSymbolMangledName, endSymbolMangledName, nodeSorter)
{
}
+ public override int ClassCode => 1312891560;
+
protected override void GetElementDataForNodes(ref ObjectDataBuilder builder, NodeFactory factory, bool relocsOnly)
{
int numSeries = 0;
@@ -246,9 +248,9 @@ namespace ILCompiler.DependencyAnalysis
return "Standalone" + _standaloneGCStaticDesc.GetMangledName(context.NameMangler);
}
- protected internal override int ClassCode => 2091208431;
+ public override int ClassCode => 2091208431;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return _standaloneGCStaticDesc.CompareTo(((StandaloneGCStaticDescRegionNode)other)._standaloneGCStaticDesc, comparer);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticEETypeNode.cs
index bea0665cd..570974205 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticEETypeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticEETypeNode.cs
@@ -69,7 +69,7 @@ namespace ILCompiler.DependencyAnalysis
dataBuilder.AddSymbol(this);
// +1 for SyncBlock (in CoreRT static size already includes EEType)
- Debug.Assert(factory.Target.Abi == TargetAbi.CoreRT);
+ Debug.Assert(factory.Target.Abi == TargetAbi.CoreRT || factory.Target.Abi == TargetAbi.CppCodegen);
int totalSize = (_gcMap.Size + 1) * _target.PointerSize;
// We only need to check for containsPointers because ThreadStatics are always allocated
@@ -101,9 +101,9 @@ namespace ILCompiler.DependencyAnalysis
return dataBuilder.ToObjectData();
}
- protected internal override int ClassCode => 1304929125;
+ public override int ClassCode => 1304929125;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return _gcMap.CompareTo(((GCStaticEETypeNode)other)._gcMap);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsNode.cs
index 814ea9756..39d886e5e 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsNode.cs
@@ -12,7 +12,7 @@ using GCStaticRegionConstants = Internal.Runtime.GCStaticRegionConstants;
namespace ILCompiler.DependencyAnalysis
{
- public class GCStaticsNode : ObjectNode, IExportableSymbolNode, ISortableSymbolNode
+ public class GCStaticsNode : ObjectNode, IExportableSymbolNode, ISortableSymbolNode, ISymbolNodeWithDebugInfo
{
private MetadataType _type;
private List<PreInitFieldInfo> _preInitFieldInfos;
@@ -34,6 +34,8 @@ namespace ILCompiler.DependencyAnalysis
public int Offset => 0;
public MetadataType Type => _type;
+ public IDebugInfo DebugInfo => NullTypeIndexDebugInfo.Instance;
+
public static string GetMangledName(TypeDesc type, NameMangler nameMangler)
{
return nameMangler.NodeMangler.GCStatics(type);
@@ -63,7 +65,7 @@ namespace ILCompiler.DependencyAnalysis
}
dependencyList.Add(factory.GCStaticsRegion, "GCStatics Region");
- if (factory.Target.Abi == TargetAbi.CoreRT)
+ if (factory.Target.Abi != TargetAbi.ProjectN)
{
dependencyList.Add(GetGCStaticEETypeNode(factory), "GCStatic EEType");
if (_preInitFieldInfos != null)
@@ -130,18 +132,11 @@ namespace ILCompiler.DependencyAnalysis
}
}
- protected internal override int ClassCode => -522346696;
+ public override int ClassCode => -522346696;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_type, ((GCStaticsNode)other)._type);
}
-
- int ISortableSymbolNode.ClassCode => ClassCode;
-
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
- {
- return CompareToImpl((ObjectNode)other, comparer);
- }
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsPreInitDataNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsPreInitDataNode.cs
index 653a18fa0..e78801952 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsPreInitDataNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsPreInitDataNode.cs
@@ -113,9 +113,9 @@ namespace ILCompiler.DependencyAnalysis
return builder.ToObjectData();
}
- protected internal override int ClassCode => 1148300665;
+ public override int ClassCode => 1148300665;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_type, ((GCStaticsPreInitDataNode)other)._type);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericCompositionNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericCompositionNode.cs
index cff9f3746..8d4c161fc 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericCompositionNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericCompositionNode.cs
@@ -100,8 +100,8 @@ namespace ILCompiler.DependencyAnalysis
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
- protected internal override int ClassCode => -762680703;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int ClassCode => -762680703;
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return _details.CompareToImpl(((GenericCompositionNode)other)._details, comparer);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDefinitionEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDefinitionEETypeNode.cs
index d40972210..243d94cd6 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDefinitionEETypeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDefinitionEETypeNode.cs
@@ -76,6 +76,6 @@ namespace ILCompiler.DependencyAnalysis
return dataBuilder.ToObjectData();
}
- protected internal override int ClassCode => -160325006;
+ public override int ClassCode => -160325006;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDictionaryNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDictionaryNode.cs
index 8ebdfa051..211ac3a1f 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDictionaryNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDictionaryNode.cs
@@ -86,9 +86,9 @@ namespace ILCompiler.DependencyAnalysis
return this.GetMangledName(factory.NameMangler);
}
- int ISortableSymbolNode.ClassCode => ClassCode;
+ public override int ClassCode => ClassCode;
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return CompareToImpl((ObjectNode)other, comparer);
}
@@ -134,11 +134,11 @@ namespace ILCompiler.DependencyAnalysis
foreach (var arg in _owningType.Instantiation)
{
// Skip types that do not have a default constructor (not interesting).
- if (arg.IsValueType || arg.GetDefaultConstructor() == null)
+ if (arg.IsValueType || arg.GetDefaultConstructor() == null || !ConstructedEETypeNode.CreationAllowed(arg))
continue;
result.Add(new DependencyListEntry(
- factory.DefaultConstructorFromLazy(arg.ConvertToCanonForm(CanonicalFormKind.Specific)),
+ factory.ConstructedTypeSymbol(arg.ConvertToCanonForm(CanonicalFormKind.Specific)),
"Default constructor for lazy generics"));
}
}
@@ -176,9 +176,9 @@ namespace ILCompiler.DependencyAnalysis
_owningType = owningType;
}
- protected internal override int ClassCode => 889700584;
+ public override int ClassCode => 889700584;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_owningType, ((TypeGenericDictionaryNode)other)._owningType);
}
@@ -218,21 +218,21 @@ namespace ILCompiler.DependencyAnalysis
foreach (var arg in _owningMethod.OwningType.Instantiation)
{
// Skip types that do not have a default constructor (not interesting).
- if (arg.IsValueType || arg.GetDefaultConstructor() == null)
+ if (arg.IsValueType || arg.GetDefaultConstructor() == null || !ConstructedEETypeNode.CreationAllowed(arg))
continue;
dependencies.Add(new DependencyListEntry(
- factory.DefaultConstructorFromLazy(arg.ConvertToCanonForm(CanonicalFormKind.Specific)),
+ factory.ConstructedTypeSymbol(arg.ConvertToCanonForm(CanonicalFormKind.Specific)),
"Default constructor for lazy generics"));
}
foreach (var arg in _owningMethod.Instantiation)
{
// Skip types that do not have a default constructor (not interesting).
- if (arg.IsValueType || arg.GetDefaultConstructor() == null)
+ if (arg.IsValueType || arg.GetDefaultConstructor() == null || !ConstructedEETypeNode.CreationAllowed(arg))
continue;
dependencies.Add(new DependencyListEntry(
- factory.DefaultConstructorFromLazy(arg.ConvertToCanonForm(CanonicalFormKind.Specific)),
+ factory.ConstructedTypeSymbol(arg.ConvertToCanonForm(CanonicalFormKind.Specific)),
"Default constructor for lazy generics"));
}
}
@@ -277,9 +277,9 @@ namespace ILCompiler.DependencyAnalysis
_owningMethod = owningMethod;
}
- protected internal override int ClassCode => -1245704203;
+ public override int ClassCode => -1245704203;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_owningMethod, ((MethodGenericDictionaryNode)other)._owningMethod);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs
index bb6d87553..efbe77897 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs
@@ -126,6 +126,6 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.GenericMethodsHashtableNode;
+ public override int ClassCode => (int)ObjectNodeOrder.GenericMethodsHashtableNode;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs
index 5f48eff37..c4a743219 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs
@@ -118,6 +118,6 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.GenericMethodsTemplateMap;
+ public override int ClassCode => (int)ObjectNodeOrder.GenericMethodsTemplateMap;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesHashtableNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesHashtableNode.cs
index 0d9907e9f..0bf0f3850 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesHashtableNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesHashtableNode.cs
@@ -68,6 +68,6 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.GenericTypesHashtableNode;
+ public override int ClassCode => (int)ObjectNodeOrder.GenericTypesHashtableNode;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs
index 812a2a3fb..c01bfae12 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs
@@ -160,6 +160,6 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.GenericTypesTemplateMap;
+ public override int ClassCode => (int)ObjectNodeOrder.GenericTypesTemplateMap;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs
index 69e35880d..18f727a69 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs
@@ -145,6 +145,6 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.GenericVirtualMethodTableNode;
+ public override int ClassCode => (int)ObjectNodeOrder.GenericVirtualMethodTableNode;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ILScanNodeFactory.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ILScanNodeFactory.cs
index 6f061c02f..3069c5f53 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ILScanNodeFactory.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ILScanNodeFactory.cs
@@ -63,7 +63,7 @@ namespace ILCompiler.DependencyAnalysis
// 'this' and also provides an instantiation argument (we do a calling convention conversion).
// We don't do this for generic instance methods though because they don't use the EEType
// for the generic context anyway.
- return new ScannedMethodNode(TypeSystemContext.GetSpecialUnboxingThunk(method, CompilationModuleGroup.GeneratedAssembly));
+ return new ScannedMethodNode(TypeSystemContext.GetSpecialUnboxingThunk(method, TypeSystemContext.GeneratedAssembly));
}
else
{
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IMethodCodeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IMethodCodeNode.cs
index 8a5e8d7f4..3aaece4d1 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IMethodCodeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IMethodCodeNode.cs
@@ -14,5 +14,6 @@ namespace ILCompiler.DependencyAnalysis
void InitializeEHInfo(ObjectNode.ObjectData ehInfo);
void InitializeDebugLocInfos(DebugLocInfo[] debugLocInfos);
void InitializeDebugVarInfos(DebugVarInfo[] debugVarInfos);
+ void InitializeDebugEHClauseInfos(DebugEHClauseInfo[] debugEHClauseInfos);
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/INodeWithCodeInfo.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/INodeWithCodeInfo.cs
index 48b48e656..c1b293b02 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/INodeWithCodeInfo.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/INodeWithCodeInfo.cs
@@ -33,6 +33,22 @@ namespace ILCompiler.DependencyAnalysis
}
}
+ public struct DebugEHClauseInfo
+ {
+ public uint TryOffset;
+ public uint TryLength;
+ public uint HandlerOffset;
+ public uint HandlerLength;
+
+ public DebugEHClauseInfo(uint tryOffset, uint tryLength, uint handlerOffset, uint handlerLength)
+ {
+ TryOffset = tryOffset;
+ TryLength = tryLength;
+ HandlerOffset = handlerOffset;
+ HandlerLength = handlerLength;
+ }
+ }
+
public interface INodeWithCodeInfo
{
FrameInfo[] FrameInfos
@@ -45,6 +61,11 @@ namespace ILCompiler.DependencyAnalysis
get;
}
+ DebugEHClauseInfo[] DebugEHClauseInfos
+ {
+ get;
+ }
+
ObjectNode.ObjectData EHInfo
{
get;
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ISortableNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ISortableNode.cs
new file mode 100644
index 000000000..ac62439b0
--- /dev/null
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ISortableNode.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace ILCompiler.DependencyAnalysis
+{
+ public interface ISortableNode
+ {
+#if !SUPPORT_JIT
+ /// <summary>
+ /// Gets an identifier that is the same for all instances of this <see cref="ObjectNode"/>
+ /// descendant, but different from the <see cref="ClassCode"/> of any other descendant.
+ /// </summary>
+ /// <remarks>
+ /// This is really just a number, ideally produced by "new Random().Next(int.MinValue, int.MaxValue)".
+ /// If two manage to conflict (which is pretty unlikely), just make a new one...
+ /// </remarks>
+ int ClassCode { get; }
+
+ int CompareToImpl(ISortableNode other, CompilerComparer comparer);
+#endif
+ }
+}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ISymbolNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ISymbolNode.cs
index af38e11d6..feca8b45e 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ISymbolNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ISymbolNode.cs
@@ -32,13 +32,19 @@ namespace ILCompiler.DependencyAnalysis
bool RepresentsIndirectionCell { get; }
}
+ /// <summary>
+ /// Represents a symbol backed by a different symbol for object emission purposes.
+ /// </summary>
+ public interface ISymbolNodeWithLinkage : ISymbolNode
+ {
+ /// <summary>
+ /// Return a node that is used for linkage
+ /// </summary>
+ ISymbolNode NodeForLinkage(NodeFactory factory);
+ }
- public interface ISortableSymbolNode : ISymbolNode
+ public interface ISortableSymbolNode : ISymbolNode, ISortableNode
{
-#if !SUPPORT_JIT
- int ClassCode { get; }
- int CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer);
-#endif
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ISymbolNodeWithDebugInfo.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ISymbolNodeWithDebugInfo.cs
new file mode 100644
index 000000000..971cf7016
--- /dev/null
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ISymbolNodeWithDebugInfo.cs
@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using ILCompiler.DependencyAnalysisFramework;
+using Internal.Text;
+
+namespace ILCompiler.DependencyAnalysis
+{
+ /// <summary>
+ /// Represents a symbol definition with debug info, i.e., the S_GDATA32 record.
+ /// </summary>
+ public interface ISymbolNodeWithDebugInfo : ISymbolDefinitionNode
+ {
+ IDebugInfo DebugInfo { get; }
+ }
+
+ public interface IDebugInfo
+ { }
+
+ public interface ITypeIndexDebugInfo : IDebugInfo
+ {
+ int TypeIndex { get; }
+ }
+
+ public class NullTypeIndexDebugInfo : ITypeIndexDebugInfo
+ {
+ private NullTypeIndexDebugInfo() { }
+
+ public int TypeIndex => 0;
+
+ public static IDebugInfo Instance
+ {
+ get { return new NullTypeIndexDebugInfo(); }
+ }
+ }
+}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ImportedEETypeSymbolNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ImportedEETypeSymbolNode.cs
index 1918de4af..e8138f95e 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ImportedEETypeSymbolNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ImportedEETypeSymbolNode.cs
@@ -31,5 +31,7 @@ namespace ILCompiler.DependencyAnalysis
return _type;
}
}
+
+ public override int ClassCode => 395643063;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IndirectionExtensions.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IndirectionExtensions.cs
new file mode 100644
index 000000000..9265f94f8
--- /dev/null
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IndirectionExtensions.cs
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.Runtime;
+using Internal.TypeSystem;
+
+using Debug = System.Diagnostics.Debug;
+
+namespace ILCompiler.DependencyAnalysis
+{
+ static class IndirectionExtensions
+ {
+ /// <summary>
+ /// Use this api to generate a reloc to a symbol that may be an indirection cell or not as a pointer
+ /// </summary>
+ /// <param name="symbol">symbol to reference</param>
+ /// <param name="indirectionBit">value to OR in to the reloc to represent to runtime code that this pointer is an indirection. Defaults to IndirectionConstants.IndirectionCellPointer</param>
+ /// <param name="delta">Delta from symbol start for value</param>
+ public static void EmitPointerRelocOrIndirectionReference(ref this ObjectDataBuilder builder, ISymbolNode symbol, int delta = 0, int indirectionBit = IndirectionConstants.IndirectionCellPointer)
+ {
+ if (symbol.RepresentsIndirectionCell)
+ delta |= indirectionBit;
+
+ builder.EmitReloc(symbol, (builder.TargetPointerSize == 8) ? RelocType.IMAGE_REL_BASED_DIR64 : RelocType.IMAGE_REL_BASED_HIGHLOW, delta);
+ }
+
+ public static void EmitRelativeRelocOrIndirectionReference(ref this ObjectDataBuilder builder, ISymbolNode symbol, int delta = 0, int indirectionBit = IndirectionConstants.IndirectionCellPointer)
+ {
+ if (symbol.RepresentsIndirectionCell)
+ delta = delta | indirectionBit;
+
+ builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_RELPTR32, delta);
+ }
+ }
+}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IndirectionNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IndirectionNode.cs
index 77bd897ea..f21986979 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IndirectionNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IndirectionNode.cs
@@ -61,11 +61,11 @@ namespace ILCompiler.DependencyAnalysis
return builder.ToObjectData();
}
- protected internal override int ClassCode => -1401349230;
+ public override int ClassCode => -1401349230;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
- return comparer.Compare(this._indirectedNode, ((IndirectionNode)other)._indirectedNode);
+ return comparer.Compare(_indirectedNode, ((IndirectionNode)other)._indirectedNode);
}
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs
index a5c49fc66..4bcd90215 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Collections.Generic;
using System.Diagnostics;
using Internal.Runtime;
@@ -10,11 +11,15 @@ using Internal.TypeSystem;
namespace ILCompiler.DependencyAnalysis
{
- public class InterfaceDispatchCellNode : ObjectNode, ISymbolDefinitionNode
+ public class InterfaceDispatchCellNode : EmbeddedObjectNode, ISymbolDefinitionNode
{
private readonly MethodDesc _targetMethod;
private readonly string _callSiteIdentifier;
+ internal MethodDesc TargetMethod => _targetMethod;
+
+ internal string CallSiteIdentifier => _callSiteIdentifier;
+
public InterfaceDispatchCellNode(MethodDesc targetMethod, string callSiteIdentifier)
{
Debug.Assert(targetMethod.OwningType.IsInterface);
@@ -27,7 +32,10 @@ namespace ILCompiler.DependencyAnalysis
{
sb.Append(GetMangledName(nameMangler, _targetMethod, _callSiteIdentifier));
}
- public int Offset => 0;
+
+ int ISymbolDefinitionNode.Offset => OffsetFromBeginningOfArray;
+
+ int ISymbolNode.Offset => 0;
public override bool IsShareable => false;
@@ -45,11 +53,9 @@ namespace ILCompiler.DependencyAnalysis
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
- public override ObjectNodeSection Section => ObjectNodeSection.DataSection;
-
public override bool StaticDependenciesAreComputed => true;
- protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
+ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
{
DependencyList result = new DependencyList();
@@ -59,18 +65,25 @@ namespace ILCompiler.DependencyAnalysis
}
factory.MetadataManager.GetDependenciesDueToVirtualMethodReflectability(ref result, factory, _targetMethod);
-
+
+ TargetArchitecture targetArchitecture = factory.Target.Architecture;
+ if (targetArchitecture == TargetArchitecture.ARM ||
+ targetArchitecture == TargetArchitecture.ARMEL)
+ {
+ result.Add(factory.InitialInterfaceDispatchStub, "Initial interface dispatch stub");
+ }
+ else
+ {
+ result.Add(factory.ExternSymbol("RhpInitialDynamicInterfaceDispatch"), "Initial interface dispatch stub");
+ }
+
+ result.Add(factory.NecessaryTypeSymbol(_targetMethod.OwningType), "Interface type");
+
return result;
}
- public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
+ public override void EncodeData(ref ObjectDataBuilder objData, NodeFactory factory, bool relocsOnly)
{
- ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly);
- // The interface dispatch cell has an alignment requirement of 2 * [Pointer size] as part of the
- // synchronization mechanism of the two values in the runtime.
- objData.RequireInitialAlignment(_targetMethod.Context.Target.PointerSize * 2);
- objData.AddSymbol(this);
-
TargetArchitecture targetArchitecture = factory.Target.Architecture;
if (targetArchitecture == TargetArchitecture.ARM ||
targetArchitecture == TargetArchitecture.ARMEL)
@@ -101,22 +114,16 @@ namespace ILCompiler.DependencyAnalysis
// 32 bits on targets whose pointer size is 64 bit.
objData.EmitInt(0);
}
+ }
- // End the run of dispatch cells
- objData.EmitZeroPointer();
-
- // Avoid consulting VTable slots until they're guaranteed complete during final data emission
- if (!relocsOnly)
- {
- objData.EmitNaturalInt(VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, _targetMethod));
- }
-
- return objData.ToObjectData();
+ protected override void OnMarked(NodeFactory factory)
+ {
+ factory.InterfaceDispatchCellSection.AddEmbeddedObject(this);
}
- protected internal override int ClassCode => -2023802120;
+ public override int ClassCode => -2023802120;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
var compare = comparer.Compare(_targetMethod, ((InterfaceDispatchCellNode)other)._targetMethod);
return compare != 0 ? compare : string.Compare(_callSiteIdentifier, ((InterfaceDispatchCellNode)other)._callSiteIdentifier);
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellSectionNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellSectionNode.cs
new file mode 100644
index 000000000..274a4254a
--- /dev/null
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellSectionNode.cs
@@ -0,0 +1,132 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+
+using Internal.TypeSystem;
+
+using Debug = System.Diagnostics.Debug;
+
+namespace ILCompiler.DependencyAnalysis
+{
+ /// <summary>
+ /// Represents a section of the executable where interface dispatch cells and their slot information
+ /// is stored.
+ /// </summary>
+ public class InterfaceDispatchCellSectionNode : ArrayOfEmbeddedDataNode<InterfaceDispatchCellNode>
+ {
+ public InterfaceDispatchCellSectionNode(NodeFactory factory)
+ : base("__InterfaceDispatchCellSection_Start", "__InterfaceDispatchCellSection_End", new DispatchCellComparer(factory))
+ {
+ }
+
+ protected override void GetElementDataForNodes(ref ObjectDataBuilder builder, NodeFactory factory, bool relocsOnly)
+ {
+ if (relocsOnly)
+ return;
+
+ // The interface dispatch cell has an alignment requirement of 2 * [Pointer size] as part of the
+ // synchronization mechanism of the two values in the runtime.
+ builder.RequireInitialAlignment(factory.Target.PointerSize * 2);
+
+ // This number chosen to be high enough that the cost of recording slot numbers is cheap.
+ const int InterfaceDispatchCellRunLength = 32;
+
+ const int NoSlot = -1;
+
+ //
+ // We emit the individual dispatch cells in groups. The purpose of the grouping is to save
+ // us the number of slots we need to emit. The grouping looks like this:
+ //
+ // DispatchCell1
+ // DispatchCell2
+ // ...
+ // DispatchCellN
+ // Null
+ // Slot of the above dispatch cells
+ //
+ int runLength = 0;
+ int currentSlot = NoSlot;
+ foreach (InterfaceDispatchCellNode node in NodesList)
+ {
+ MethodDesc targetMethod = node.TargetMethod;
+ int targetSlot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod, targetMethod.OwningType);
+ if (currentSlot == NoSlot)
+ {
+ // This is the first dispatch cell we're emitting
+ currentSlot = targetSlot;
+ }
+ else if (currentSlot != targetSlot || runLength == InterfaceDispatchCellRunLength)
+ {
+ // Make sure we are sorted
+ Debug.Assert(targetSlot >= currentSlot);
+
+ // End the run of dispatch cells
+ builder.EmitZeroPointer();
+ builder.EmitNaturalInt(currentSlot);
+
+ currentSlot = targetSlot;
+ runLength = 0;
+ }
+
+ node.InitializeOffsetFromBeginningOfArray(builder.CountBytes);
+ node.EncodeData(ref builder, factory, relocsOnly);
+ builder.AddSymbol(node);
+
+ runLength++;
+ }
+
+ if (runLength > 0)
+ {
+ // End the run of dispatch cells
+ builder.EmitZeroPointer();
+ builder.EmitNaturalInt(currentSlot);
+ }
+ }
+
+ public override int ClassCode => -1389343;
+
+ /// <summary>
+ /// Comparer that groups interface dispatch cells by their slot number.
+ /// </summary>
+ private class DispatchCellComparer : IComparer<InterfaceDispatchCellNode>
+ {
+ private readonly NodeFactory _factory;
+ private readonly TypeSystemComparer _comparer = new TypeSystemComparer();
+
+ public DispatchCellComparer(NodeFactory factory)
+ {
+ _factory = factory;
+ }
+
+ public int Compare(InterfaceDispatchCellNode x, InterfaceDispatchCellNode y)
+ {
+ MethodDesc methodX = x.TargetMethod;
+ MethodDesc methodY = y.TargetMethod;
+
+ // The primary purpose of this comparer is to sort everything by slot
+ int slotX = VirtualMethodSlotHelper.GetVirtualMethodSlot(_factory, methodX, methodX.OwningType);
+ int slotY = VirtualMethodSlotHelper.GetVirtualMethodSlot(_factory, methodY, methodY.OwningType);
+
+ int result = slotX - slotY;
+ if (result != 0)
+ return result;
+
+ // If slots are the same, compare the method and callsite identifier to get
+ // a deterministic order within the group.
+ result = _comparer.Compare(methodX, methodY);
+ if (result != 0)
+ return result;
+
+ result = StringComparer.Ordinal.Compare(x.CallSiteIdentifier, y.CallSiteIdentifier);
+ if (result != 0)
+ return result;
+
+ Debug.Assert(x == y);
+ return 0;
+ }
+ }
+ }
+}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs
index e2f6a6535..2da7c8d02 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs
@@ -15,8 +15,14 @@ namespace ILCompiler.DependencyAnalysis
{
TypeDesc _type;
- public InterfaceDispatchMapNode(TypeDesc type)
+ public InterfaceDispatchMapNode(NodeFactory factory, TypeDesc type)
{
+ // Multidimensional arrays should not get a sealed vtable or a dispatch map. Runtime should use the
+ // sealed vtable and dispatch map of the System.Array basetype instead.
+ // Pointer arrays also follow the same path
+ Debug.Assert(!type.IsArrayTypeWithoutGenericInterfaces());
+ Debug.Assert(MightHaveInterfaceDispatchMap(type, factory));
+
_type = type;
}
@@ -57,14 +63,71 @@ namespace ILCompiler.DependencyAnalysis
return result;
}
+ /// <summary>
+ /// Gets a value indicating whether '<paramref name="type"/>' might have a non-empty dispatch map.
+ /// Note that this is only an approximation because we might not be able to take into account
+ /// whether the interface methods are actually used.
+ /// </summary>
+ public static bool MightHaveInterfaceDispatchMap(TypeDesc type, NodeFactory factory)
+ {
+ if (type.IsArrayTypeWithoutGenericInterfaces())
+ return false;
+
+ if (!type.IsArray && !type.IsDefType)
+ return false;
+
+ TypeDesc declType = type.GetClosestDefType();
+
+ for (int interfaceIndex = 0; interfaceIndex < declType.RuntimeInterfaces.Length; interfaceIndex++)
+ {
+ DefType interfaceType = declType.RuntimeInterfaces[interfaceIndex];
+ InstantiatedType interfaceOnDefinitionType = interfaceType.IsTypeDefinition ?
+ null :
+ (InstantiatedType)declType.GetTypeDefinition().RuntimeInterfaces[interfaceIndex];
+
+ IEnumerable<MethodDesc> slots;
+
+ // If the vtable has fixed slots, we can query it directly.
+ // If it's a lazily built vtable, we might not be able to query slots
+ // just yet, so approximate by looking at all methods.
+ VTableSliceNode vtableSlice = factory.VTable(interfaceType);
+ if (vtableSlice.HasFixedSlots)
+ slots = vtableSlice.Slots;
+ else
+ slots = interfaceType.GetAllMethods();
+
+ foreach (MethodDesc slotMethod in slots)
+ {
+ MethodDesc declMethod = slotMethod;
+ if (interfaceOnDefinitionType != null)
+ declMethod = factory.TypeSystemContext.GetMethodForInstantiatedType(declMethod.GetTypicalMethodDefinition(), interfaceOnDefinitionType);
+
+ if (declMethod.Signature.IsStatic)
+ continue;
+
+ var implMethod = declType.GetTypeDefinition().ResolveInterfaceMethodToVirtualMethodOnType(declMethod);
+ if (implMethod != null)
+ return true;
+ }
+ }
+
+ return false;
+ }
+
void EmitDispatchMap(ref ObjectDataBuilder builder, NodeFactory factory)
{
var entryCountReservation = builder.ReserveInt();
int entryCount = 0;
-
- for (int interfaceIndex = 0; interfaceIndex < _type.RuntimeInterfaces.Length; interfaceIndex++)
+
+ TypeDesc declType = _type.GetClosestDefType();
+
+ // Catch any runtime interface collapsing. We shouldn't have any
+ Debug.Assert(declType.RuntimeInterfaces.Length == declType.GetTypeDefinition().RuntimeInterfaces.Length);
+
+ for (int interfaceIndex = 0; interfaceIndex < declType.RuntimeInterfaces.Length; interfaceIndex++)
{
- var interfaceType = _type.RuntimeInterfaces[interfaceIndex];
+ var interfaceType = declType.RuntimeInterfaces[interfaceIndex];
+ var interfaceDefinitionType = declType.GetTypeDefinition().RuntimeInterfaces[interfaceIndex];
Debug.Assert(interfaceType.IsInterface);
IReadOnlyList<MethodDesc> virtualSlots = factory.VTable(interfaceType).Slots;
@@ -72,15 +135,26 @@ namespace ILCompiler.DependencyAnalysis
for (int interfaceMethodSlot = 0; interfaceMethodSlot < virtualSlots.Count; interfaceMethodSlot++)
{
MethodDesc declMethod = virtualSlots[interfaceMethodSlot];
- var implMethod = _type.GetClosestDefType().ResolveInterfaceMethodToVirtualMethodOnType(declMethod);
+ if(!interfaceType.IsTypeDefinition)
+ declMethod = factory.TypeSystemContext.GetMethodForInstantiatedType(declMethod.GetTypicalMethodDefinition(), (InstantiatedType)interfaceDefinitionType);
+
+ var implMethod = declType.GetTypeDefinition().ResolveInterfaceMethodToVirtualMethodOnType(declMethod);
// Interface methods first implemented by a base type in the hierarchy will return null for the implMethod (runtime interface
// dispatch will walk the inheritance chain).
if (implMethod != null)
{
+ TypeDesc implType = declType;
+ while (!implType.HasSameTypeDefinition(implMethod.OwningType))
+ implType = implType.BaseType;
+
+ MethodDesc targetMethod = implMethod;
+ if (!implType.IsTypeDefinition)
+ targetMethod = factory.TypeSystemContext.GetMethodForInstantiatedType(implMethod.GetTypicalMethodDefinition(), (InstantiatedType)implType);
+
builder.EmitShort(checked((short)interfaceIndex));
builder.EmitShort(checked((short)(interfaceMethodSlot + (interfaceType.HasGenericDictionarySlot() ? 1 : 0))));
- builder.EmitShort(checked((short)VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, implMethod)));
+ builder.EmitShort(checked((short)VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod, declType)));
entryCount++;
}
}
@@ -103,18 +177,11 @@ namespace ILCompiler.DependencyAnalysis
return objData.ToObjectData();
}
- protected internal override int ClassCode => 848664602;
+ public override int ClassCode => 848664602;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_type, ((InterfaceDispatchMapNode)other)._type);
}
-
- int ISortableSymbolNode.ClassCode => ClassCode;
-
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
- {
- return CompareToImpl((ObjectNode)other, comparer);
- }
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs
index 4418d2984..38fc2bd52 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs
@@ -214,6 +214,6 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.InterfaceGenericVirtualMethodTableNode;
+ public override int ClassCode => (int)ObjectNodeOrder.InterfaceGenericVirtualMethodTableNode;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/JumpStubNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/JumpStubNode.cs
index abc13496c..811a1bea9 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/JumpStubNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/JumpStubNode.cs
@@ -23,6 +23,6 @@ namespace ILCompiler.DependencyAnalysis
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
- protected internal override int ClassCode => 737788182;
+ public override int ClassCode => 737788182;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/LoopHijackFlagNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/LoopHijackFlagNode.cs
index 69b1bd764..46d92a2ba 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/LoopHijackFlagNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/LoopHijackFlagNode.cs
@@ -35,7 +35,7 @@ namespace ILCompiler.DependencyAnalysis
public override bool StaticDependenciesAreComputed => true;
- protected internal override int ClassCode => -266743363;
+ public override int ClassCode => -266743363;
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MetadataNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MetadataNode.cs
index 246e804ce..fda760c8c 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MetadataNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MetadataNode.cs
@@ -58,6 +58,6 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.MetadataNode;
+ public override int ClassCode => (int)ObjectNodeOrder.MetadataNode;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodAssociatedDataNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodAssociatedDataNode.cs
index 46dacad9e..262d0799a 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodAssociatedDataNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodAssociatedDataNode.cs
@@ -41,9 +41,9 @@ namespace ILCompiler.DependencyAnalysis
public int Offset => 0;
public override bool IsShareable => _methodNode.Method is InstantiatedMethod || EETypeNode.IsTypeNodeShareable(_methodNode.Method.OwningType);
- protected internal override int ClassCode => 1055183914;
+ public override int ClassCode => 1055183914;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_methodNode, ((MethodAssociatedDataNode)other)._methodNode);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodCodeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodCodeNode.cs
index 69832904e..fc0efb910 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodCodeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodCodeNode.cs
@@ -24,6 +24,7 @@ namespace ILCompiler.DependencyAnalysis
private ObjectData _ehInfo;
private DebugLocInfo[] _debugLocInfos;
private DebugVarInfo[] _debugVarInfos;
+ private DebugEHClauseInfo[] _debugEHClauseInfos;
public MethodCodeNode(MethodDesc method)
{
@@ -140,6 +141,7 @@ namespace ILCompiler.DependencyAnalysis
public DebugLocInfo[] DebugLocInfos => _debugLocInfos;
public DebugVarInfo[] DebugVarInfos => _debugVarInfos;
+ public DebugEHClauseInfo[] DebugEHClauseInfos => _debugEHClauseInfos;
public void InitializeDebugLocInfos(DebugLocInfo[] debugLocInfos)
{
@@ -153,18 +155,17 @@ namespace ILCompiler.DependencyAnalysis
_debugVarInfos = debugVarInfos;
}
- protected internal override int ClassCode => 788492407;
-
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public void InitializeDebugEHClauseInfos(DebugEHClauseInfo[] debugEHClauseInfos)
{
- return comparer.Compare(_method, ((MethodCodeNode)other)._method);
+ Debug.Assert(_debugEHClauseInfos == null);
+ _debugEHClauseInfos = debugEHClauseInfos;
}
- int ISortableSymbolNode.ClassCode => ClassCode;
+ public override int ClassCode => 788492407;
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
- return CompareToImpl((ObjectNode)other, comparer);
+ return comparer.Compare(_method, ((MethodCodeNode)other)._method);
}
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ModulesSectionNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ModulesSectionNode.cs
index ed629af32..895138a10 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ModulesSectionNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ModulesSectionNode.cs
@@ -55,6 +55,6 @@ namespace ILCompiler.DependencyAnalysis
return objData.ToObjectData();
}
- protected internal override int ClassCode => -1225116970;
+ public override int ClassCode => -1225116970;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MrtImports.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MrtImports.cs
index e7bce493e..503667b2e 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MrtImports.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MrtImports.cs
@@ -23,42 +23,49 @@ namespace ILCompiler.DependencyAnalysis
{
public MrtImportedEETypeSymbolNode(TypeDesc type) : base(type) { }
protected override sealed string GetNonImportedName(NameMangler nameMangler) => nameMangler.NodeMangler.EEType(Type);
+ public override int ClassCode => 126598072;
}
public sealed class MrtImportedGCStaticSymbolNode : MrtImportWithTypeSymbol
{
public MrtImportedGCStaticSymbolNode(TypeDesc type) : base(type) { }
protected override sealed string GetNonImportedName(NameMangler nameMangler) => GCStaticsNode.GetMangledName(Type, nameMangler);
+ public override int ClassCode => 1974639431;
}
public sealed class MrtImportedNonGCStaticSymbolNode : MrtImportWithTypeSymbol
{
public MrtImportedNonGCStaticSymbolNode(TypeDesc type) : base(type) { }
protected override sealed string GetNonImportedName(NameMangler nameMangler) => NonGCStaticsNode.GetMangledName(Type, nameMangler);
+ public override int ClassCode => 257546392;
}
public sealed class MrtImportedThreadStaticOffsetSymbolNode : MrtImportWithTypeSymbol
{
public MrtImportedThreadStaticOffsetSymbolNode(TypeDesc type) : base(type) { }
protected override sealed string GetNonImportedName(NameMangler nameMangler) => ThreadStaticsOffsetNode.GetMangledName(nameMangler, Type);
+ public override int ClassCode => 1944978231;
}
public sealed class MrtImportedMethodDictionarySymbolNode : MrtImportWithMethodSymbol
{
public MrtImportedMethodDictionarySymbolNode(MethodDesc method) : base(method) { }
protected override sealed string GetNonImportedName(NameMangler nameMangler) => nameMangler.NodeMangler.MethodGenericDictionary(Method);
+ public override int ClassCode => 925274757;
}
public sealed class MrtImportedMethodCodeSymbolNode : MrtImportWithMethodSymbol, IMethodNode
{
public MrtImportedMethodCodeSymbolNode(MethodDesc method) : base(method) { }
protected override sealed string GetNonImportedName(NameMangler nameMangler) => nameMangler.GetMangledMethodName(Method).ToString();
+ public override int ClassCode => -454606757;
}
public sealed class MrtImportedUnboxingMethodCodeSymbolNode : MrtImportWithMethodSymbol, IMethodNode
{
public MrtImportedUnboxingMethodCodeSymbolNode(MethodDesc method) : base(method) { }
protected override sealed string GetNonImportedName(NameMangler nameMangler) => UnboxingStubNode.GetMangledName(nameMangler, Method);
+ public override int ClassCode => 1712079609;
}
public abstract class MrtImportWithTypeSymbol : MrtImportNode
@@ -153,7 +160,7 @@ namespace ILCompiler.DependencyAnalysis
public sealed override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) => null;
public sealed override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
MrtImportNode otherImportNode = (MrtImportNode)other;
@@ -164,7 +171,7 @@ namespace ILCompiler.DependencyAnalysis
return Ordinal - otherImportNode.Ordinal;
}
- protected internal override int ClassCode => 2017985192;
+ public override int ClassCode => 2017985192;
public sealed override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
{
@@ -180,13 +187,6 @@ namespace ILCompiler.DependencyAnalysis
_importTable.AddNode(this);
}
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
- {
- return CompareToImpl((SortableDependencyNode)other, comparer);
- }
-
- int ISortableSymbolNode.ClassCode => this.ClassCode;
-
void ISymbolNode.AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
AppendMangledName(nameMangler, sb);
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MrtProcessedExportAddressTableNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MrtProcessedExportAddressTableNode.cs
index 50c3e3a8f..40c60b8bd 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MrtProcessedExportAddressTableNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MrtProcessedExportAddressTableNode.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
+using System.Linq;
using System.Collections.Generic;
using Internal.Text;
@@ -24,7 +25,8 @@ namespace ILCompiler.DependencyAnalysis
_factory = factory;
}
- public event Action<int, IExportableSymbolNode> ReportExportedItem;
+ public event Func<uint, IExportableSymbolNode, uint> ReportExportedItem;
+ public event Func<uint> GetInitialExportOrdinal;
public void AddExportableSymbol(IExportableSymbolNode exportableSymbol)
{
@@ -68,6 +70,13 @@ namespace ILCompiler.DependencyAnalysis
builder.RequireInitialPointerAlignment();
builder.AddSymbol(this);
+ //
+ // Entries in the export table need to be sorted by ordinals. When compiling using baseline TOC files, we reuse
+ // the ordinals from the baseline for sorting, otherwise we start assigning new sequential ordinals. Export entries that do
+ // not exist in the baseline will get new sequential ordinals, but for determinism, they are also pre-sorted using the
+ // CompilerComparer logic
+ //
+
ISortableSymbolNode[] symbolNodes = new ISortableSymbolNode[_exportableSymbols.Count];
_exportableSymbols.CopyTo(symbolNodes);
Array.Sort(symbolNodes, new CompilerComparer());
@@ -75,30 +84,29 @@ namespace ILCompiler.DependencyAnalysis
builder.EmitInt(1); // Export table version 1
builder.EmitInt(symbolNodes.Length); // Count of exported symbols in this table
- int index = 1;
+ uint index = GetInitialExportOrdinal == null ? 1 : GetInitialExportOrdinal();
+ Dictionary<uint, ISortableSymbolNode> symbolsOridnalMap = new Dictionary<uint, ISortableSymbolNode>();
foreach (ISortableSymbolNode symbol in symbolNodes)
{
- builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_REL32);
- ReportExportedItem?.Invoke(index, (IExportableSymbolNode)symbol);
- index++;
+ uint indexUsed = ReportExportedItem.Invoke(index, (IExportableSymbolNode)symbol);
+ symbolsOridnalMap.Add(indexUsed, symbol);
+ index += (indexUsed == index ? (uint)1 : 0);
+ }
+
+ foreach (uint ordinal in symbolsOridnalMap.Keys.OrderBy(o => o))
+ {
+ builder.EmitReloc(symbolsOridnalMap[ordinal], RelocType.IMAGE_REL_BASED_REL32);
}
return builder.ToObjectData();
}
- protected internal override int ClassCode => 40423846;
+ public override int ClassCode => 40423846;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
Debug.Assert(Object.ReferenceEquals(other, this));
return 0; // There should only ever be one of these per dependency graph
}
-
- int ISortableSymbolNode.ClassCode => ClassCode;
-
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
- {
- return CompareToImpl((ObjectNode)other, comparer);
- }
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MrtProcessedImportAddressTableNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MrtProcessedImportAddressTableNode.cs
index e72126588..c2c9b53d9 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MrtProcessedImportAddressTableNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MrtProcessedImportAddressTableNode.cs
@@ -113,14 +113,7 @@ namespace ILCompiler.DependencyAnalysis
return dependencies;
}
- protected internal override int ClassCode => -1145565068;
-
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
- {
- return CompareToImpl((SortableDependencyNode)other, comparer);
- }
-
- int ISortableSymbolNode.ClassCode => this.ClassCode;
+ public override int ClassCode => -1145565068;
void ISymbolNode.AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs
index a73b9edc3..2b61d0ff4 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs
@@ -95,6 +95,6 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.NativeLayoutInfoNode;
+ public override int ClassCode => (int)ObjectNodeOrder.NativeLayoutInfoNode;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutSignatureNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutSignatureNode.cs
index 2c1dd5f4d..f4a0044ea 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutSignatureNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutSignatureNode.cs
@@ -85,9 +85,9 @@ namespace ILCompiler.DependencyAnalysis
return objData.ToObjectData();
}
- protected internal override int ClassCode => 1887049331;
+ public override int ClassCode => 1887049331;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
NativeLayoutSignatureNode otherSignature = (NativeLayoutSignatureNode)other;
if (_identity is MethodDesc)
@@ -118,4 +118,4 @@ namespace ILCompiler.DependencyAnalysis
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs
index 2c9122d7c..d48937e59 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs
@@ -982,7 +982,7 @@ namespace ILCompiler.DependencyAnalysis
yield return new DependencyListEntry(GetStaticsNode(context, out ignored), "type gc static info");
}
- if (_type.GetClosestDefType().ThreadStaticFieldSize.AsInt > 0)
+ if (_type.GetClosestDefType().ThreadGcStaticFieldSize.AsInt > 0)
{
BagElementKind ignored;
yield return new DependencyListEntry(GetThreadStaticsNode(context, out ignored), "type thread static info");
@@ -1059,7 +1059,7 @@ namespace ILCompiler.DependencyAnalysis
List<NativeLayoutVertexNode> vtableSignatureNodeEntries = null;
int currentVTableIndexUnused = 0;
ProcessVTableEntriesForCallingConventionSignatureGeneration(context, VTableEntriesToProcess.AllOnTypesThatShouldProduceFullVTables, ref currentVTableIndexUnused,
- (int vtableIndex, MethodDesc declMethod, MethodDesc implMethod) =>
+ (int vtableIndex, bool isSealedVTableSlot, MethodDesc declMethod, MethodDesc implMethod) =>
{
if (implMethod.IsAbstract)
return;
@@ -1069,7 +1069,7 @@ namespace ILCompiler.DependencyAnalysis
if (vtableSignatureNodeEntries == null)
vtableSignatureNodeEntries = new List<NativeLayoutVertexNode>();
- vtableSignatureNodeEntries.Add(context.NativeLayout.MethodSignatureVertex(implMethod.GetTypicalMethodDefinition().Signature));
+ vtableSignatureNodeEntries.Add(context.NativeLayout.MethodSignatureVertex(declMethod.GetTypicalMethodDefinition().Signature));
}
}
, _type, _type, _type);
@@ -1096,7 +1096,7 @@ namespace ILCompiler.DependencyAnalysis
int currentVTableIndexUnused = 0;
ProcessVTableEntriesForCallingConventionSignatureGeneration(context, VTableEntriesToProcess.AllOnTypesThatProducePartialVTables, ref currentVTableIndexUnused,
- (int vtableIndex, MethodDesc declMethod, MethodDesc implMethod) =>
+ (int vtableIndex, bool isSealedVTableSlot, MethodDesc declMethod, MethodDesc implMethod) =>
{
if (implMethod.IsAbstract)
return;
@@ -1107,7 +1107,7 @@ namespace ILCompiler.DependencyAnalysis
conditionalDependencies = new List<CombinedDependencyListEntry>();
conditionalDependencies.Add(
- new CombinedDependencyListEntry(context.NativeLayout.MethodSignatureVertex(implMethod.GetTypicalMethodDefinition().Signature),
+ new CombinedDependencyListEntry(context.NativeLayout.MethodSignatureVertex(declMethod.GetTypicalMethodDefinition().Signature),
context.VirtualMethodUse(declMethod),
"conditional vtable cctor sig"));
}
@@ -1201,9 +1201,9 @@ namespace ILCompiler.DependencyAnalysis
layoutInfo.AppendUnsigned(staticDescBagType, gcStaticsSymbolIndex);
}
- if (closestDefType.ThreadStaticFieldSize.AsInt != 0)
+ if (closestDefType.ThreadGcStaticFieldSize.AsInt != 0)
{
- layoutInfo.AppendUnsigned(BagElementKind.ThreadStaticDataSize, checked((uint)closestDefType.ThreadStaticFieldSize.AsInt));
+ layoutInfo.AppendUnsigned(BagElementKind.ThreadStaticDataSize, checked((uint)closestDefType.ThreadGcStaticFieldSize.AsInt));
BagElementKind threadStaticDescBagType;
ISymbolNode threadStaticsDescSymbol = GetThreadStaticsNode(factory, out threadStaticDescBagType);
uint threadStaticsSymbolIndex = factory.MetadataManager.NativeLayoutInfo.StaticsReferences.GetIndex(threadStaticsDescSymbol);
@@ -1236,6 +1236,16 @@ namespace ILCompiler.DependencyAnalysis
if (typeFlags != default(Internal.NativeFormat.TypeFlags))
layoutInfo.AppendUnsigned(BagElementKind.TypeFlags, (uint)typeFlags);
+ if (!_type.IsArrayTypeWithoutGenericInterfaces() && ConstructedEETypeNode.CreationAllowed(_type))
+ {
+ SealedVTableNode sealedVTable = factory.SealedVTable(_type.ConvertToCanonForm(CanonicalFormKind.Specific));
+
+ sealedVTable.BuildSealedVTableSlots(factory, relocsOnly: false /* This is the final emission phase */);
+
+ if (sealedVTable.NumSealedVTableEntries > 0)
+ layoutInfo.AppendUnsigned(BagElementKind.SealedVTableEntries, (uint)sealedVTable.NumSealedVTableEntries);
+ }
+
if (_type.GetTypeDefinition().HasVariance || factory.TypeSystemContext.IsGenericArrayInterfaceType(_type))
{
// Runtime casting logic relies on all interface types implemented on arrays
@@ -1319,7 +1329,7 @@ namespace ILCompiler.DependencyAnalysis
VertexSequence vtableSignaturesSequence = null;
ProcessVTableEntriesForCallingConventionSignatureGeneration(factory, VTableEntriesToProcess.AllInVTable, ref currentVTableIndexUnused,
- (int vtableIndex, MethodDesc declMethod, MethodDesc implMethod) =>
+ (int vtableIndex, bool isSealedVTableSlot, MethodDesc declMethod, MethodDesc implMethod) =>
{
if (implMethod.IsAbstract)
return;
@@ -1329,11 +1339,11 @@ namespace ILCompiler.DependencyAnalysis
if (vtableSignaturesSequence == null)
vtableSignaturesSequence = new VertexSequence();
- NativeLayoutVertexNode methodSignature = factory.NativeLayout.MethodSignatureVertex(implMethod.GetTypicalMethodDefinition().Signature);
+ NativeLayoutVertexNode methodSignature = factory.NativeLayout.MethodSignatureVertex(declMethod.GetTypicalMethodDefinition().Signature);
Vertex signatureVertex = GetNativeWriter(factory).GetRelativeOffsetSignature(methodSignature.WriteVertex(factory));
Vertex vtableSignatureEntry = writer.GetTuple(
- writer.GetUnsignedConstant(((uint)vtableIndex) << 1), // We currently do not use sealed vtable entries yet. Update when that happens
+ writer.GetUnsignedConstant((uint)((vtableIndex << 1) | (isSealedVTableSlot ? 1 : 0))),
factory.MetadataManager.NativeLayoutInfo.TemplatesSection.Place(signatureVertex));
vtableSignaturesSequence.Append(vtableSignatureEntry);
@@ -1391,7 +1401,7 @@ namespace ILCompiler.DependencyAnalysis
/// Do not adjust vtable index for generic dictionary slot
/// The vtable index is only actually valid if whichEntries is set to VTableEntriesToProcess.AllInVTable
/// </summary>
- private void ProcessVTableEntriesForCallingConventionSignatureGeneration(NodeFactory factory, VTableEntriesToProcess whichEntries, ref int currentVTableIndex, Action<int, MethodDesc, MethodDesc> operation, TypeDesc implType, TypeDesc declType, TypeDesc templateType)
+ private void ProcessVTableEntriesForCallingConventionSignatureGeneration(NodeFactory factory, VTableEntriesToProcess whichEntries, ref int currentVTableIndex, Action<int, bool, MethodDesc, MethodDesc> operation, TypeDesc implType, TypeDesc declType, TypeDesc templateType)
{
if (implType.IsInterface)
return;
@@ -1454,16 +1464,28 @@ namespace ILCompiler.DependencyAnalysis
if (declType.HasGenericDictionarySlot() || templateType.HasGenericDictionarySlot())
currentVTableIndex++;
+ int sealedVTableSlot = 0;
+ DefType closestDefType = implType.GetClosestDefType();
+
// Actual vtable slots follow
foreach (MethodDesc declMethod in vtableEntriesToProcess)
{
// No generic virtual methods can appear in the vtable!
Debug.Assert(!declMethod.HasInstantiation);
- MethodDesc implMethod = implType.GetClosestDefType().FindVirtualFunctionTargetMethodOnObjectType(declMethod);
+ MethodDesc implMethod = closestDefType.FindVirtualFunctionTargetMethodOnObjectType(declMethod);
- operation(currentVTableIndex, declMethod, implMethod);
- currentVTableIndex++;
+ if (implMethod.CanMethodBeInSealedVTable() && !implType.IsArrayTypeWithoutGenericInterfaces())
+ {
+ // Sealed vtable entries on other types in the hierarchy should not be reported (types read entries
+ // from their own sealed vtables, and not from the sealed vtables of base types).
+ if (implMethod.OwningType == closestDefType)
+ operation(sealedVTableSlot++, true, declMethod, implMethod);
+ }
+ else
+ {
+ operation(currentVTableIndex++, false, declMethod, implMethod);
+ }
}
}
}
@@ -1714,7 +1736,7 @@ namespace ILCompiler.DependencyAnalysis
if (method.IsRuntimeDeterminedExactMethod)
method = method.GetCanonMethodTarget(CanonicalFormKind.Specific);
- int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, method);
+ int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, method, method.OwningType);
return writer.GetMethodSlotSignature(_signature.WriteVertex(factory), checked((uint)slot));
}
@@ -1870,8 +1892,8 @@ namespace ILCompiler.DependencyAnalysis
protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory)
{
NativeWriter nativeWriter = GetNativeWriter(factory);
-
- int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, _slotDefiningMethod);
+
+ int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, _slotDefiningMethod, _slotDefiningMethod.OwningType);
Vertex typeVertex = factory.NativeLayout.TypeSignatureVertex(_slotDefiningMethod.OwningType).WriteVertex(factory);
return nativeWriter.GetTuple(typeVertex, nativeWriter.GetUnsignedConstant((uint)slot));
}
@@ -2024,7 +2046,8 @@ namespace ILCompiler.DependencyAnalysis
{
Debug.Assert((SignatureKind == FixupSignatureKind.NonGenericConstrainedMethod) || (SignatureKind == FixupSignatureKind.NonGenericDirectConstrainedMethod));
Vertex methodType = factory.NativeLayout.TypeSignatureVertex(_constrainedMethod.OwningType).WriteVertex(factory);
- int interfaceSlot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, _constrainedMethod.GetCanonMethodTarget(CanonicalFormKind.Specific));
+ var canonConstrainedMethod = _constrainedMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
+ int interfaceSlot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, canonConstrainedMethod, canonConstrainedMethod.OwningType);
Vertex interfaceSlotVertex = writer.GetUnsignedConstant(checked((uint)interfaceSlot));
return writer.GetTuple(constraintType, methodType, interfaceSlotVertex);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NecessaryCanonicalEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NecessaryCanonicalEETypeNode.cs
index 2a72b509b..a55b62860 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NecessaryCanonicalEETypeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NecessaryCanonicalEETypeNode.cs
@@ -27,6 +27,6 @@ namespace ILCompiler.DependencyAnalysis
return _type.BaseType != null ? factory.NecessaryTypeSymbol(GetFullCanonicalTypeForCanonicalType(_type.BaseType)) : null;
}
- protected internal override int ClassCode => 1505000724;
+ public override int ClassCode => 1505000724;
}
-} \ No newline at end of file
+}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs
index 6bfbf947d..26b0c703d 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs
@@ -14,7 +14,6 @@ using Internal.Text;
using Internal.TypeSystem;
using Internal.Runtime;
using Internal.IL;
-using Internal.NativeFormat;
namespace ILCompiler.DependencyAnalysis
{
@@ -50,6 +49,7 @@ namespace ILCompiler.DependencyAnalysis
MetadataManager = metadataManager;
LazyGenericsPolicy = lazyGenericsPolicy;
_importedNodeProvider = importedNodeProvider;
+ InterfaceDispatchCellSection = new InterfaceDispatchCellSectionNode(this);
}
public void SetMarkingComplete()
@@ -282,9 +282,9 @@ namespace ILCompiler.DependencyAnalysis
return new PInvokeModuleFixupNode(name);
});
- _pInvokeMethodFixups = new NodeCache<Tuple<string, string>, PInvokeMethodFixupNode>((Tuple<string, string> key) =>
+ _pInvokeMethodFixups = new NodeCache<Tuple<string, string, PInvokeFlags>, PInvokeMethodFixupNode>((Tuple<string, string, PInvokeFlags> key) =>
{
- return new PInvokeMethodFixupNode(key.Item1, key.Item2);
+ return new PInvokeMethodFixupNode(key.Item1, key.Item2, key.Item3);
});
_methodEntrypoints = new NodeCache<MethodDesc, IMethodNode>(CreateMethodEntrypointNode);
@@ -379,7 +379,12 @@ namespace ILCompiler.DependencyAnalysis
_interfaceDispatchMaps = new NodeCache<TypeDesc, InterfaceDispatchMapNode>((TypeDesc type) =>
{
- return new InterfaceDispatchMapNode(type);
+ return new InterfaceDispatchMapNode(this, type);
+ });
+
+ _sealedVtableNodes = new NodeCache<TypeDesc, SealedVTableNode>((TypeDesc type) =>
+ {
+ return new SealedVTableNode(type);
});
_runtimeMethodHandles = new NodeCache<MethodDesc, RuntimeMethodHandleNode>((MethodDesc method) =>
@@ -474,11 +479,6 @@ namespace ILCompiler.DependencyAnalysis
return new StringAllocatorMethodNode(constructor);
});
- _defaultConstructorFromLazyNodes = new NodeCache<TypeDesc, DefaultConstructorFromLazyNode>(type =>
- {
- return new DefaultConstructorFromLazyNode(type);
- });
-
NativeLayout = new NativeLayoutHelper(this);
WindowsDebugData = new WindowsDebugDataHelper(this);
}
@@ -641,6 +641,13 @@ namespace ILCompiler.DependencyAnalysis
return _readOnlyDataBlobs.GetOrAdd(new ReadOnlyDataBlobKey(name, blobData, alignment));
}
+ private NodeCache<TypeDesc, SealedVTableNode> _sealedVtableNodes;
+
+ internal SealedVTableNode SealedVTable(TypeDesc type)
+ {
+ return _sealedVtableNodes.GetOrAdd(type);
+ }
+
private NodeCache<TypeDesc, InterfaceDispatchMapNode> _interfaceDispatchMaps;
internal InterfaceDispatchMapNode InterfaceDispatchMap(TypeDesc type)
@@ -676,11 +683,11 @@ namespace ILCompiler.DependencyAnalysis
return _pInvokeModuleFixups.GetOrAdd(moduleName);
}
- private NodeCache<Tuple<string, string>, PInvokeMethodFixupNode> _pInvokeMethodFixups;
+ private NodeCache<Tuple<string, string, PInvokeFlags>, PInvokeMethodFixupNode> _pInvokeMethodFixups;
- public PInvokeMethodFixupNode PInvokeMethodFixup(string moduleName, string entryPointName)
+ public PInvokeMethodFixupNode PInvokeMethodFixup(string moduleName, string entryPointName, PInvokeFlags flags)
{
- return _pInvokeMethodFixups.GetOrAdd(new Tuple<string, string>(moduleName, entryPointName));
+ return _pInvokeMethodFixups.GetOrAdd(Tuple.Create(moduleName, entryPointName, flags));
}
private NodeCache<TypeDesc, VTableSliceNode> _vTableNodes;
@@ -788,12 +795,6 @@ namespace ILCompiler.DependencyAnalysis
return _runtimeDeterminedMethods.GetOrAdd(method);
}
- private NodeCache<TypeDesc, DefaultConstructorFromLazyNode> _defaultConstructorFromLazyNodes;
- internal DefaultConstructorFromLazyNode DefaultConstructorFromLazy(TypeDesc type)
- {
- return _defaultConstructorFromLazyNodes.GetOrAdd(type);
- }
-
private static readonly string[][] s_helperEntrypointNames = new string[][] {
new string[] { "System.Runtime.CompilerServices", "ClassConstructorRunner", "CheckStaticClassConstructionReturnGCStaticBase" },
new string[] { "System.Runtime.CompilerServices", "ClassConstructorRunner", "CheckStaticClassConstructionReturnNonGCStaticBase" },
@@ -911,6 +912,9 @@ namespace ILCompiler.DependencyAnalysis
internal TypeMetadataNode TypeMetadata(MetadataType type)
{
+ // These are only meaningful for UsageBasedMetadataManager. We should not have them
+ // in the dependency graph otherwise.
+ Debug.Assert(MetadataManager is UsageBasedMetadataManager);
return _typesWithMetadata.GetOrAdd(type);
}
@@ -918,6 +922,9 @@ namespace ILCompiler.DependencyAnalysis
internal MethodMetadataNode MethodMetadata(MethodDesc method)
{
+ // These are only meaningful for UsageBasedMetadataManager. We should not have them
+ // in the dependency graph otherwise.
+ Debug.Assert(MetadataManager is UsageBasedMetadataManager);
return _methodsWithMetadata.GetOrAdd(method);
}
@@ -925,6 +932,9 @@ namespace ILCompiler.DependencyAnalysis
internal FieldMetadataNode FieldMetadata(FieldDesc field)
{
+ // These are only meaningful for UsageBasedMetadataManager. We should not have them
+ // in the dependency graph otherwise.
+ Debug.Assert(MetadataManager is UsageBasedMetadataManager);
return _fieldsWithMetadata.GetOrAdd(field);
}
@@ -932,6 +942,9 @@ namespace ILCompiler.DependencyAnalysis
internal ModuleMetadataNode ModuleMetadata(ModuleDesc module)
{
+ // These are only meaningful for UsageBasedMetadataManager. We should not have them
+ // in the dependency graph otherwise.
+ Debug.Assert(MetadataManager is UsageBasedMetadataManager);
return _modulesWithMetadata.GetOrAdd(module);
}
@@ -1016,6 +1029,8 @@ namespace ILCompiler.DependencyAnalysis
"__ImportTablesTableEnd",
new SortableDependencyNode.ObjectNodeComparer(new CompilerComparer()));
+ public InterfaceDispatchCellSectionNode InterfaceDispatchCellSection { get; }
+
public ReadyToRunHeaderNode ReadyToRunHeader;
public Dictionary<ISymbolNode, string> NodeAliases = new Dictionary<ISymbolNode, string>();
@@ -1035,6 +1050,7 @@ namespace ILCompiler.DependencyAnalysis
graph.AddRoot(TypeManagerIndirection, "TypeManagerIndirection is always generated");
graph.AddRoot(DispatchMapTable, "DispatchMapTable is always generated");
graph.AddRoot(FrozenSegmentRegion, "FrozenSegmentRegion is always generated");
+ graph.AddRoot(InterfaceDispatchCellSection, "Interface dispatch cell section is always generated");
if (Target.IsWindows)
{
// We need 2 delimiter symbols to bound the unboxing stubs region on Windows platforms (these symbols are
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NonExternMethodSymbolNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NonExternMethodSymbolNode.cs
index 1b09590ca..6be5e9456 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NonExternMethodSymbolNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NonExternMethodSymbolNode.cs
@@ -18,7 +18,7 @@ namespace ILCompiler.DependencyAnalysis
// When full analysis is fully supported, remove this class and field forever.
public static bool EnableFullAnalysis = false;
}
-
+
/// <summary>
/// Represents a symbol that is defined externally but modeled as a method
/// in the DependencyAnalysis infrastructure during compilation that is compiled
@@ -32,9 +32,10 @@ namespace ILCompiler.DependencyAnalysis
ISymbolNode[] _funcletSymbols = Array.Empty<ISymbolNode>();
bool _dependenciesQueried;
bool _hasCompiledBody;
+ private HashSet<GenericLookupResult> _floatingGenericLookupResults;
public NonExternMethodSymbolNode(NodeFactory factory, MethodDesc method, bool isUnboxing)
- : base(isUnboxing ? UnboxingStubNode.GetMangledName(factory.NameMangler, method) :
+ : base(isUnboxing ? UnboxingStubNode.GetMangledName(factory.NameMangler, method) :
factory.NameMangler.GetMangledMethodName(method))
{
_isUnboxing = isUnboxing;
@@ -101,6 +102,30 @@ namespace ILCompiler.DependencyAnalysis
_funcletSymbols = funclets;
}
+ public void DeferFloatingGenericLookup(GenericLookupResult lookupResult)
+ {
+ if (_floatingGenericLookupResults == null)
+ _floatingGenericLookupResults = new HashSet<GenericLookupResult>();
+ _floatingGenericLookupResults.Add(lookupResult);
+ }
+
+ protected override void OnMarked(NodeFactory factory)
+ {
+ // Commit all floating generic lookups associated with the method when the method
+ // is proved not dead.
+ if (_floatingGenericLookupResults != null)
+ {
+ Debug.Assert(_method.IsCanonicalMethod(CanonicalFormKind.Any));
+ TypeSystemEntity canonicalOwner = _method.HasInstantiation ? (TypeSystemEntity)_method : (TypeSystemEntity)_method.OwningType;
+ DictionaryLayoutNode dictLayout = factory.GenericDictionaryLayout(canonicalOwner);
+
+ foreach (var lookupResult in _floatingGenericLookupResults)
+ {
+ dictLayout.EnsureEntry(lookupResult);
+ }
+ }
+ }
+
public void AddCompilationDiscoveredDependency(IDependencyNode<NodeFactory> node, string reason)
{
Debug.Assert(!_dependenciesQueried);
@@ -149,6 +174,15 @@ namespace ILCompiler.DependencyAnalysis
return dependencies;
}
+ public override int ClassCode => -2124588118;
+
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
+ {
+ NonExternMethodSymbolNode otherMethod = (NonExternMethodSymbolNode)other;
+ var result = _isUnboxing.CompareTo(otherMethod._isUnboxing);
+ return result != 0 ? result : comparer.Compare(_method, otherMethod._method);
+ }
+
private class FuncletSymbol : ISymbolNodeWithFuncletId
{
public FuncletSymbol(NonExternMethodSymbolNode methodSymbol, int funcletId)
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NonGCStaticsNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NonGCStaticsNode.cs
index dc6ade07c..ac2115d7c 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NonGCStaticsNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NonGCStaticsNode.cs
@@ -18,7 +18,7 @@ namespace ILCompiler.DependencyAnalysis
/// with the class constructor context if the type has a class constructor that
/// needs to be triggered before the type members can be accessed.
/// </summary>
- public class NonGCStaticsNode : ObjectNode, IExportableSymbolNode, ISortableSymbolNode
+ public class NonGCStaticsNode : ObjectNode, IExportableSymbolNode, ISortableSymbolNode, ISymbolNodeWithDebugInfo
{
private MetadataType _type;
private NodeFactory _factory;
@@ -69,6 +69,8 @@ namespace ILCompiler.DependencyAnalysis
}
}
+ public IDebugInfo DebugInfo => NullTypeIndexDebugInfo.Instance;
+
public override bool IsShareable => EETypeNode.IsTypeNodeShareable(_type);
public MetadataType Type => _type;
@@ -178,18 +180,11 @@ namespace ILCompiler.DependencyAnalysis
return builder.ToObjectData();
}
- protected internal override int ClassCode => -1173104872;
+ public override int ClassCode => -1173104872;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_type, ((NonGCStaticsNode)other)._type);
}
-
- int ISortableSymbolNode.ClassCode => ClassCode;
-
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
- {
- return CompareToImpl((ObjectNode)other, comparer);
- }
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectDataBuilder.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectDataBuilder.cs
index b42c3e382..29fc23f98 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectDataBuilder.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectDataBuilder.cs
@@ -5,7 +5,6 @@
using System;
using System.Collections.Generic;
using Internal.TypeSystem;
-using Internal.Runtime;
using Debug = System.Diagnostics.Debug;
@@ -293,20 +292,6 @@ namespace ILCompiler.DependencyAnalysis
EmitReloc(symbol, (_target.PointerSize == 8) ? RelocType.IMAGE_REL_BASED_DIR64 : RelocType.IMAGE_REL_BASED_HIGHLOW, delta);
}
- /// <summary>
- /// Use this api to generate a reloc to a symbol that may be an indirection cell or not as a pointer
- /// </summary>
- /// <param name="symbol">symbol to reference</param>
- /// <param name="indirectionBit">value to OR in to the reloc to represent to runtime code that this pointer is an indirection. Defaults to IndirectionConstants.IndirectionCellPointer</param>
- /// <param name="delta">Delta from symbol start for value</param>
- public void EmitPointerRelocOrIndirectionReference(ISymbolNode symbol, int indirectionBit = IndirectionConstants.IndirectionCellPointer, int delta = 0)
- {
- if (symbol.RepresentsIndirectionCell)
- delta |= indirectionBit;
-
- EmitReloc(symbol, (_target.PointerSize == 8) ? RelocType.IMAGE_REL_BASED_DIR64 : RelocType.IMAGE_REL_BASED_HIGHLOW, delta);
- }
-
public ObjectNode.ObjectData ToObjectData()
{
#if DEBUG
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectNode.cs
index 6dcf96ae8..21490cadc 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectNode.cs
@@ -51,16 +51,6 @@ namespace ILCompiler.DependencyAnalysis
return false;
}
- /// <summary>
- /// Return a node that is used for linkage
- /// </summary>
- /// <param name="factory"></param>
- /// <returns></returns>
- public virtual ObjectNode NodeForLinkage(NodeFactory factory)
- {
- return this;
- }
-
public override bool HasConditionalStaticDependencies => false;
public override bool HasDynamicDependencies => false;
public override bool InterestingForDynamicDependencyAnalysis => false;
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectNodeSection.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectNodeSection.cs
index 86c6a3178..e9eaf77c7 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectNodeSection.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectNodeSection.cs
@@ -46,7 +46,7 @@ namespace ILCompiler.DependencyAnalysis
public static readonly ObjectNodeSection XDataSection = new ObjectNodeSection("xdata", SectionType.ReadOnly);
public static readonly ObjectNodeSection DataSection = new ObjectNodeSection("data", SectionType.Writeable);
public static readonly ObjectNodeSection ReadOnlyDataSection = new ObjectNodeSection("rdata", SectionType.ReadOnly);
- public static readonly ObjectNodeSection FoldableReadOnlyDataSection = new ObjectNodeSection("rdata$ICF", SectionType.ReadOnly);
+ public static readonly ObjectNodeSection FoldableReadOnlyDataSection = new ObjectNodeSection("rdata$F", SectionType.ReadOnly);
public static readonly ObjectNodeSection TextSection = new ObjectNodeSection("text", SectionType.Executable);
public static readonly ObjectNodeSection TLSSection = new ObjectNodeSection("TLS", SectionType.Writeable);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectWriter.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectWriter.cs
index 25242c877..4a85d860d 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectWriter.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectWriter.cs
@@ -194,16 +194,6 @@ namespace ILCompiler.DependencyAnalysis
private static extern int EmitSymbolRef(IntPtr objWriter, byte[] symbolName, RelocType relocType, int delta);
public int EmitSymbolRef(Utf8StringBuilder symbolName, RelocType relocType, int delta = 0)
{
- if (_targetPlatform.Architecture != TargetArchitecture.ARMEL && _targetPlatform.Architecture != TargetArchitecture.ARM)
- {
- // Workaround for ObjectWriter's lack of support for IMAGE_REL_BASED_RELPTR32
- // https://github.com/dotnet/corert/issues/3278
- if (relocType == RelocType.IMAGE_REL_BASED_RELPTR32)
- {
- relocType = RelocType.IMAGE_REL_BASED_REL32;
- delta = checked(delta + sizeof(int));
- }
- }
return EmitSymbolRef(_nativeObjectWriter, symbolName.Append('\0').UnderlyingArray, relocType, delta);
}
@@ -275,7 +265,12 @@ namespace ILCompiler.DependencyAnalysis
private static extern uint GetClassTypeIndex(IntPtr objWriter, ClassTypeDescriptor classTypeDescriptor);
[DllImport(NativeObjectWriterFileName)]
- private static extern uint GetCompleteClassTypeIndex(IntPtr objWriter, ClassTypeDescriptor classTypeDescriptor, ClassFieldsTypeDescriptor classFieldsTypeDescriptior, DataFieldDescriptor[] fields);
+ private static extern uint GetCompleteClassTypeIndex(IntPtr objWriter, ClassTypeDescriptor classTypeDescriptor,
+ ClassFieldsTypeDescriptor classFieldsTypeDescriptior, DataFieldDescriptor[] fields,
+ StaticDataFieldDescriptor[] statics);
+
+ [DllImport(NativeObjectWriterFileName)]
+ private static extern uint GetPrimitiveTypeIndex(IntPtr objWriter, int type);
[DllImport(NativeObjectWriterFileName)]
private static extern void EmitARMFnStart(IntPtr objWriter);
@@ -316,9 +311,16 @@ namespace ILCompiler.DependencyAnalysis
return GetClassTypeIndex(_nativeObjectWriter, classTypeDescriptor);
}
- public uint GetCompleteClassTypeIndex(ClassTypeDescriptor classTypeDescriptor, ClassFieldsTypeDescriptor classFieldsTypeDescriptior, DataFieldDescriptor[] fields)
+ public uint GetCompleteClassTypeIndex(ClassTypeDescriptor classTypeDescriptor, ClassFieldsTypeDescriptor classFieldsTypeDescriptior,
+ DataFieldDescriptor[] fields, StaticDataFieldDescriptor[] statics)
{
- return GetCompleteClassTypeIndex(_nativeObjectWriter, classTypeDescriptor, classFieldsTypeDescriptior, fields);
+ return GetCompleteClassTypeIndex(_nativeObjectWriter, classTypeDescriptor, classFieldsTypeDescriptior, fields, statics);
+ }
+
+ public uint GetPrimitiveTypeIndex(TypeDesc type)
+ {
+ Debug.Assert(type.IsPrimitive, "it is not a primitive type");
+ return GetPrimitiveTypeIndex(_nativeObjectWriter, (int)type.Category);
}
[DllImport(NativeObjectWriterFileName)]
@@ -372,10 +374,42 @@ namespace ILCompiler.DependencyAnalysis
}
[DllImport(NativeObjectWriterFileName)]
- private static extern void EmitDebugFunctionInfo(IntPtr objWriter, byte[] methodName, int methodSize);
- public void EmitDebugFunctionInfo(int methodSize)
+ private static extern void EmitDebugEHClause(IntPtr objWriter, UInt32 TryOffset, UInt32 TryLength, UInt32 HandlerOffset, UInt32 HandlerLength);
+
+ public void EmitDebugEHClause(DebugEHClauseInfo ehClause)
{
- EmitDebugFunctionInfo(_nativeObjectWriter, _currentNodeZeroTerminatedName.UnderlyingArray, methodSize);
+ EmitDebugEHClause(_nativeObjectWriter, ehClause.TryOffset, ehClause.TryLength, ehClause.HandlerOffset, ehClause.HandlerLength);
+ }
+
+ public void EmitDebugEHClauseInfo(ObjectNode node)
+ {
+ var nodeWithCodeInfo = node as INodeWithCodeInfo;
+ if (nodeWithCodeInfo != null)
+ {
+ DebugEHClauseInfo[] clauses = nodeWithCodeInfo.DebugEHClauseInfos;
+ if (clauses != null)
+ {
+ foreach (var clause in clauses)
+ {
+ EmitDebugEHClause(clause);
+ }
+ }
+ }
+ }
+
+ [DllImport(NativeObjectWriterFileName)]
+ private static extern void EmitDebugFunctionInfo(IntPtr objWriter, byte[] methodName, int methodSize, UInt32 methodTypeIndex);
+ public void EmitDebugFunctionInfo(ObjectNode node, int methodSize)
+ {
+ uint methodTypeIndex = 0;
+
+ var methodNode = node as IMethodNode;
+ if (methodNode != null)
+ {
+ methodTypeIndex = _userDefinedTypeDescriptor.GetMethodFunctionIdTypeIndex(methodNode.Method);
+ }
+
+ EmitDebugFunctionInfo(_nativeObjectWriter, _currentNodeZeroTerminatedName.UnderlyingArray, methodSize, methodTypeIndex);
}
[DllImport(NativeObjectWriterFileName)]
@@ -699,12 +733,21 @@ namespace ILCompiler.DependencyAnalysis
List<byte[]> cfis;
if (_offsetToCfis.TryGetValue(offset, out cfis))
{
- foreach (byte[] cfi in cfis)
+ if (forArm)
{
- if (forArm)
- EmitARMExIdxCode(offset, cfi);
- else
+ // Unwind insts are generated in the object file in the reversed order on arm,
+ // so we should reverse the cfi list
+ for (int index = cfis.Count - 1; index >= 0; index--)
+ {
+ EmitARMExIdxCode(offset, cfis[index]);
+ }
+ }
+ else
+ {
+ foreach (byte[] cfi in cfis)
+ {
EmitCFICode(offset, cfi);
+ }
}
}
}
@@ -1113,13 +1156,9 @@ namespace ILCompiler.DependencyAnalysis
if (objectWriter.HasFunctionDebugInfo())
{
- if (factory.Target.OperatingSystem == TargetOS.Windows)
- {
- // Build debug local var info.
- // It currently supports only Windows CodeView format.
- objectWriter.EmitDebugVarInfo(node);
- }
- objectWriter.EmitDebugFunctionInfo(nodeContents.Data.Length);
+ objectWriter.EmitDebugVarInfo(node);
+ objectWriter.EmitDebugEHClauseInfo(node);
+ objectWriter.EmitDebugFunctionInfo(node, nodeContents.Data.Length);
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs
index 797032e3e..c7707b23a 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
+using System.Runtime.InteropServices;
using Internal.Text;
using Internal.TypeSystem;
@@ -16,11 +17,13 @@ namespace ILCompiler.DependencyAnalysis
{
private string _moduleName;
private string _entryPointName;
+ private PInvokeFlags _flags;
- public PInvokeMethodFixupNode(string moduleName, string entryPointName)
+ public PInvokeMethodFixupNode(string moduleName, string entryPointName, PInvokeFlags flags)
{
_moduleName = moduleName;
_entryPointName = entryPointName;
+ _flags = flags;
}
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
@@ -29,6 +32,13 @@ namespace ILCompiler.DependencyAnalysis
sb.Append(_moduleName);
sb.Append("__");
sb.Append(_entryPointName);
+ if(!_flags.ExactSpelling)
+ {
+ sb.Append("__");
+ sb.Append(_flags.CharSet.ToString());
+ }
+ sb.Append("__");
+ sb.Append(((int)_flags.Attributes).ToString());
}
public int Offset => 0;
public override bool IsShareable => true;
@@ -72,16 +82,22 @@ namespace ILCompiler.DependencyAnalysis
// Module fixup cell
builder.EmitPointerReloc(factory.PInvokeModuleFixup(_moduleName));
+ builder.EmitInt(_flags.ExactSpelling ? 0 : (int)_flags.CharSet);
+
return builder.ToObjectData();
}
- protected internal override int ClassCode => -1592006940;
+ public override int ClassCode => -1592006940;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
- var compare = string.Compare(_moduleName, ((PInvokeMethodFixupNode)other)._moduleName);
- if (compare != 0)
- return compare;
+ var flagsCompare = _flags.CompareTo(((PInvokeMethodFixupNode)other)._flags);
+ if (flagsCompare != 0)
+ return flagsCompare;
+
+ var moduleCompare = string.Compare(_moduleName, ((PInvokeMethodFixupNode)other)._moduleName);
+ if (moduleCompare != 0)
+ return moduleCompare;
return string.Compare(_entryPointName, ((PInvokeMethodFixupNode)other)._entryPointName);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/PInvokeModuleFixupNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/PInvokeModuleFixupNode.cs
index bf83f13b1..784f791ba 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/PInvokeModuleFixupNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/PInvokeModuleFixupNode.cs
@@ -50,9 +50,9 @@ namespace ILCompiler.DependencyAnalysis
return builder.ToObjectData();
}
- protected internal override int ClassCode => 159930099;
+ public override int ClassCode => 159930099;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return string.Compare(_moduleName, ((PInvokeModuleFixupNode)other)._moduleName);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs
index ddd1479b2..f68ccbf0a 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs
@@ -63,6 +63,8 @@ namespace ILCompiler.DependencyAnalysis
}
}
+ protected override bool IsVisibleFromManagedCode => false;
+
protected sealed override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
public override bool IsShareable => true;
@@ -206,7 +208,7 @@ namespace ILCompiler.DependencyAnalysis
return conditionalDependencies;
}
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
var compare = _id.CompareTo(((ReadyToRunGenericHelperNode)other)._id);
if (compare != 0)
@@ -272,7 +274,7 @@ namespace ILCompiler.DependencyAnalysis
AppendLookupSignatureMangledName(nameMangler, sb);
}
- protected internal override int ClassCode => 1055354299;
+ public override int ClassCode => 1055354299;
}
public partial class ReadyToRunGenericLookupFromTypeNode : ReadyToRunGenericHelperNode
@@ -294,6 +296,6 @@ namespace ILCompiler.DependencyAnalysis
AppendLookupSignatureMangledName(nameMangler, sb);
}
- protected internal override int ClassCode => 913214059;
+ public override int ClassCode => 913214059;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHeaderNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHeaderNode.cs
index 6c2fd6d73..fa8e6ed26 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHeaderNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHeaderNode.cs
@@ -128,6 +128,6 @@ namespace ILCompiler.DependencyAnalysis
return builder.ToObjectData();
}
- protected internal override int ClassCode => -534800244;
+ public override int ClassCode => -534800244;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs
index 7b941ec85..76f4785a4 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs
@@ -80,16 +80,24 @@ namespace ILCompiler.DependencyAnalysis
}
break;
case ReadyToRunHelperId.VirtualCall:
+ case ReadyToRunHelperId.ResolveVirtualFunction:
{
// Make sure we aren't trying to callvirt Object.Finalize
MethodDesc method = (MethodDesc)target;
if (method.IsFinalizer)
ThrowHelper.ThrowInvalidProgramException(ExceptionStringID.InvalidProgramCallVirtFinalize, method);
+
+ // Method should be in fully canonical form. Otherwise we're being wasteful and generate more
+ // helpers than needed.
+ Debug.Assert(!method.IsCanonicalMethod(CanonicalFormKind.Any) ||
+ method.GetCanonMethodTarget(CanonicalFormKind.Specific) == method);
}
break;
}
}
+ protected override bool IsVisibleFromManagedCode => false;
+
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
public ReadyToRunHelperId Id => _id;
@@ -221,9 +229,9 @@ namespace ILCompiler.DependencyAnalysis
}
#if !SUPPORT_JIT
- protected internal override int ClassCode => -911637948;
+ public override int ClassCode => -911637948;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
var compare = _id.CompareTo(((ReadyToRunHelperNode)other)._id);
if (compare != 0)
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs
index 93bf59979..7c062d068 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs
@@ -187,6 +187,6 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.ReflectionFieldMapNode;
+ public override int ClassCode => (int)ObjectNodeOrder.ReflectionFieldMapNode;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs
index 73a95d2e5..2304902a5 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs
@@ -189,6 +189,6 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.ReflectionInvokeMapNode;
+ public override int ClassCode => (int)ObjectNodeOrder.ReflectionInvokeMapNode;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs
index 2b5f45090..0b256dbf1 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs
@@ -218,7 +218,7 @@ namespace ILCompiler.DependencyAnalysis
else
{
// Get the declaring method for slot on the instantiated declaring type
- int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, declaringMethodForSlot, factory.Target.Abi != TargetAbi.ProjectN);
+ int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, declaringMethodForSlot, declaringMethodForSlot.OwningType, factory.Target.Abi != TargetAbi.ProjectN);
Debug.Assert(slot != -1);
vertex = writer.GetTuple(
@@ -242,6 +242,6 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.ReflectionVirtualInvokeMapNode;
+ public override int ClassCode => (int)ObjectNodeOrder.ReflectionVirtualInvokeMapNode;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceDataNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceDataNode.cs
index cc9dd6a2c..b425283de 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceDataNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceDataNode.cs
@@ -98,6 +98,11 @@ namespace ILCompiler.DependencyAnalysis
}
string resourceName = module.MetadataReader.GetString(resource.Name);
+
+ // Check if emitting the manifest resource is blocked by policy.
+ if (factory.MetadataManager.IsManifestResourceBlocked(module, resourceName))
+ continue;
+
string assemblyName = module.GetName().FullName;
BlobReader reader = resourceDirectory.GetReader((int)resource.Offset, resourceDirectory.Length - (int)resource.Offset);
int length = (int)reader.ReadUInt32();
@@ -143,7 +148,7 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.ResourceDataNode;
+ public override int ClassCode => (int)ObjectNodeOrder.ResourceDataNode;
}
/// <summary>
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceIndexNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceIndexNode.cs
index 4ad4a3b89..bd1243f4a 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceIndexNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceIndexNode.cs
@@ -97,6 +97,6 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.ResourceIndexNode;
+ public override int ClassCode => (int)ObjectNodeOrder.ResourceIndexNode;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeDecodableJumpStub.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeDecodableJumpStub.cs
index d4d8e06ff..1fba7e459 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeDecodableJumpStub.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeDecodableJumpStub.cs
@@ -50,18 +50,11 @@ namespace ILCompiler.DependencyAnalysis
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
- protected internal override int ClassCode => 532434339;
+ public override int ClassCode => 532434339;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(WrappedMethodIndirectionCellNode, ((RuntimeDecodableJumpStubNode)other).WrappedMethodIndirectionCellNode);
}
-
- int ISortableSymbolNode.ClassCode => ClassCode;
-
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
- {
- return CompareToImpl((ObjectNode)other, comparer);
- }
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeDeterminedMethodNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeDeterminedMethodNode.cs
index d3a3672ea..e9ac8a8d7 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeDeterminedMethodNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeDeterminedMethodNode.cs
@@ -62,9 +62,9 @@ namespace ILCompiler.DependencyAnalysis
public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null;
public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) => null;
- int ISortableSymbolNode.ClassCode => 258139501;
+ int ISortableNode.ClassCode => 258139501;
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
+ int ISortableNode.CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_canonicalMethodNode, ((RuntimeDeterminedMethodNode)other)._canonicalMethodNode);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs
index 57a4018fd..c5eaeddfe 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs
@@ -29,10 +29,20 @@ namespace ILCompiler.DependencyAnalysis
}
public int Offset => 0;
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
- public override ObjectNodeSection Section => ObjectNodeSection.ReadOnlyDataSection;
public override bool IsShareable => false;
public override bool StaticDependenciesAreComputed => true;
+ public override ObjectNodeSection Section
+ {
+ get
+ {
+ if (_targetField.Context.Target.IsWindows)
+ return ObjectNodeSection.ReadOnlyDataSection;
+ else
+ return ObjectNodeSection.DataSection;
+ }
+ }
+
private static Utf8String s_NativeLayoutSignaturePrefix = new Utf8String("__RFHSignature_");
protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
@@ -55,9 +65,9 @@ namespace ILCompiler.DependencyAnalysis
return objData.ToObjectData();
}
- protected internal override int ClassCode => -1326215725;
+ public override int ClassCode => -1326215725;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_targetField, ((RuntimeFieldHandleNode)other)._targetField);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeImportMethodNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeImportMethodNode.cs
index 909edfae4..796ffce38 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeImportMethodNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeImportMethodNode.cs
@@ -10,7 +10,7 @@ namespace ILCompiler.DependencyAnalysis
/// <summary>
/// Represents a method that is imported from the runtime library.
/// </summary>
- public class RuntimeImportMethodNode : ExternSymbolNode, IMethodNode
+ public class RuntimeImportMethodNode : ExternSymbolNode, IMethodNode, IExportableSymbolNode
{
private MethodDesc _method;
@@ -27,5 +27,27 @@ namespace ILCompiler.DependencyAnalysis
return _method;
}
}
+
+ public ExportForm GetExportForm(NodeFactory factory)
+ {
+ // Force non-fake exports for RuntimeImportMethods that have '*' as their module. ('*' means the method is
+ // REALLY a reference to the linked in native code)
+ if (((EcmaMethod)_method).GetRuntimeImportDllName() == "*")
+ {
+ ExportForm exportForm = factory.CompilationModuleGroup.GetExportMethodForm(_method, false);
+ if (exportForm == ExportForm.ByName)
+ return ExportForm.None; // Method symbols exported by name are naturally handled by the linker
+ return exportForm;
+ }
+
+ return ExportForm.None;
+ }
+
+ public override int ClassCode => -1173492615;
+
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
+ {
+ return comparer.Compare(_method, ((RuntimeImportMethodNode)other)._method);
+ }
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs
index c40987f3c..39884096a 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs
@@ -35,10 +35,20 @@ namespace ILCompiler.DependencyAnalysis
}
public int Offset => 0;
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
- public override ObjectNodeSection Section => ObjectNodeSection.ReadOnlyDataSection;
public override bool IsShareable => false;
public override bool StaticDependenciesAreComputed => true;
+ public override ObjectNodeSection Section
+ {
+ get
+ {
+ if (_targetMethod.Context.Target.IsWindows)
+ return ObjectNodeSection.ReadOnlyDataSection;
+ else
+ return ObjectNodeSection.DataSection;
+ }
+ }
+
protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
{
DependencyList dependencies = null;
@@ -70,9 +80,9 @@ namespace ILCompiler.DependencyAnalysis
return objData.ToObjectData();
}
- protected internal override int ClassCode => -274400625;
+ public override int ClassCode => -274400625;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_targetMethod, ((RuntimeMethodHandleNode)other)._targetMethod);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RyuJitNodeFactory.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RyuJitNodeFactory.cs
index cce88f810..1db0a5948 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RyuJitNodeFactory.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RyuJitNodeFactory.cs
@@ -60,7 +60,7 @@ namespace ILCompiler.DependencyAnalysis
// 'this' and also provides an instantiation argument (we do a calling convention conversion).
// We don't do this for generic instance methods though because they don't use the EEType
// for the generic context anyway.
- return new MethodCodeNode(TypeSystemContext.GetSpecialUnboxingThunk(method, CompilationModuleGroup.GeneratedAssembly));
+ return new MethodCodeNode(TypeSystemContext.GetSpecialUnboxingThunk(method, TypeSystemContext.GeneratedAssembly));
}
else
{
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ScannedMethodNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ScannedMethodNode.cs
index 43d27c344..4dfd01266 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ScannedMethodNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ScannedMethodNode.cs
@@ -63,9 +63,9 @@ namespace ILCompiler.DependencyAnalysis
public override bool HasDynamicDependencies => false;
public override bool HasConditionalStaticDependencies => false;
- int ISortableSymbolNode.ClassCode => -1381809560;
+ int ISortableNode.ClassCode => -1381809560;
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
+ int ISortableNode.CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(Method, ((ScannedMethodNode)other).Method);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SealedVTableNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SealedVTableNode.cs
new file mode 100644
index 000000000..dac6d8dbc
--- /dev/null
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SealedVTableNode.cs
@@ -0,0 +1,170 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+using Internal.Text;
+using Internal.TypeSystem;
+
+namespace ILCompiler.DependencyAnalysis
+{
+ public class SealedVTableNode : ObjectNode, ISymbolDefinitionNode
+ {
+ private readonly TypeDesc _type;
+ private List<MethodDesc> _sealedVTableEntries;
+
+ public SealedVTableNode(TypeDesc type)
+ {
+ // Multidimensional arrays should not get a sealed vtable or a dispatch map. Runtime should use the
+ // sealed vtable and dispatch map of the System.Array basetype instead.
+ // Pointer arrays also follow the same path
+ Debug.Assert(!type.IsArrayTypeWithoutGenericInterfaces());
+ Debug.Assert(!type.IsRuntimeDeterminedSubtype);
+
+ _type = type;
+ }
+
+ protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
+
+ public override ObjectNodeSection Section => _type.Context.Target.IsWindows ? ObjectNodeSection.FoldableReadOnlyDataSection : ObjectNodeSection.DataSection;
+
+ public virtual void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
+ {
+ sb.Append(nameMangler.CompilationUnitPrefix + "__SealedVTable_" + nameMangler.NodeMangler.EEType(_type));
+ }
+
+ int ISymbolNode.Offset => 0;
+ int ISymbolDefinitionNode.Offset => 0;
+ public override bool IsShareable => EETypeNode.IsTypeNodeShareable(_type);
+ public override bool StaticDependenciesAreComputed => true;
+
+ /// <summary>
+ /// Returns the number of sealed vtable slots on the type. This API should only be called after successfully
+ /// building the sealed vtable slots.
+ /// </summary>
+ public int NumSealedVTableEntries
+ {
+ get
+ {
+ if (_sealedVTableEntries == null)
+ throw new NotSupportedException();
+
+ return _sealedVTableEntries.Count;
+ }
+ }
+
+ /// <summary>
+ /// Returns the slot of a method in the sealed vtable, or -1 if not found. This API should only be called after
+ /// successfully building the sealed vtable slots.
+ /// </summary>
+ public int ComputeSealedVTableSlot(MethodDesc method)
+ {
+ if (_sealedVTableEntries == null)
+ throw new NotSupportedException();
+
+ for (int i = 0; i < _sealedVTableEntries.Count; i++)
+ {
+ if (_sealedVTableEntries[i] == method)
+ return i;
+ }
+
+ return -1;
+ }
+
+ public bool BuildSealedVTableSlots(NodeFactory factory, bool relocsOnly)
+ {
+ // Sealed vtable already built
+ if (_sealedVTableEntries != null)
+ return true;
+
+ TypeDesc declType = _type.GetClosestDefType();
+
+ // It's only okay to touch the actual list of slots if we're in the final emission phase
+ // or the vtable is not built lazily.
+ if (relocsOnly && !factory.VTable(declType).HasFixedSlots)
+ return false;
+
+ _sealedVTableEntries = new List<MethodDesc>();
+
+ IReadOnlyList<MethodDesc> virtualSlots = factory.VTable(declType).Slots;
+
+ for (int i = 0; i < virtualSlots.Count; i++)
+ {
+ MethodDesc implMethod = declType.FindVirtualFunctionTargetMethodOnObjectType(virtualSlots[i]);
+
+ if (implMethod.CanMethodBeInSealedVTable())
+ _sealedVTableEntries.Add(implMethod);
+ }
+
+ // Catch any runtime interface collapsing. We shouldn't have any
+ Debug.Assert(declType.RuntimeInterfaces.Length == declType.GetTypeDefinition().RuntimeInterfaces.Length);
+
+ for (int interfaceIndex = 0; interfaceIndex < declType.RuntimeInterfaces.Length; interfaceIndex++)
+ {
+ var interfaceType = declType.RuntimeInterfaces[interfaceIndex];
+ var interfaceDefinitionType = declType.GetTypeDefinition().RuntimeInterfaces[interfaceIndex];
+
+ virtualSlots = factory.VTable(interfaceType).Slots;
+
+ for (int interfaceMethodSlot = 0; interfaceMethodSlot < virtualSlots.Count; interfaceMethodSlot++)
+ {
+ MethodDesc declMethod = virtualSlots[interfaceMethodSlot];
+ if (!interfaceType.IsTypeDefinition)
+ declMethod = factory.TypeSystemContext.GetMethodForInstantiatedType(declMethod.GetTypicalMethodDefinition(), (InstantiatedType)interfaceDefinitionType);
+
+ var implMethod = declType.GetTypeDefinition().ResolveInterfaceMethodToVirtualMethodOnType(declMethod);
+
+ // Interface methods first implemented by a base type in the hierarchy will return null for the implMethod (runtime interface
+ // dispatch will walk the inheritance chain).
+ if (implMethod != null && implMethod.CanMethodBeInSealedVTable() && !implMethod.OwningType.HasSameTypeDefinition(declType))
+ {
+ TypeDesc implType = declType;
+ while (!implType.HasSameTypeDefinition(implMethod.OwningType))
+ implType = implType.BaseType;
+
+ MethodDesc targetMethod = implMethod;
+ if (!implType.IsTypeDefinition)
+ targetMethod = factory.TypeSystemContext.GetMethodForInstantiatedType(implMethod.GetTypicalMethodDefinition(), (InstantiatedType)implType);
+
+ _sealedVTableEntries.Add(targetMethod);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ public override ObjectData GetData(NodeFactory factory, bool relocsOnly)
+ {
+ ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly);
+ objData.RequireInitialAlignment(4);
+ objData.AddSymbol(this);
+
+ if (BuildSealedVTableSlots(factory, relocsOnly))
+ {
+ for (int i = 0; i < _sealedVTableEntries.Count; i++)
+ {
+ MethodDesc canonImplMethod = _sealedVTableEntries[i].GetCanonMethodTarget(CanonicalFormKind.Specific);
+ IMethodNode relocTarget = factory.MethodEntrypoint(canonImplMethod, _sealedVTableEntries[i].OwningType.IsValueType);
+
+ if (factory.Target.SupportsRelativePointers)
+ objData.EmitReloc(relocTarget, RelocType.IMAGE_REL_BASED_RELPTR32);
+ else
+ objData.EmitPointerReloc(relocTarget);
+ }
+ }
+
+ return objData.ToObjectData();
+ }
+
+ public override int ClassCode => 1632890252;
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
+ {
+ return comparer.Compare(_type, ((SealedVTableNode)other)._type);
+ }
+ }
+}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ShadowConcreteMethodNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ShadowConcreteMethodNode.cs
index 40d7cc978..5f1eef5b8 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ShadowConcreteMethodNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ShadowConcreteMethodNode.cs
@@ -20,7 +20,7 @@ namespace ILCompiler.DependencyAnalysis
/// method body, as if it was generated. The node acts as a symbol for the canonical
/// method for convenience.
/// </summary>
- public class ShadowConcreteMethodNode : DependencyNodeCore<NodeFactory>, IMethodNode
+ public class ShadowConcreteMethodNode : DependencyNodeCore<NodeFactory>, IMethodNode, ISymbolNodeWithLinkage
{
/// <summary>
/// Gets the canonical method body that defines the dependencies of this node.
@@ -53,6 +53,11 @@ namespace ILCompiler.DependencyAnalysis
CanonicalMethodNode = canonicalMethod;
}
+ public ISymbolNode NodeForLinkage(NodeFactory factory)
+ {
+ return CanonicalMethodNode;
+ }
+
public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
{
DependencyList dependencies = new DependencyList();
@@ -99,9 +104,9 @@ namespace ILCompiler.DependencyAnalysis
public sealed override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null;
public sealed override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) => null;
- int ISortableSymbolNode.ClassCode => -1440570971;
+ int ISortableNode.ClassCode => -1440570971;
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
+ int ISortableNode.CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
var compare = comparer.Compare(Method, ((ShadowConcreteMethodNode)other).Method);
if (compare != 0)
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ShadowConcreteUnboxingThunkNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ShadowConcreteUnboxingThunkNode.cs
index fe973fdb3..9a1dae917 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ShadowConcreteUnboxingThunkNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ShadowConcreteUnboxingThunkNode.cs
@@ -70,9 +70,9 @@ namespace ILCompiler.DependencyAnalysis
public sealed override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null;
public sealed override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) => null;
- int ISortableSymbolNode.ClassCode => -501699818;
+ int ISortableNode.ClassCode => -501699818;
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
+ int ISortableNode.CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
var compare = comparer.Compare(Method, ((ShadowConcreteUnboxingThunkNode)other).Method);
if (compare != 0)
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SortableDependencyNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SortableDependencyNode.cs
index 521a5bf45..f65c5b602 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SortableDependencyNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SortableDependencyNode.cs
@@ -12,7 +12,7 @@ using Internal.TypeSystem;
namespace ILCompiler.DependencyAnalysis
{
- public abstract class SortableDependencyNode : DependencyNodeCore<NodeFactory>
+ public abstract class SortableDependencyNode : DependencyNodeCore<NodeFactory>, ISortableNode
{
#if !SUPPORT_JIT
/// <summary>
@@ -29,10 +29,10 @@ namespace ILCompiler.DependencyAnalysis
/// This is really just a number, ideally produced by "new Random().Next(int.MinValue, int.MaxValue)".
/// If two manage to conflict (which is pretty unlikely), just make a new one...
/// </remarks>
- protected internal abstract int ClassCode { get; }
-
+ public abstract int ClassCode { get; }
+
// Note to implementers: the type of `other` is actually the same as the type of `this`.
- protected internal virtual int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public virtual int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
throw new NotImplementedException("Multiple nodes of this type are not supported");
}
@@ -75,12 +75,18 @@ namespace ILCompiler.DependencyAnalysis
BlockReflectionTypeMapNode,
StaticsInfoHashtableNode,
ReflectionVirtualInvokeMapNode,
- ExternalReferencesTableNode,
ArrayOfEmbeddedPointersNode,
DefaultConstructorMapNode,
+ ExternalReferencesTableNode,
StackTraceEmbeddedMetadataNode,
StackTraceMethodMappingNode,
- ArrayOfEmbeddedDataNode
+ ArrayOfEmbeddedDataNode,
+ WindowsDebugNeedTypeIndicesStoreNode,
+ WindowsDebugMethodSignatureMapSectionNode,
+ WindowsDebugTypeSignatureMapSectionNode,
+ WindowsDebugManagedNativeDictionaryInfoSectionNode,
+ WindowsDebugTypeRecordsSectionNode,
+ WindowsDebugPseudoAssemblySectionNode,
}
public class EmbeddedObjectNodeComparer : IComparer<EmbeddedObjectNode>
@@ -159,7 +165,7 @@ namespace ILCompiler.DependencyAnalysis
else
{
Debug.Assert(x.GetType() != y.GetType());
- return codeX - codeY;
+ return codeY > codeX ? -1 : 1;
}
}
else
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StackTraceEmbeddedMetadataNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StackTraceEmbeddedMetadataNode.cs
index b1ab09a29..39c62fcb0 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StackTraceEmbeddedMetadataNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StackTraceEmbeddedMetadataNode.cs
@@ -38,7 +38,7 @@ namespace ILCompiler.DependencyAnalysis
public int Offset => 0;
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.StackTraceEmbeddedMetadataNode;
+ public override int ClassCode => (int)ObjectNodeOrder.StackTraceEmbeddedMetadataNode;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StackTraceMethodMappingNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StackTraceMethodMappingNode.cs
index de12c6f92..d9c13b19c 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StackTraceMethodMappingNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StackTraceMethodMappingNode.cs
@@ -31,7 +31,7 @@ namespace ILCompiler.DependencyAnalysis
public int Offset => 0;
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.StackTraceMethodMappingNode;
+ public override int ClassCode => (int)ObjectNodeOrder.StackTraceMethodMappingNode;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StaticsInfoHashtableNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StaticsInfoHashtableNode.cs
index 14b81d92e..d1ea7d3d4 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StaticsInfoHashtableNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StaticsInfoHashtableNode.cs
@@ -70,7 +70,7 @@ namespace ILCompiler.DependencyAnalysis
dependencies.Add(factory.Indirection(factory.TypeNonGCStaticsSymbol(metadataType)), "Non-GC statics indirection for StaticsInfoHashtable");
}
- if (metadataType.ThreadStaticFieldSize.AsInt > 0)
+ if (metadataType.ThreadGcStaticFieldSize.AsInt > 0)
{
if (factory.Target.Abi == TargetAbi.ProjectN)
{
@@ -116,7 +116,7 @@ namespace ILCompiler.DependencyAnalysis
ISymbolNode nonGCStaticIndirection = factory.Indirection(factory.TypeNonGCStaticsSymbol(metadataType));
bag.AppendUnsigned(BagElementKind.NonGcStaticData, _nativeStaticsReferences.GetIndex(nonGCStaticIndirection));
}
- if (metadataType.ThreadStaticFieldSize.AsInt > 0)
+ if (metadataType.ThreadGcStaticFieldSize.AsInt > 0)
{
if (factory.Target.Abi == TargetAbi.ProjectN)
{
@@ -148,6 +148,6 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.StaticsInfoHashtableNode;
+ public override int ClassCode => (int)ObjectNodeOrder.StaticsInfoHashtableNode;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StringAllocatorMethodNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StringAllocatorMethodNode.cs
index fe9528040..4e68d5536 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StringAllocatorMethodNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StringAllocatorMethodNode.cs
@@ -73,9 +73,9 @@ namespace ILCompiler.DependencyAnalysis
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
- int ISortableSymbolNode.ClassCode => 1991750873;
+ int ISortableNode.ClassCode => 1991750873;
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
+ int ISortableNode.CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_allocationMethod, ((StringAllocatorMethodNode)other)._allocationMethod);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StructMarshallingStubMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StructMarshallingStubMapNode.cs
index 604e25076..d4d5664fd 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StructMarshallingStubMapNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StructMarshallingStubMapNode.cs
@@ -71,7 +71,7 @@ namespace ILCompiler.DependencyAnalysis
writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(structEntry.UnmarshallingThunk))),
writer.GetUnsignedConstant(_externalReferences.GetIndex(factory.MethodEntrypoint(structEntry.CleanupThunk))));
- uint size = (uint)nativeType.InstanceByteCount.AsInt;
+ uint size = (uint)nativeType.InstanceFieldSize.AsInt;
uint mask = (uint)(nativeType.Fields.Length << 1) | (uint)(nativeType.HasInvalidLayout ? 1 : 0);
Vertex data = writer.GetTuple(
@@ -106,6 +106,6 @@ namespace ILCompiler.DependencyAnalysis
}
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.StructMarshallingStubMapNode;
+ public override int ClassCode => (int)ObjectNodeOrder.StructMarshallingStubMapNode;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMDebug.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMDebug.cs
index 0a1cd0639..b0d8ab2ee 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMDebug.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMDebug.cs
@@ -9,6 +9,7 @@ namespace ILCompiler.DependencyAnalysis
{
public static class ARMDebug
{
+ [System.Diagnostics.Conditional("DEBUG")]
public static void EmitNYIAssert(NodeFactory factory, ref ARMEmitter encoder, string message,
[System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = null,
[System.Runtime.CompilerServices.CallerMemberName] string memberName = null,
@@ -21,6 +22,7 @@ namespace ILCompiler.DependencyAnalysis
encoder.EmitJMP(NYI_Assert);
}
+ [System.Diagnostics.Conditional("DEBUG")]
public static void EmitHelperNYIAssert(NodeFactory factory, ref ARMEmitter encoder, ReadyToRunHelperId hId,
[System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = null,
[System.Runtime.CompilerServices.CallerMemberName] string memberName = null,
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMInitialInterfaceDispatchStubNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMInitialInterfaceDispatchStubNode.cs
index 1c201ebe3..7e1793acf 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMInitialInterfaceDispatchStubNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMInitialInterfaceDispatchStubNode.cs
@@ -52,6 +52,6 @@ namespace ILCompiler.DependencyAnalysis
throw new NotImplementedException();
}
- protected internal override int ClassCode => 588185132;
+ public override int ClassCode => 588185132;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs
index d4bf28b31..a05365715 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs
@@ -33,13 +33,14 @@ namespace ILCompiler.DependencyAnalysis
MethodDesc targetMethod = (MethodDesc)Target;
Debug.Assert(!targetMethod.OwningType.IsInterface);
+ Debug.Assert(!targetMethod.CanMethodBeInSealedVTable());
int pointerSize = factory.Target.PointerSize;
int slot = 0;
if (!relocsOnly)
{
- slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod);
+ slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod, targetMethod.OwningType);
Debug.Assert(slot != -1);
}
@@ -162,11 +163,13 @@ namespace ILCompiler.DependencyAnalysis
if (target.TargetNeedsVTableLookup)
{
+ Debug.Assert(!target.TargetMethod.CanMethodBeInSealedVTable());
+
encoder.EmitLDR(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg1);
int slot = 0;
if (!relocsOnly)
- slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, target.TargetMethod);
+ slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, target.TargetMethod, target.TargetMethod.OwningType);
Debug.Assert(slot != -1);
encoder.EmitLDR(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg2,
@@ -212,7 +215,9 @@ namespace ILCompiler.DependencyAnalysis
encoder.EmitLDR(encoder.TargetRegister.Result, encoder.TargetRegister.Arg0);
- int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod);
+ Debug.Assert(!targetMethod.CanMethodBeInSealedVTable());
+
+ int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod, targetMethod.OwningType);
Debug.Assert(slot != -1);
encoder.EmitLDR(encoder.TargetRegister.Result, encoder.TargetRegister.Result,
((short)(EETypeNode.GetVTableOffset(factory.Target.PointerSize) + (slot * factory.Target.PointerSize))));
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64Emitter.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64Emitter.cs
index 09ebadeaa..662867f99 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64Emitter.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64Emitter.cs
@@ -88,6 +88,20 @@ namespace ILCompiler.DependencyAnalysis.X64
}
}
+ public void EmitJE(ISymbolNode symbol)
+ {
+ if (symbol.RepresentsIndirectionCell)
+ {
+ throw new NotImplementedException();
+ }
+ else
+ {
+ Builder.EmitByte(0x0f);
+ Builder.EmitByte(0x84);
+ Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_REL32);
+ }
+ }
+
public void EmitINT3()
{
Builder.EmitByte(0xCC);
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs
index 614c171e6..dbe8319c8 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs
@@ -32,6 +32,7 @@ namespace ILCompiler.DependencyAnalysis
MethodDesc targetMethod = (MethodDesc)Target;
Debug.Assert(!targetMethod.OwningType.IsInterface);
+ Debug.Assert(!targetMethod.CanMethodBeInSealedVTable());
AddrMode loadFromThisPtr = new AddrMode(encoder.TargetRegister.Arg0, null, 0, 0, AddrModeSize.Int64);
encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromThisPtr);
@@ -41,7 +42,7 @@ namespace ILCompiler.DependencyAnalysis
int slot = 0;
if (!relocsOnly)
{
- slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod);
+ slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod, targetMethod.OwningType);
Debug.Assert(slot != -1);
}
Debug.Assert(((INodeWithDebugInfo)this).DebugLocInfos[1].NativeOffset == encoder.Builder.CountBytes);
@@ -126,7 +127,11 @@ namespace ILCompiler.DependencyAnalysis
else
{
encoder.EmitLEAQ(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target), - NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.Target, target));
- // TODO: performance optimization - inline the check verifying whether we need to trigger the cctor
+
+ AddrMode initialized = new AddrMode(encoder.TargetRegister.Arg2, null, factory.Target.PointerSize, 0, AddrModeSize.Int32);
+ encoder.EmitCMP(ref initialized, 1);
+ encoder.EmitJE(factory.HelperEntrypoint(HelperEntrypoint.GetThreadStaticBaseForType));
+
encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnThreadStaticBase));
}
}
@@ -167,12 +172,14 @@ namespace ILCompiler.DependencyAnalysis
if (target.TargetNeedsVTableLookup)
{
+ Debug.Assert(!target.TargetMethod.CanMethodBeInSealedVTable());
+
AddrMode loadFromThisPtr = new AddrMode(encoder.TargetRegister.Arg1, null, 0, 0, AddrModeSize.Int64);
encoder.EmitMOV(encoder.TargetRegister.Arg2, ref loadFromThisPtr);
int slot = 0;
if (!relocsOnly)
- slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, target.TargetMethod);
+ slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, target.TargetMethod, target.TargetMethod.OwningType);
Debug.Assert(slot != -1);
AddrMode loadFromSlot = new AddrMode(encoder.TargetRegister.Arg2, null, EETypeNode.GetVTableOffset(factory.Target.PointerSize) + (slot * factory.Target.PointerSize), 0, AddrModeSize.Int64);
@@ -214,7 +221,9 @@ namespace ILCompiler.DependencyAnalysis
AddrMode loadFromThisPtr = new AddrMode(encoder.TargetRegister.Arg0, null, 0, 0, AddrModeSize.Int64);
encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromThisPtr);
- int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod);
+ Debug.Assert(!targetMethod.CanMethodBeInSealedVTable());
+
+ int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod, targetMethod.OwningType);
Debug.Assert(slot != -1);
AddrMode loadFromSlot = new AddrMode(encoder.TargetRegister.Result, null, EETypeNode.GetVTableOffset(factory.Target.PointerSize) + (slot * factory.Target.PointerSize), 0, AddrModeSize.Int64);
encoder.EmitMOV(encoder.TargetRegister.Result, ref loadFromSlot);
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsIndexNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsIndexNode.cs
index f350c2cfb..fbfe07f9e 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsIndexNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsIndexNode.cs
@@ -82,19 +82,12 @@ namespace ILCompiler.DependencyAnalysis
return objData.ToObjectData();
}
- protected internal override int ClassCode => -968500265;
+ public override int ClassCode => -968500265;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return string.Compare(_prefix, ((ThreadStaticsIndexNode)other)._prefix);
}
-
- int ISortableSymbolNode.ClassCode => ClassCode;
-
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
- {
- return CompareToImpl((ObjectNode)other, comparer);
- }
}
// The data structure used by the OS loader to load TLS chunks.
@@ -182,9 +175,9 @@ namespace ILCompiler.DependencyAnalysis
return objData.ToObjectData();
}
- protected internal override int ClassCode => -754150753;
+ public override int ClassCode => -754150753;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return string.Compare(_prefix, ((ThreadStaticsDirectoryNode)other)._prefix);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsNode.cs
index 357dde0fe..80c497e2c 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsNode.cs
@@ -20,7 +20,7 @@ namespace ILCompiler.DependencyAnalysis
public ThreadStaticsNode(MetadataType type, NodeFactory factory)
{
- Debug.Assert(factory.Target.Abi == TargetAbi.CoreRT);
+ Debug.Assert(factory.Target.Abi == TargetAbi.CoreRT || factory.Target.Abi == TargetAbi.CppCodegen);
_type = type;
}
@@ -76,9 +76,9 @@ namespace ILCompiler.DependencyAnalysis
builder.EmitPointerReloc(GetGCStaticEETypeNode(factory));
}
- protected internal override int ClassCode => 2091208431;
+ public override int ClassCode => 2091208431;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_type, ((ThreadStaticsNode)other)._type);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsOffsetNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsOffsetNode.cs
index 096ebe98a..5eb2f7525 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsOffsetNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsOffsetNode.cs
@@ -74,18 +74,11 @@ namespace ILCompiler.DependencyAnalysis
builder.EmitReloc(factory.TypeThreadStaticsSymbol(_type), RelocType.IMAGE_REL_SECREL);
}
- protected internal override int ClassCode => 419394032;
+ public sealed override int ClassCode => 419394032;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_type, ((ThreadStaticsOffsetNode)other)._type);
}
-
- int ISortableSymbolNode.ClassCode => 419394032;
-
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
- {
- return CompareToImpl((SortableDependencyNode)other, comparer);
- }
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeManagerIndirectionNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeManagerIndirectionNode.cs
index 4199c29fb..7a7c4b797 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeManagerIndirectionNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeManagerIndirectionNode.cs
@@ -34,6 +34,6 @@ namespace ILCompiler.DependencyAnalysis
return objData.ToObjectData();
}
- protected internal override int ClassCode => -2028598574;
+ public override int ClassCode => -2028598574;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataMapNode.cs
index 75012d6e8..469d86dd5 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataMapNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataMapNode.cs
@@ -53,12 +53,9 @@ namespace ILCompiler.DependencyAnalysis
foreach (var mappingEntry in factory.MetadataManager.GetTypeDefinitionMapping(factory))
{
- if (!factory.CompilationModuleGroup.ContainsType(mappingEntry.Entity))
- continue;
-
// Types that don't have EETypes don't need mapping table entries because there's no risk of them
// not unifying to the same System.Type at runtime.
- if (!factory.MetadataManager.TypeGeneratesEEType(mappingEntry.Entity))
+ if (!factory.MetadataManager.TypeGeneratesEEType(mappingEntry.Entity) && !factory.CompilationModuleGroup.ShouldReferenceThroughImportTable(mappingEntry.Entity))
continue;
// Go with a necessary type symbol. It will be upgraded to a constructed one if a constructed was emitted.
@@ -82,6 +79,6 @@ namespace ILCompiler.DependencyAnalysis
protected internal override int Phase => (int)ObjectNodePhase.Ordered;
- protected internal override int ClassCode => (int)ObjectNodeOrder.TypeMetadataMapNode;
+ public override int ClassCode => (int)ObjectNodeOrder.TypeMetadataMapNode;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataNode.cs
index a8416afad..39ad01e9f 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataNode.cs
@@ -51,6 +51,23 @@ namespace ILCompiler.DependencyAnalysis
dependencies.Add(factory.MethodMetadata(_type.GetMethod("Invoke", null)), "Delegate invoke method metadata");
}
+ // If the user asked for complete metadata to be generated for all types that are getting metadata, ensure that.
+ var mdManager = (UsageBasedMetadataManager)factory.MetadataManager;
+ if ((mdManager._generationOptions & UsageBasedMetadataGenerationOptions.CompleteTypesOnly) != 0)
+ {
+ foreach (MethodDesc method in _type.GetMethods())
+ {
+ if (!mdManager.IsReflectionBlocked(method))
+ dependencies.Add(factory.MethodMetadata(method), "Complete metadata for type");
+ }
+
+ foreach (FieldDesc field in _type.GetFields())
+ {
+ if (!mdManager.IsReflectionBlocked(field))
+ dependencies.Add(factory.FieldMetadata(field), "Complete metadata for type");
+ }
+ }
+
return dependencies;
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeThreadStaticIndexNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeThreadStaticIndexNode.cs
index 11ac06f2c..2c20841bb 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeThreadStaticIndexNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeThreadStaticIndexNode.cs
@@ -67,9 +67,9 @@ namespace ILCompiler.DependencyAnalysis
return objData.ToObjectData();
}
- protected internal override int ClassCode => -149601250;
+ public override int ClassCode => -149601250;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_type, ((TypeThreadStaticIndexNode)other)._type);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UnboxingStubNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UnboxingStubNode.cs
index d0cb80ba3..ae39c5074 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UnboxingStubNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UnboxingStubNode.cs
@@ -70,19 +70,12 @@ namespace ILCompiler.DependencyAnalysis
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
- protected internal override int ClassCode => -1846923013;
+ public override int ClassCode => -1846923013;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(Method, ((UnboxingStubNode)other).Method);
}
-
- int ISortableSymbolNode.ClassCode => ClassCode;
-
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
- {
- return CompareToImpl((ObjectNode)other, comparer);
- }
}
//
@@ -122,9 +115,9 @@ namespace ILCompiler.DependencyAnalysis
return objData.ToObjectData();
}
- protected internal override int ClassCode => 1102274050;
+ public override int ClassCode => 1102274050;
- protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return _isEndSymbol.CompareTo(((WindowsUnboxingStubsRegionNode)other)._isEndSymbol);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcDictionaryLayoutNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcDictionaryLayoutNode.cs
deleted file mode 100644
index d268fa17b..000000000
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcDictionaryLayoutNode.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Diagnostics;
-
-using Internal.TypeSystem;
-
-using ILCompiler.DependencyAnalysisFramework;
-
-namespace ILCompiler.DependencyAnalysis
-{
- /// <summary>
- /// Represents the layout of the generic dictionary associated with a given canonical
- /// generic type or generic method. Maintains a bag of <see cref="GenericLookupResult"/> associated
- /// with the canonical entity.
- /// </summary>
- /// <remarks>
- /// The generic dictionary doesn't have any dependent nodes because <see cref="GenericLookupResult"/>
- /// are runtime-determined - the concrete dependency depends on the generic context the canonical
- /// entity is instantiated with.
- /// </remarks>
- public partial class UtcDictionaryLayoutNode : DictionaryLayoutNode
- {
- public override bool HasFixedSlots
- {
- get
- {
- return false;
- }
- }
-
- public UtcDictionaryLayoutNode(TypeSystemEntity owningMethodOrType) : base(owningMethodOrType)
- {
-
- }
-
-#if !PROJECTN
- public override void EnsureEntry(GenericLookupResult lookupResult) => throw new NotImplementedException();
- public override int GetSlotForEntry(GenericLookupResult entry) => throw new NotImplementedException();
- public override IEnumerable<GenericLookupResult> Entries => throw new NotImplementedException();
- public override ICollection<NativeLayoutVertexNode> GetTemplateEntries(NodeFactory factory) => throw new NotImplementedException();
- public override void EmitDictionaryData(ref ObjectDataBuilder builder, NodeFactory factory, GenericDictionaryNode dictionary, bool fixedLayoutOnly) => throw new NotImplementedException();
-#endif
- }
-}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs
index 776ca6a2b..80aec11b0 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs
@@ -59,7 +59,7 @@ namespace ILCompiler
return null;
}
- private static MetadataManager PickMetadataManager(CompilerTypeSystemContext context, CompilationModuleGroup compilationModuleGroup, IEnumerable<ModuleDesc> inputModules, IEnumerable<ModuleDesc> inputMetadataOnlyAssemblies, string metadataFile)
+ private static MetadataManager PickMetadataManager(CompilerTypeSystemContext context, CompilationModuleGroup compilationModuleGroup, IEnumerable<ModuleDesc> inputModules, IEnumerable<ModuleDesc> inputMetadataOnlyAssemblies, string metadataFile, bool emitStackTraceMetadata, bool disableExceptionMessages, bool disableInvokeThunks)
{
if (metadataFile == null)
{
@@ -67,7 +67,28 @@ namespace ILCompiler
}
else
{
- return new PrecomputedMetadataManager(compilationModuleGroup, context, FindMetadataDescribingModuleInInputSet(inputModules), inputModules, inputMetadataOnlyAssemblies, ReadBytesFromFile(metadataFile), new UtcStackTraceEmissionPolicy());
+ // Set Policies according to passed arguments
+ StackTraceEmissionPolicy stackTraceEmissionPolicy;
+ if (emitStackTraceMetadata)
+ {
+ stackTraceEmissionPolicy = new UtcStackTraceEmissionPolicy();
+ }
+ else
+ {
+ stackTraceEmissionPolicy = new NoStackTraceEmissionPolicy();
+ }
+
+ ManifestResourceBlockingPolicy resourceBlockingPolicy;
+ if (disableExceptionMessages)
+ {
+ resourceBlockingPolicy = new FrameworkStringResourceBlockingPolicy();
+ }
+ else
+ {
+ resourceBlockingPolicy = new NoManifestResourceBlockingPolicy();
+ }
+
+ return new PrecomputedMetadataManager(compilationModuleGroup, context, FindMetadataDescribingModuleInInputSet(inputModules), inputModules, inputMetadataOnlyAssemblies, ReadBytesFromFile(metadataFile), stackTraceEmissionPolicy , resourceBlockingPolicy, disableInvokeThunks);
}
}
@@ -86,11 +107,14 @@ namespace ILCompiler
string outputFile,
UTCNameMangler nameMangler,
bool buildMRT,
+ bool emitStackTraceMetadata,
+ bool disableExceptionMessages,
+ bool allowInvokeThunks,
DictionaryLayoutProvider dictionaryLayoutProvider,
ImportedNodeProvider importedNodeProvider)
: base(context,
compilationModuleGroup,
- PickMetadataManager(context, compilationModuleGroup, inputModules, inputMetadataOnlyAssemblies, metadataFile),
+ PickMetadataManager(context, compilationModuleGroup, inputModules, inputMetadataOnlyAssemblies, metadataFile, emitStackTraceMetadata, disableExceptionMessages, allowInvokeThunks),
NewEmptyInteropStubManager(context, compilationModuleGroup),
nameMangler,
new AttributeDrivenLazyGenericsPolicy(),
@@ -159,6 +183,7 @@ namespace ILCompiler
graph.AddRoot(EagerCctorTable, "EagerCctorTable is always generated");
graph.AddRoot(DispatchMapTable, "DispatchMapTable is always generated");
graph.AddRoot(FrozenSegmentRegion, "FrozenSegmentRegion is always generated");
+ graph.AddRoot(InterfaceDispatchCellSection, "Interface dispatch cell section is always generated");
graph.AddRoot(TypeManagerIndirection, "ModuleManagerIndirection is always generated");
graph.AddRoot(GCStaticsRegion, "GC StaticsRegion is always generated");
graph.AddRoot(GCStaticDescRegion, "GC Static Desc is always generated");
@@ -212,12 +237,21 @@ namespace ILCompiler
{
if (method.HasCustomAttribute("System.Runtime", "RuntimeImportAttribute"))
{
- return new RuntimeImportMethodNode(method);
+ RuntimeImportMethodNode runtimeImportMethod = new RuntimeImportMethodNode(method);
+
+ // If the method is imported from either the current module or the runtime, reference it directly
+ if (CompilationModuleGroup.ContainsMethodBody(method, false))
+ return runtimeImportMethod;
+ // If the method is imported from the runtime but not a managed assembly, reference it directly
+ else if (!CompilationModuleGroup.ImportsMethod(method, false))
+ return runtimeImportMethod;
+
+ // If the method is imported from a managed assembly, reference it via an import cell
}
-
- if (CompilationModuleGroup.ContainsMethodBody(method, false))
+ else
{
- return NonExternMethodSymbol(method, false);
+ if (CompilationModuleGroup.ContainsMethodBody(method, false))
+ return NonExternMethodSymbol(method, false);
}
return _importedNodeProvider.ImportedMethodCodeNode(this, method, false);
@@ -251,16 +285,18 @@ namespace ILCompiler
public GCStaticDescRegionNode GCStaticDescRegion = new GCStaticDescRegionNode(
CompilationUnitPrefix + "__GCStaticDescStart",
- CompilationUnitPrefix + "__GCStaticDescEnd");
+ CompilationUnitPrefix + "__GCStaticDescEnd",
+ new SortableDependencyNode.EmbeddedObjectNodeComparer(new CompilerComparer()));
public GCStaticDescRegionNode ThreadStaticGCDescRegion = new GCStaticDescRegionNode(
CompilationUnitPrefix + "__ThreadStaticGCDescStart",
- CompilationUnitPrefix + "__ThreadStaticGCDescEnd");
+ CompilationUnitPrefix + "__ThreadStaticGCDescEnd",
+ new SortableDependencyNode.EmbeddedObjectNodeComparer(new CompilerComparer()));
public ArrayOfEmbeddedDataNode<ThreadStaticsOffsetNode> ThreadStaticsOffsetRegion = new ArrayOfEmbeddedDataNode<ThreadStaticsOffsetNode>(
CompilationUnitPrefix + "__ThreadStaticOffsetRegionStart",
CompilationUnitPrefix + "__ThreadStaticOffsetRegionEnd",
- null);
+ new SortableDependencyNode.EmbeddedObjectNodeComparer(new CompilerComparer()));
public ThreadStaticsIndexNode ThreadStaticsIndex;
@@ -348,14 +384,6 @@ namespace ILCompiler
return ReadOnlyDataBlob(NameMangler.GetMangledFieldName(field), ((EcmaField)field).GetFieldRvaData(), Target.PointerSize);
}
- public class UtcDictionaryLayoutProvider : DictionaryLayoutProvider
- {
- public override DictionaryLayoutNode GetLayout(TypeSystemEntity methodOrType)
- {
- return new UtcDictionaryLayoutNode(methodOrType);
- }
- }
-
public ISymbolNode LoopHijackFlagSymbol()
{
return LoopHijackFlag;
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcThreadStaticsNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcThreadStaticsNode.cs
index 3aeadde41..9647ef562 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcThreadStaticsNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcThreadStaticsNode.cs
@@ -7,7 +7,7 @@ using Internal.TypeSystem;
namespace ILCompiler.DependencyAnalysis
{
- public class UtcThreadStaticsNode : ObjectNode, ISymbolDefinitionNode
+ public class UtcThreadStaticsNode : ObjectNode, ISymbolDefinitionNode, ISymbolNodeWithDebugInfo, ISortableSymbolNode
{
private MetadataType _type;
@@ -26,6 +26,8 @@ namespace ILCompiler.DependencyAnalysis
public int Offset => 0;
public MetadataType Type => _type;
+ public IDebugInfo DebugInfo => NullTypeIndexDebugInfo.Instance;
+
public static string GetMangledName(TypeDesc type, NameMangler nameMangler)
{
return nameMangler.NodeMangler.ThreadStatics(type);
@@ -56,11 +58,16 @@ namespace ILCompiler.DependencyAnalysis
{
ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);
builder.RequireInitialPointerAlignment();
- builder.EmitZeros(_type.ThreadStaticFieldSize.AsInt);
+ builder.EmitZeros(_type.ThreadGcStaticFieldSize.AsInt);
builder.AddSymbol(this);
return builder.ToObjectData();
}
- protected internal override int ClassCode => -1421136129;
+ public sealed override int ClassCode => -1421136129;
+
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
+ {
+ return comparer.Compare(_type, ((UtcThreadStaticsNode)other)._type);
+ }
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugILImagesSection.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugILImagesSection.cs
index 5ac16bbb3..284e4fe17 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugILImagesSection.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugILImagesSection.cs
@@ -30,7 +30,7 @@ namespace ILCompiler.DependencyAnalysis
public int Offset => 0;
- protected internal override int ClassCode => 2051656903;
+ public override int ClassCode => 2051656903;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugManagedNativeDictionaryInfoSection.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugManagedNativeDictionaryInfoSection.cs
index 5d3ebd6e7..79c176034 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugManagedNativeDictionaryInfoSection.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugManagedNativeDictionaryInfoSection.cs
@@ -30,7 +30,8 @@ namespace ILCompiler.DependencyAnalysis
public int Offset => 0;
- protected internal override int ClassCode => 1502860768;
+ protected internal override int Phase => (int)ObjectNodePhase.Ordered;
+ public override int ClassCode => (int)ObjectNodeOrder.WindowsDebugManagedNativeDictionaryInfoSectionNode;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMergedAssemblyRecordsSection.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMergedAssemblyRecordsSection.cs
index 49f75a100..d16f9cc5b 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMergedAssemblyRecordsSection.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMergedAssemblyRecordsSection.cs
@@ -31,7 +31,7 @@ namespace ILCompiler.DependencyAnalysis
public int Offset => 0;
- protected internal override int ClassCode => -1250136545;
+ public override int ClassCode => -1250136545;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMethodInfoSection.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMethodInfoSection.cs
index 7d4396fc7..9a8d8e765 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMethodInfoSection.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMethodInfoSection.cs
@@ -102,7 +102,7 @@ namespace ILCompiler.DependencyAnalysis
// find virtual method slot.
MethodDesc declaringMethodForSlot =
MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(md.GetTypicalMethodDefinition());
- int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, declaringMethodForSlot);
+ int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, declaringMethodForSlot, type);
if (slot != -1 && !methodList.ContainsKey(methodToken))
methodList.Add(methodToken, slot);
}
@@ -150,6 +150,6 @@ namespace ILCompiler.DependencyAnalysis
return "___DebugMethodInfoSection";
}
- protected internal override int ClassCode => 513099721;
+ public override int ClassCode => 513099721;
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMethodMapSection.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMethodMapSection.cs
index c351d54e8..9ff897804 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMethodMapSection.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMethodMapSection.cs
@@ -30,7 +30,8 @@ namespace ILCompiler.DependencyAnalysis
public int Offset => 0;
- protected internal override int ClassCode => -2063194124;
+ protected internal override int Phase => (int)ObjectNodePhase.Ordered;
+ public override int ClassCode => (int)ObjectNodeOrder.WindowsDebugMethodSignatureMapSectionNode;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
@@ -178,9 +179,6 @@ namespace ILCompiler.DependencyAnalysis
if (relocsOnly)
return new ObjectData(Array.Empty<byte>(), Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this });
- if (factory.WindowsDebugData.DebugTypeRecordsSection != null)
- factory.WindowsDebugData.DebugTypeRecordsSection.Neuter();
-
List<Relocation> relocations = new List<Relocation>();
DebugInfoBlob debugData = GetDebugMethodRVAToTokenMap(factory.WindowsDebugData.DebugPseudoAssemblySection.PseudoAssembly, factory.MetadataManager.GetCompiledMethodBodies(), out relocations);
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugNeedTypeIndicesStoreNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugNeedTypeIndicesStoreNode.cs
index 71435021c..3aa7335d8 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugNeedTypeIndicesStoreNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugNeedTypeIndicesStoreNode.cs
@@ -21,7 +21,8 @@ namespace ILCompiler.DependencyAnalysis
public int Offset => 0;
- protected internal override int ClassCode => 1275723356;
+ protected internal override int Phase => (int)ObjectNodePhase.Ordered;
+ public override int ClassCode => (int)ObjectNodeOrder.WindowsDebugNeedTypeIndicesStoreNode;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugPseudoAssemblySection.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugPseudoAssemblySection.cs
index 7f393b2d4..6780d0685 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugPseudoAssemblySection.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugPseudoAssemblySection.cs
@@ -29,7 +29,8 @@ namespace ILCompiler.DependencyAnalysis
public int Offset => 0;
- protected internal override int ClassCode => 920778380;
+ protected internal override int Phase => (int)ObjectNodePhase.Ordered;
+ public override int ClassCode => (int)ObjectNodeOrder.WindowsDebugPseudoAssemblySectionNode;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugTypeRecordsSection.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugTypeRecordsSection.cs
index 660559ccb..e74e0a077 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugTypeRecordsSection.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugTypeRecordsSection.cs
@@ -33,7 +33,8 @@ namespace ILCompiler.DependencyAnalysis
public int Offset => 0;
- protected internal override int ClassCode => -2081034825;
+ protected internal override int Phase => (int)ObjectNodePhase.Ordered;
+ public override int ClassCode => (int)ObjectNodeOrder.WindowsDebugTypeRecordsSectionNode;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
@@ -73,9 +74,10 @@ namespace ILCompiler.DependencyAnalysis
return _dbgInfoWriter.GetClassTypeIndex(classTypeDescriptor);
}
- uint ITypesDebugInfoWriter.GetCompleteClassTypeIndex(ClassTypeDescriptor classTypeDescriptor, ClassFieldsTypeDescriptor classFieldsTypeDescriptior, DataFieldDescriptor[] fields)
+ uint ITypesDebugInfoWriter.GetCompleteClassTypeIndex(ClassTypeDescriptor classTypeDescriptor, ClassFieldsTypeDescriptor classFieldsTypeDescriptior,
+ DataFieldDescriptor[] fields, StaticDataFieldDescriptor[] statics)
{
- return _dbgInfoWriter.GetCompleteClassTypeIndex(classTypeDescriptor, classFieldsTypeDescriptior, fields);
+ return _dbgInfoWriter.GetCompleteClassTypeIndex(classTypeDescriptor, classFieldsTypeDescriptior, fields, statics);
}
uint ITypesDebugInfoWriter.GetArrayTypeIndex(ClassTypeDescriptor classDescriptor, ArrayTypeDescriptor arrayTypeDescriptor)
@@ -98,6 +100,11 @@ namespace ILCompiler.DependencyAnalysis
return _dbgInfoWriter.GetMemberFunctionId(memberIdDescriptor);
}
+ uint ITypesDebugInfoWriter.GetPrimitiveTypeIndex(TypeDesc type)
+ {
+ return PrimitiveTypeDescriptor.GetPrimitiveTypeIndex(type);
+ }
+
string ITypesDebugInfoWriter.GetMangledName(TypeDesc type)
{
return _nodeFactory.NameMangler.GetMangledTypeName(type);
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugTypeSignatureMapSection.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugTypeSignatureMapSection.cs
index 0ec387d9c..a5aaea9b7 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugTypeSignatureMapSection.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugTypeSignatureMapSection.cs
@@ -31,7 +31,8 @@ namespace ILCompiler.DependencyAnalysis
public int Offset => 0;
- protected internal override int ClassCode => 1029840999;
+ protected internal override int Phase => (int)ObjectNodePhase.Ordered;
+ public override int ClassCode => (int)ObjectNodeOrder.WindowsDebugTypeSignatureMapSectionNode;
public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
{
@@ -129,9 +130,6 @@ namespace ILCompiler.DependencyAnalysis
if (relocsOnly)
return new ObjectData(Array.Empty<byte>(), Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this });
- if (factory.WindowsDebugData.DebugTypeRecordsSection != null)
- factory.WindowsDebugData.DebugTypeRecordsSection.Neuter();
-
DebugInfoBlob debugData = GetDebugTypeIndexToTokenMap(factory.WindowsDebugData.DebugPseudoAssemblySection.PseudoAssembly, factory.WindowsDebugData.UserDefinedTypeDescriptor.CompleteKnownTypes);
return new ObjectData(debugData.ToArray(), Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this });
diff --git a/src/ILCompiler.Compiler/src/Compiler/DynamicInvokeThunkGenerationPolicy.cs b/src/ILCompiler.Compiler/src/Compiler/DynamicInvokeThunkGenerationPolicy.cs
new file mode 100644
index 000000000..e4f3f67d7
--- /dev/null
+++ b/src/ILCompiler.Compiler/src/Compiler/DynamicInvokeThunkGenerationPolicy.cs
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.TypeSystem;
+
+namespace ILCompiler
+{
+ /// <summary>
+ /// Controls the way calling convention conversion is performed in
+ /// <see cref="System.Reflection.MethodBase.Invoke(object, object[])"/>
+ /// scenarios.
+ /// </summary>
+ public abstract class DynamicInvokeThunkGenerationPolicy
+ {
+ /// <summary>
+ /// Gets a value indicating whether reflection-invokable method '<paramref name="targetMethod"/>'
+ /// should get a static calling convention conversion thunk. Static calling convention
+ /// conversion thunks speed up reflection invoke of the method at the cost of extra code generation.
+ /// </summary>
+ public abstract bool HasStaticInvokeThunk(MethodDesc targetMethod);
+ }
+
+ /// <summary>
+ /// A thunk generation policy that generates no static invocation thunks.
+ /// </summary>
+ public sealed class NoDynamicInvokeThunkGenerationPolicy : DynamicInvokeThunkGenerationPolicy
+ {
+ public override bool HasStaticInvokeThunk(MethodDesc targetMethod) => false;
+ }
+
+ /// <summary>
+ /// A thunk generation policy that uses static invocation thunks whenever possible.
+ /// </summary>
+ public sealed class DefaultDynamicInvokeThunkGenerationPolicy : DynamicInvokeThunkGenerationPolicy
+ {
+ public override bool HasStaticInvokeThunk(MethodDesc targetMethod)
+ {
+ // Place an upper limit on how many parameters a method can have to still get a static stub.
+ // From the past experience, methods taking 8000+ parameters get a stub that can hit various limitations
+ // in the codegen. On Project N, we were limited to 256 parameters because of MDIL limitations.
+ // We don't have such limitations here, but it's a nice round number.
+ // Reflection invoke will still work, but will go through the calling convention converter.
+
+ return targetMethod.Signature.Length <= 256;
+ }
+ }
+}
diff --git a/src/ILCompiler.Compiler/src/Compiler/EmptyMetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/EmptyMetadataManager.cs
index 2ae053669..16d547abe 100644
--- a/src/ILCompiler.Compiler/src/Compiler/EmptyMetadataManager.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/EmptyMetadataManager.cs
@@ -17,7 +17,7 @@ namespace ILCompiler
public override bool SupportsReflection => false;
public EmptyMetadataManager(CompilerTypeSystemContext typeSystemContext)
- : base(typeSystemContext, new FullyBlockedMetadataPolicy())
+ : base(typeSystemContext, new FullyBlockedMetadataPolicy(), new FullyBlockedManifestResourcePolicy(), new NoDynamicInvokeThunkGenerationPolicy())
{
}
@@ -62,15 +62,6 @@ namespace ILCompiler
}
/// <summary>
- /// Is there a reflection invoke stub for a method that is invokable?
- /// </summary>
- public override bool HasReflectionInvokeStubForInvokableMethod(MethodDesc method)
- {
- Debug.Assert(IsReflectionInvokable(method));
- return false;
- }
-
- /// <summary>
/// Gets a stub that can be used to reflection-invoke a method with a given signature.
/// </summary>
public override MethodDesc GetCanonicalReflectionInvokeStub(MethodDesc method)
@@ -108,5 +99,13 @@ namespace ILCompiler
return true;
}
}
+
+ private sealed class FullyBlockedManifestResourcePolicy : ManifestResourceBlockingPolicy
+ {
+ public override bool IsManifestResourceBlocked(ModuleDesc module, string resourceName)
+ {
+ return true;
+ }
+ }
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/FrameworkStringResourceBlockingPolicy.cs b/src/ILCompiler.Compiler/src/Compiler/FrameworkStringResourceBlockingPolicy.cs
new file mode 100644
index 000000000..dd53aa024
--- /dev/null
+++ b/src/ILCompiler.Compiler/src/Compiler/FrameworkStringResourceBlockingPolicy.cs
@@ -0,0 +1,91 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Reflection.Metadata;
+using System.Reflection.PortableExecutable;
+
+using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
+
+namespace ILCompiler
+{
+ /// <summary>
+ /// A resource blocking policy that blocks RESX resources in framework assemblies.
+ /// This is useful for size-conscious scenarios where the conveniece of having
+ /// proper exception messages in framework-throw exceptions is not important.
+ /// </summary>
+ public sealed class FrameworkStringResourceBlockingPolicy : ManifestResourceBlockingPolicy
+ {
+ public override bool IsManifestResourceBlocked(ModuleDesc module, string resourceName)
+ {
+ // The embedded RESX files all have names that end with .resources, so use that as the initial filter.
+ if (!resourceName.EndsWith(".resources", StringComparison.OrdinalIgnoreCase))
+ return false;
+
+ // Assuming multimodule and non-ecma assemblies are unsupported
+ EcmaModule ecmaModule = (EcmaModule)module;
+
+ // If this is not a framework assembly, no resources are blocked
+ if (!IsFrameworkAssembly(ecmaModule))
+ return false;
+
+ MetadataReader reader = ecmaModule.MetadataReader;
+
+ // We have a resource in the framework assembly. Now check if this is a RESX
+ foreach (ManifestResourceHandle resourceHandle in reader.ManifestResources)
+ {
+ ManifestResource resource = reader.GetManifestResource(resourceHandle);
+ if (reader.StringComparer.Equals(resource.Name, resourceName) &&
+ resource.Implementation.IsNil)
+ {
+ PEMemoryBlock resourceDirectory =
+ ecmaModule.PEReader.GetSectionData(ecmaModule.PEReader.PEHeaders.CorHeader.ResourcesDirectory.RelativeVirtualAddress);
+ BlobReader blob = resourceDirectory.GetReader((int)resource.Offset, resourceDirectory.Length - (int)resource.Offset);
+ int length = (int)blob.ReadUInt32();
+ if (length > 4)
+ {
+ // Check for magic bytes that correspond to RESX
+ if (blob.ReadUInt32() == 0xBEEFCACE)
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether '<paramref name="module"/>' is a framework assembly.
+ /// </summary>
+ private static bool IsFrameworkAssembly(EcmaModule module)
+ {
+ MetadataReader reader = module.MetadataReader;
+
+ // We look for [assembly:AssemblyMetadata(".NETFrameworkAssembly", "")]
+
+ foreach (CustomAttributeHandle attributeHandle in reader.GetAssemblyDefinition().GetCustomAttributes())
+ {
+ if (!reader.GetAttributeNamespaceAndName(attributeHandle, out StringHandle namespaceHandle, out StringHandle nameHandle))
+ continue;
+
+ if (!reader.StringComparer.Equals(namespaceHandle, "System.Reflection") ||
+ !reader.StringComparer.Equals(nameHandle, "AssemblyMetadataAttribute"))
+ continue;
+
+ var attributeTypeProvider = new CustomAttributeTypeProvider(module);
+ CustomAttribute attribute = reader.GetCustomAttribute(attributeHandle);
+ CustomAttributeValue<TypeDesc> decodedAttribute = attribute.DecodeValue(attributeTypeProvider);
+
+ if (decodedAttribute.FixedArguments.Length != 2)
+ continue;
+
+ if (decodedAttribute.FixedArguments[0].Value is string s && s == ".NETFrameworkAssembly")
+ return true;
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/src/ILCompiler.Compiler/src/Compiler/GeneratingMetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/GeneratingMetadataManager.cs
index b01a4bb5f..044842f81 100644
--- a/src/ILCompiler.Compiler/src/Compiler/GeneratingMetadataManager.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/GeneratingMetadataManager.cs
@@ -9,14 +9,11 @@ using System.Text;
using Internal.IL.Stubs;
using Internal.TypeSystem;
-using Internal.TypeSystem.Ecma;
using Internal.Metadata.NativeFormat.Writer;
using ILCompiler.Metadata;
using ILCompiler.DependencyAnalysis;
-using Debug = System.Diagnostics.Debug;
-
namespace ILCompiler
{
/// <summary>
@@ -26,20 +23,16 @@ namespace ILCompiler
{
protected readonly string _metadataLogFile;
protected readonly StackTraceEmissionPolicy _stackTraceEmissionPolicy;
- private readonly Dictionary<DynamicInvokeMethodSignature, MethodDesc> _dynamicInvokeThunks;
private readonly ModuleDesc _generatedAssembly;
- public GeneratingMetadataManager(ModuleDesc generatedAssembly, CompilerTypeSystemContext typeSystemContext, MetadataBlockingPolicy blockingPolicy, string logFile, StackTraceEmissionPolicy stackTracePolicy)
- : base(typeSystemContext, blockingPolicy)
+ public GeneratingMetadataManager(CompilerTypeSystemContext typeSystemContext, MetadataBlockingPolicy blockingPolicy,
+ ManifestResourceBlockingPolicy resourceBlockingPolicy, string logFile, StackTraceEmissionPolicy stackTracePolicy,
+ DynamicInvokeThunkGenerationPolicy invokeThunkGenerationPolicy)
+ : base(typeSystemContext, blockingPolicy, resourceBlockingPolicy, invokeThunkGenerationPolicy)
{
_metadataLogFile = logFile;
_stackTraceEmissionPolicy = stackTracePolicy;
- _generatedAssembly = generatedAssembly;
-
- if (DynamicInvokeMethodThunk.SupportsThunks(typeSystemContext))
- {
- _dynamicInvokeThunks = new Dictionary<DynamicInvokeMethodSignature, MethodDesc>();
- }
+ _generatedAssembly = typeSystemContext.GeneratedAssembly;
}
public sealed override bool WillUseMetadataTokenToReferenceMethod(MethodDesc method)
@@ -176,40 +169,13 @@ namespace ILCompiler
protected abstract IEnumerable<FieldDesc> GetFieldsWithRuntimeMapping();
/// <summary>
- /// Is there a reflection invoke stub for a method that is invokable?
- /// </summary>
- public sealed override bool HasReflectionInvokeStubForInvokableMethod(MethodDesc method)
- {
- Debug.Assert(IsReflectionInvokable(method));
-
- if (_dynamicInvokeThunks == null)
- return false;
-
- // Place an upper limit on how many parameters a method can have to still get a static stub.
- // From the past experience, methods taking 8000+ parameters get a stub that can hit various limitations
- // in the codegen. On Project N, we were limited to 256 parameters because of MDIL limitations.
- // We don't have such limitations here, but it's a nice round number.
- // Reflection invoke will still work, but will go through the calling convention converter.
-
- return method.Signature.Length <= 256;
- }
-
- /// <summary>
/// Gets a stub that can be used to reflection-invoke a method with a given signature.
/// </summary>
public sealed override MethodDesc GetCanonicalReflectionInvokeStub(MethodDesc method)
{
- TypeSystemContext context = method.Context;
- var sig = method.Signature;
-
// Get a generic method that can be used to invoke method with this shape.
- MethodDesc thunk;
- var lookupSig = new DynamicInvokeMethodSignature(sig);
- if (!_dynamicInvokeThunks.TryGetValue(lookupSig, out thunk))
- {
- thunk = new DynamicInvokeMethodThunk(_generatedAssembly.GetGlobalModuleType(), lookupSig);
- _dynamicInvokeThunks.Add(lookupSig, thunk);
- }
+ var lookupSig = new DynamicInvokeMethodSignature(method.Signature);
+ MethodDesc thunk = _typeSystemContext.GetDynamicInvokeThunk(lookupSig);
return InstantiateCanonicalDynamicInvokeMethodForMethod(thunk, method);
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/ILScannerBuilder.cs b/src/ILCompiler.Compiler/src/Compiler/ILScannerBuilder.cs
index 340c5603a..2202f93d6 100644
--- a/src/ILCompiler.Compiler/src/Compiler/ILScannerBuilder.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/ILScannerBuilder.cs
@@ -53,7 +53,7 @@ namespace ILCompiler
public IILScanner ToILScanner()
{
- var interopStubManager = new CompilerGeneratedInteropStubManager(_compilationGroup, _context, new InteropStateManager(_compilationGroup.GeneratedAssembly));
+ var interopStubManager = new CompilerGeneratedInteropStubManager(_compilationGroup, _context, new InteropStateManager(_context.GeneratedAssembly));
var nodeFactory = new ILScanNodeFactory(_context, _compilationGroup, _metadataManager, interopStubManager, _nameMangler);
DependencyAnalyzerBase<NodeFactory> graph = _dependencyTrackingLevel.CreateDependencyGraph(nodeFactory);
diff --git a/src/ILCompiler.Compiler/src/Compiler/ILStreamReader.cs b/src/ILCompiler.Compiler/src/Compiler/ILStreamReader.cs
index 8facc05f7..badf0151a 100644
--- a/src/ILCompiler.Compiler/src/Compiler/ILStreamReader.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/ILStreamReader.cs
@@ -179,9 +179,9 @@ namespace Internal.Compiler
try
{
tokenResolved = TryReadLdtoken(out token);
- entity = tokenResolved ?(TypeSystemEntity)_methodIL.GetObject(token) : null;
+ entity = tokenResolved ? (TypeSystemEntity)_methodIL.GetObject(token) : null;
}
- catch (TypeSystemException.TypeLoadException)
+ catch (TypeSystemException)
{
tokenResolved = false;
entity = null;
diff --git a/src/ILCompiler.Compiler/src/Compiler/IRootingServiceProvider.cs b/src/ILCompiler.Compiler/src/Compiler/IRootingServiceProvider.cs
index 0895464cc..1a462e9fc 100644
--- a/src/ILCompiler.Compiler/src/Compiler/IRootingServiceProvider.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/IRootingServiceProvider.cs
@@ -18,5 +18,6 @@ namespace ILCompiler
void RootNonGCStaticBaseForType(TypeDesc type, string reason);
void RootVirtualMethodForReflection(MethodDesc method, string reason);
void RootModuleMetadata(ModuleDesc module, string reason);
+ void RootReadOnlyDataBlob(byte[] data, int alignment, string reason, string exportName);
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/LibraryInitializers.cs b/src/ILCompiler.Compiler/src/Compiler/LibraryInitializers.cs
index cf9222cb8..e970fdd76 100644
--- a/src/ILCompiler.Compiler/src/Compiler/LibraryInitializers.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/LibraryInitializers.cs
@@ -2,12 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
using System.Collections.Generic;
using Internal.TypeSystem;
-using AssemblyName = System.Reflection.AssemblyName;
using Debug = System.Diagnostics.Debug;
namespace ILCompiler
@@ -17,37 +15,22 @@ namespace ILCompiler
/// </summary>
public sealed class LibraryInitializers
{
- private const string ClassLibraryPlaceHolderString = "*ClassLibrary*";
private const string LibraryInitializerContainerNamespaceName = "Internal.Runtime.CompilerHelpers";
private const string LibraryInitializerContainerTypeName = "LibraryInitializer";
private const string LibraryInitializerMethodName = "InitializeLibrary";
- private static readonly LibraryInitializerInfo[] s_assembliesWithLibraryInitializers =
- {
- new LibraryInitializerInfo(ClassLibraryPlaceHolderString),
- new LibraryInitializerInfo("System.Private.TypeLoader"),
- new LibraryInitializerInfo("System.Private.Reflection.Execution"),
- new LibraryInitializerInfo("System.Private.DeveloperExperience.Console"),
- new LibraryInitializerInfo("System.Private.Interop"),
- new LibraryInitializerInfo("System.Private.StackTraceMetadata"),
- };
-
private List<MethodDesc> _libraryInitializerMethods;
private readonly TypeSystemContext _context;
- private readonly bool _isCppCodeGen;
+ private IReadOnlyCollection<ModuleDesc> _librariesWithInitializers;
- public LibraryInitializers(TypeSystemContext context, bool isCppCodeGen)
+ public LibraryInitializers(TypeSystemContext context, IEnumerable<ModuleDesc> librariesWithInitalizers)
{
_context = context;
- //
- // We should not care which code-gen is being used but for the time being
- // this can be useful to workaround CppCodeGen bugs.
- //
- _isCppCodeGen = isCppCodeGen;
+ _librariesWithInitializers = new List<ModuleDesc>(librariesWithInitalizers);
}
- public IList<MethodDesc> LibraryInitializerMethods
+ public IReadOnlyCollection<MethodDesc> LibraryInitializerMethods
{
get
{
@@ -64,18 +47,8 @@ namespace ILCompiler
_libraryInitializerMethods = new List<MethodDesc>();
- foreach (var entry in s_assembliesWithLibraryInitializers)
+ foreach (var assembly in _librariesWithInitializers)
{
- if (_isCppCodeGen && !entry.UseWithCppCodeGen)
- continue;
-
- ModuleDesc assembly = entry.Assembly == ClassLibraryPlaceHolderString
- ? _context.SystemModule
- : _context.ResolveAssembly(new AssemblyName(entry.Assembly), false);
-
- if (assembly == null)
- continue;
-
TypeDesc containingType = assembly.GetType(LibraryInitializerContainerNamespaceName, LibraryInitializerContainerTypeName, false);
if (containingType == null)
continue;
@@ -87,17 +60,5 @@ namespace ILCompiler
_libraryInitializerMethods.Add(initializerMethod);
}
}
-
- private sealed class LibraryInitializerInfo
- {
- public string Assembly { get; }
- public bool UseWithCppCodeGen { get; }
-
- public LibraryInitializerInfo(string assembly, bool useWithCppCodeGen = true)
- {
- Assembly = assembly;
- UseWithCppCodeGen = useWithCppCodeGen;
- }
- }
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/MainMethodRootProvider.cs b/src/ILCompiler.Compiler/src/Compiler/MainMethodRootProvider.cs
index 4df659ad8..2b716787b 100644
--- a/src/ILCompiler.Compiler/src/Compiler/MainMethodRootProvider.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/MainMethodRootProvider.cs
@@ -22,9 +22,9 @@ namespace ILCompiler
public const string ManagedEntryPointMethodName = "__managed__Main";
private EcmaModule _module;
- private IList<MethodDesc> _libraryInitializers;
+ private IReadOnlyCollection<MethodDesc> _libraryInitializers;
- public MainMethodRootProvider(EcmaModule module, IList<MethodDesc> libraryInitializers)
+ public MainMethodRootProvider(EcmaModule module, IReadOnlyCollection<MethodDesc> libraryInitializers)
{
_module = module;
_libraryInitializers = libraryInitializers;
diff --git a/src/ILCompiler.Compiler/src/Compiler/ManifestResourceBlockingPolicy.cs b/src/ILCompiler.Compiler/src/Compiler/ManifestResourceBlockingPolicy.cs
new file mode 100644
index 000000000..9f61db5bd
--- /dev/null
+++ b/src/ILCompiler.Compiler/src/Compiler/ManifestResourceBlockingPolicy.cs
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.TypeSystem;
+
+namespace ILCompiler
+{
+ /// <summary>
+ /// Represents a manifest resource blocking policy. The policy dictates whether manifest resources should
+ /// be generated into the executable.
+ /// </summary>
+ public abstract class ManifestResourceBlockingPolicy
+ {
+ /// <summary>
+ /// Returns true if manifest resource with name '<paramref name="resourceName"/>' in module '<paramref name="module"/>'
+ /// is reflection blocked.
+ /// </summary>
+ public abstract bool IsManifestResourceBlocked(ModuleDesc module, string resourceName);
+ }
+}
diff --git a/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs
index 2c2c6123b..31526a097 100644
--- a/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/MetadataManager.cs
@@ -42,6 +42,8 @@ namespace ILCompiler
protected readonly CompilerTypeSystemContext _typeSystemContext;
protected readonly MetadataBlockingPolicy _blockingPolicy;
+ protected readonly ManifestResourceBlockingPolicy _resourceBlockingPolicy;
+ protected readonly DynamicInvokeThunkGenerationPolicy _dynamicInvokeThunkGenerationPolicy;
private List<NonGCStaticsNode> _cctorContextsGenerated = new List<NonGCStaticsNode>();
private HashSet<TypeDesc> _typesWithEETypesGenerated = new HashSet<TypeDesc>();
@@ -50,16 +52,18 @@ namespace ILCompiler
private HashSet<GenericDictionaryNode> _genericDictionariesGenerated = new HashSet<GenericDictionaryNode>();
private HashSet<IMethodBodyNode> _methodBodiesGenerated = new HashSet<IMethodBodyNode>();
private List<TypeGVMEntriesNode> _typeGVMEntries = new List<TypeGVMEntriesNode>();
- private HashSet<DefaultConstructorFromLazyNode> _defaultConstructorsNeeded = new HashSet<DefaultConstructorFromLazyNode>();
internal NativeLayoutInfoNode NativeLayoutInfo { get; private set; }
internal DynamicInvokeTemplateDataNode DynamicInvokeTemplateData { get; private set; }
public virtual bool SupportsReflection => true;
- public MetadataManager(CompilerTypeSystemContext typeSystemContext, MetadataBlockingPolicy blockingPolicy)
+ public MetadataManager(CompilerTypeSystemContext typeSystemContext, MetadataBlockingPolicy blockingPolicy,
+ ManifestResourceBlockingPolicy resourceBlockingPolicy, DynamicInvokeThunkGenerationPolicy dynamicInvokeThunkGenerationPolicy)
{
_typeSystemContext = typeSystemContext;
_blockingPolicy = blockingPolicy;
+ _resourceBlockingPolicy = resourceBlockingPolicy;
+ _dynamicInvokeThunkGenerationPolicy = dynamicInvokeThunkGenerationPolicy;
}
public void AttachToDependencyGraph(DependencyAnalyzerBase<NodeFactory> graph)
@@ -205,12 +209,6 @@ namespace ILCompiler
{
_genericDictionariesGenerated.Add(dictionaryNode);
}
-
- var ctorFromLazyGenericsNode = obj as DefaultConstructorFromLazyNode;
- if (ctorFromLazyGenericsNode != null)
- {
- _defaultConstructorsNeeded.Add(ctorFromLazyGenericsNode);
- }
}
/// <summary>
@@ -218,60 +216,10 @@ namespace ILCompiler
/// </summary>
public virtual bool IsReflectionInvokable(MethodDesc method)
{
- return IsMethodSignatureSupportedInReflectionInvoke(method)
+ return Internal.IL.Stubs.DynamicInvokeMethodThunk.SupportsSignature(method.Signature)
&& IsMethodSupportedInReflectionInvoke(method);
}
- protected bool IsMethodSignatureSupportedInReflectionInvoke(MethodDesc method)
- {
- var signature = method.Signature;
-
- // ----------------------------------------------------------------
- // TODO: support for methods returning pointer types - https://github.com/dotnet/corert/issues/2113
- // ----------------------------------------------------------------
-
- if (signature.ReturnType.IsPointer)
- return false;
-
- for (int i = 0; i < signature.Length; i++)
- if (signature[i].IsByRef && ((ByRefType)signature[i]).ParameterType.IsPointer)
- return false;
-
- // ----------------------------------------------------------------
- // TODO: function pointer types are odd: https://github.com/dotnet/corert/issues/1929
- // ----------------------------------------------------------------
-
- if (signature.ReturnType.IsFunctionPointer)
- return false;
-
- for (int i = 0; i < signature.Length; i++)
- if (signature[i].IsFunctionPointer)
- return false;
-
- // ----------------------------------------------------------------
- // Methods with ByRef returns can't be reflection invoked
- // ----------------------------------------------------------------
-
- if (signature.ReturnType.IsByRef)
- return false;
-
- // ----------------------------------------------------------------
- // Methods that return ByRef-like types or take them by reference can't be reflection invoked
- // ----------------------------------------------------------------
-
- if (signature.ReturnType.IsByRefLike)
- return false;
-
- for (int i = 0; i < signature.Length; i++)
- {
- ByRefType paramType = signature[i] as ByRefType;
- if (paramType != null && paramType.ParameterType.IsByRefLike)
- return false;
- }
-
- return true;
- }
-
protected bool IsMethodSupportedInReflectionInvoke(MethodDesc method)
{
TypeDesc owningType = method.OwningType;
@@ -430,7 +378,11 @@ namespace ILCompiler
/// <summary>
/// Given that a method is invokable, does there exist a reflection invoke stub?
/// </summary>
- public abstract bool HasReflectionInvokeStubForInvokableMethod(MethodDesc method);
+ public bool HasReflectionInvokeStubForInvokableMethod(MethodDesc method)
+ {
+ Debug.Assert(IsReflectionInvokable(method));
+ return _dynamicInvokeThunkGenerationPolicy.HasStaticInvokeThunk(method);
+ }
/// <summary>
/// Given that a method is invokable, if it is inserted into the reflection invoke table
@@ -470,65 +422,7 @@ namespace ILCompiler
// Instantiate the generic thunk over the parameters and the return type of the target method
//
- ParameterMetadata[] paramMetadata = null;
- TypeDesc[] instantiation = new TypeDesc[sig.ReturnType.IsVoid ? sig.Length : sig.Length + 1];
- Debug.Assert(thunk.Instantiation.Length == instantiation.Length);
- for (int i = 0; i < sig.Length; i++)
- {
- TypeDesc parameterType = sig[i];
- if (parameterType.IsByRef)
- {
- // strip ByRefType off the parameter (the method already has ByRef in the signature)
- parameterType = ((ByRefType)parameterType).ParameterType;
-
- Debug.Assert(!parameterType.IsPointer); // TODO: support for methods returning pointer types - https://github.com/dotnet/corert/issues/2113
- }
- else if (parameterType.IsPointer || parameterType.IsFunctionPointer)
- {
- // For pointer typed parameters, instantiate the method over IntPtr
- parameterType = context.GetWellKnownType(WellKnownType.IntPtr);
- }
- else if (parameterType.IsEnum)
- {
- // If the invoke method takes an enum as an input parameter and there is no default value for
- // that paramter, we don't need to specialize on the exact enum type (we only need to specialize
- // on the underlying integral type of the enum.)
- if (paramMetadata == null)
- paramMetadata = method.GetParameterMetadata();
-
- bool hasDefaultValue = false;
- foreach (var p in paramMetadata)
- {
- // Parameter metadata indexes are 1-based (0 is reserved for return "parameter")
- if (p.Index == (i + 1) && p.HasDefault)
- {
- hasDefaultValue = true;
- break;
- }
- }
-
- if (!hasDefaultValue)
- parameterType = parameterType.UnderlyingType;
- }
-
- instantiation[i] = parameterType;
- }
-
- if (!sig.ReturnType.IsVoid)
- {
- TypeDesc returnType = sig.ReturnType;
- Debug.Assert(!returnType.IsByRef);
-
- // If the invoke method return an object reference, we don't need to specialize on the
- // exact type of the object reference, as the behavior is not different.
- if ((returnType.IsDefType && !returnType.IsValueType) || returnType.IsArray)
- {
- returnType = context.GetWellKnownType(WellKnownType.Object);
- }
-
- instantiation[sig.Length] = returnType;
- }
-
+ TypeDesc[] instantiation = Internal.IL.Stubs.DynamicInvokeMethodThunk.GetThunkInstantiationForMethod(method);
Debug.Assert(thunk.Instantiation.Length == instantiation.Length);
// Check if at least one of the instantiation arguments is a universal canonical type, and if so, we
@@ -683,11 +577,6 @@ namespace ILCompiler
return _methodBodiesGenerated;
}
- internal IEnumerable<DefaultConstructorFromLazyNode> GetDefaultConstructorsNeeded()
- {
- return _defaultConstructorsNeeded;
- }
-
internal bool TypeGeneratesEEType(TypeDesc type)
{
return _typesWithEETypesGenerated.Contains(type);
@@ -777,6 +666,11 @@ namespace ILCompiler
return _blockingPolicy.IsBlocked(typicalMethodDefinition);
}
+ public bool IsManifestResourceBlocked(ModuleDesc module, string resourceName)
+ {
+ return _resourceBlockingPolicy.IsManifestResourceBlocked(module, resourceName);
+ }
+
public bool CanGenerateMetadata(MetadataType type)
{
return (GetMetadataCategory(type) & MetadataCategory.Description) != 0;
diff --git a/src/ILCompiler.Compiler/src/Compiler/MethodExtensions.cs b/src/ILCompiler.Compiler/src/Compiler/MethodExtensions.cs
index 15070a4b4..fd274af78 100644
--- a/src/ILCompiler.Compiler/src/Compiler/MethodExtensions.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/MethodExtensions.cs
@@ -30,6 +30,26 @@ namespace ILCompiler
return null;
}
+ public static string GetRuntimeImportDllName(this EcmaMethod This)
+ {
+ var decoded = This.GetDecodedCustomAttribute("System.Runtime", "RuntimeImportAttribute");
+ if (decoded == null)
+ return null;
+
+ var decodedValue = decoded.Value;
+
+ if (decodedValue.FixedArguments.Length == 2)
+ return (string)decodedValue.FixedArguments[0].Value;
+
+ foreach (var argument in decodedValue.NamedArguments)
+ {
+ if (argument.Name == "DllName")
+ return (string)argument.Value;
+ }
+
+ return null;
+ }
+
public static string GetRuntimeExportName(this EcmaMethod This)
{
var decoded = This.GetDecodedCustomAttribute("System.Runtime", "RuntimeExportAttribute");
@@ -113,5 +133,19 @@ namespace ILCompiler
return false;
}
+
+ /// <summary>
+ /// Determine whether a method can go into the sealed vtable of a type. Such method must be a sealed virtual
+ /// method that is not overriding any method on a base type.
+ /// Given that such methods can never be overridden in any derived type, we can
+ /// save space in the vtable of a type, and all of its derived types by not emitting these methods in their vtables,
+ /// and storing them in a separate table on the side. This is especially beneficial for all array types,
+ /// since all of their collection interface methods are sealed and implemented on the System.Array and
+ /// System.Array&lt;T&gt; base types, and therefore we can minimize the vtable sizes of all derived array types.
+ /// </summary>
+ public static bool CanMethodBeInSealedVTable(this MethodDesc method)
+ {
+ return method.IsFinal && method.IsNewSlot;
+ }
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/MultiFileCompilationModuleGroup.cs b/src/ILCompiler.Compiler/src/Compiler/MultiFileCompilationModuleGroup.cs
index 9541e4285..842ddefad 100644
--- a/src/ILCompiler.Compiler/src/Compiler/MultiFileCompilationModuleGroup.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/MultiFileCompilationModuleGroup.cs
@@ -17,12 +17,11 @@ namespace ILCompiler
private HashSet<ModuleDesc> _compilationModuleSet;
public MultiFileCompilationModuleGroup(TypeSystemContext context, IEnumerable<ModuleDesc> compilationModuleSet)
- : base(context)
{
_compilationModuleSet = new HashSet<ModuleDesc>(compilationModuleSet);
// The fake assembly that holds compiler generated types is part of the compilation.
- _compilationModuleSet.Add(this.GeneratedAssembly);
+ _compilationModuleSet.Add(context.GeneratedAssembly);
}
public sealed override bool ContainsType(TypeDesc type)
@@ -59,6 +58,11 @@ namespace ILCompiler
return ContainsMethodBody(method, false);
}
+ public sealed override bool ImportsMethod(MethodDesc method, bool unboxingStub)
+ {
+ return false;
+ }
+
public sealed override ExportForm GetExportTypeForm(TypeDesc type)
{
return ExportForm.None;
diff --git a/src/ILCompiler.Compiler/src/Compiler/NativeLibraryInitializerRootProvider.cs b/src/ILCompiler.Compiler/src/Compiler/NativeLibraryInitializerRootProvider.cs
index d7460d45a..4079a902b 100644
--- a/src/ILCompiler.Compiler/src/Compiler/NativeLibraryInitializerRootProvider.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/NativeLibraryInitializerRootProvider.cs
@@ -20,10 +20,10 @@ namespace ILCompiler
/// </summary>
public const string ManagedEntryPointMethodName = "__managed__Startup";
- private EcmaModule _module;
- private IList<MethodDesc> _libraryInitializers;
+ private ModuleDesc _module;
+ private IReadOnlyCollection<MethodDesc> _libraryInitializers;
- public NativeLibraryInitializerRootProvider(EcmaModule module, IList<MethodDesc> libraryInitializers)
+ public NativeLibraryInitializerRootProvider(ModuleDesc module, IReadOnlyCollection<MethodDesc> libraryInitializers)
{
_module = module;
_libraryInitializers = libraryInitializers;
diff --git a/src/ILCompiler.Compiler/src/Compiler/NoManifestResourceBlockingPolicy.cs b/src/ILCompiler.Compiler/src/Compiler/NoManifestResourceBlockingPolicy.cs
new file mode 100644
index 000000000..fd58d0e5b
--- /dev/null
+++ b/src/ILCompiler.Compiler/src/Compiler/NoManifestResourceBlockingPolicy.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.TypeSystem;
+
+namespace ILCompiler
+{
+ /// <summary>
+ /// A blocking policy that doesn't block any manifest resources.
+ /// </summary>
+ public sealed class NoManifestResourceBlockingPolicy : ManifestResourceBlockingPolicy
+ {
+ public override bool IsManifestResourceBlocked(ModuleDesc module, string resourceName)
+ {
+ return false;
+ }
+ }
+}
diff --git a/src/ILCompiler.Compiler/src/Compiler/NoMetadataBlockingPolicy.cs b/src/ILCompiler.Compiler/src/Compiler/NoMetadataBlockingPolicy.cs
new file mode 100644
index 000000000..af0c073b9
--- /dev/null
+++ b/src/ILCompiler.Compiler/src/Compiler/NoMetadataBlockingPolicy.cs
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
+
+namespace ILCompiler
+{
+ /// <summary>
+ /// Represents a metadata blocking policy that doesn't block any metadata.
+ /// </summary>
+ public sealed class NoMetadataBlockingPolicy : MetadataBlockingPolicy
+ {
+ public override bool IsBlocked(MetadataType type) => !(type is EcmaType);
+
+ public override bool IsBlocked(FieldDesc field) => !(field is EcmaField);
+
+ private MetadataType _arrayOfTType;
+ private MetadataType InitializeArrayOfTType(TypeSystemEntity contextEntity)
+ {
+ _arrayOfTType = contextEntity.Context.SystemModule.GetType("System", "Array`1");
+ return _arrayOfTType;
+ }
+ private MetadataType GetArrayOfTType(TypeSystemEntity contextEntity)
+ {
+ if (_arrayOfTType != null)
+ {
+ return _arrayOfTType;
+ }
+ return InitializeArrayOfTType(contextEntity);
+ }
+
+ public override bool IsBlocked(MethodDesc method)
+ {
+ if (method is EcmaMethod ecmaMethod)
+ {
+ // Methods on Array`1<T> are implementation details that implement the generic interfaces on
+ // arrays. They should not generate metadata or be reflection invokable.
+ // We can get rid of this special casing if we make these methods stop being regular EcmaMethods
+ // with Array<T> as their owning type
+ if (ecmaMethod.OwningType == GetArrayOfTType(ecmaMethod))
+ return true;
+
+ return false;
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/ILCompiler.Compiler/src/Compiler/PrecomputedMetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/PrecomputedMetadataManager.cs
index 0e333d323..a005fa379 100644
--- a/src/ILCompiler.Compiler/src/Compiler/PrecomputedMetadataManager.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/PrecomputedMetadataManager.cs
@@ -33,6 +33,7 @@ namespace ILCompiler
public ImmutableArray<ModuleDesc> LocalMetadataModules = ImmutableArray<ModuleDesc>.Empty;
public ImmutableArray<ModuleDesc> ExternalMetadataModules = ImmutableArray<ModuleDesc>.Empty;
public List<MetadataType> TypesWithStrongMetadataMappings = new List<MetadataType>();
+ public Dictionary<MetadataType, int> WeakReflectedTypeMappings = new Dictionary<MetadataType, int>();
public Dictionary<MetadataType, int> AllTypeMappings = new Dictionary<MetadataType, int>();
public Dictionary<MethodDesc, int> MethodMappings = new Dictionary<MethodDesc, int>();
public Dictionary<FieldDesc, int> FieldMappings = new Dictionary<FieldDesc, int>();
@@ -62,9 +63,15 @@ namespace ILCompiler
IEnumerable<ModuleDesc> compilationModules,
IEnumerable<ModuleDesc> inputMetadataOnlyAssemblies,
byte[] metadataBlob,
- StackTraceEmissionPolicy stackTraceEmissionPolicy)
- : base(typeSystemContext, new AttributeSpecifiedBlockingPolicy())
+ StackTraceEmissionPolicy stackTraceEmissionPolicy,
+ ManifestResourceBlockingPolicy resourceBlockingPolicy,
+ bool disableInvokeThunks)
+ : base(typeSystemContext, new AttributeSpecifiedBlockingPolicy(), resourceBlockingPolicy,
+ disableInvokeThunks ? (DynamicInvokeThunkGenerationPolicy)new NoDynamicInvokeThunkGenerationPolicy() : new PrecomputedDynamicInvokeThunkGenerationPolicy())
{
+ // Need to do this dance because C# won't let us access `this` in the `base()` expression above. Sigh.
+ (_dynamicInvokeThunkGenerationPolicy as PrecomputedDynamicInvokeThunkGenerationPolicy)?.SetParentWorkaround(this);
+
_compilationModuleGroup = group;
_metadataDescribingModule = metadataDescribingModule;
_compilationModules = new HashSet<ModuleDesc>(compilationModules);
@@ -400,7 +407,7 @@ namespace ILCompiler
MethodIL weakMethodIL = ilProvider.GetMethodIL(weakMetadataMethod);
Dictionary<MethodDesc, int> weakMethodMappings = new Dictionary<MethodDesc, int>();
Dictionary<FieldDesc, int> weakFieldMappings = new Dictionary<FieldDesc, int>();
- ReadMetadataMethod(weakMethodIL, result.AllTypeMappings, weakMethodMappings, weakFieldMappings, metadataModules);
+ ReadMetadataMethod(weakMethodIL, result.WeakReflectedTypeMappings, weakMethodMappings, weakFieldMappings, metadataModules);
if ((weakMethodMappings.Count > 0) || (weakFieldMappings.Count > 0))
{
// the format does not permit weak field/method mappings
@@ -538,7 +545,7 @@ namespace ILCompiler
}
}
- if (metadataType.ThreadStaticFieldSize.AsInt > 0)
+ if (metadataType.ThreadGcStaticFieldSize.AsInt > 0)
{
dependencies.Add(((UtcNodeFactory)factory).TypeThreadStaticsOffsetSymbol(metadataType), "Thread statics for ReflectionFieldMap entry");
}
@@ -706,7 +713,7 @@ namespace ILCompiler
continue;
int token;
- if (loadedMetadata.AllTypeMappings.TryGetValue(definition, out token))
+ if (loadedMetadata.AllTypeMappings.TryGetValue(definition, out token) || loadedMetadata.WeakReflectedTypeMappings.TryGetValue(definition, out token))
{
typeMappings.Add(new MetadataMapping<MetadataType>(definition, token));
}
@@ -739,6 +746,14 @@ namespace ILCompiler
AddFieldMapping(field, canonicalFieldsAddedToMap, fieldMappings);
}
+ foreach (var typeMapping in loadedMetadata.WeakReflectedTypeMappings)
+ {
+ // Imported types that are also declared as weak reflected types need to be added to the TypeMap table, but only if they are also
+ // reachable from static compilation (node marked in the dependency analysis graph)
+ if (factory.CompilationModuleGroup.ShouldReferenceThroughImportTable(typeMapping.Key) && factory.NecessaryTypeSymbol(typeMapping.Key).Marked)
+ typeMappings.Add(new MetadataMapping<MetadataType>(typeMapping.Key, typeMapping.Value));
+ }
+
stackTraceMapping = GenerateStackTraceMetadata(factory);
}
@@ -894,38 +909,6 @@ namespace ILCompiler
}
/// <summary>
- /// Is there a reflection invoke stub for a method that is invokable?
- /// </summary>
- public override bool HasReflectionInvokeStubForInvokableMethod(MethodDesc method)
- {
- Debug.Assert(IsReflectionInvokable(method));
-
- if (!ProjectNDependencyBehavior.EnableFullAnalysis)
- {
- if (method.IsCanonicalMethod(CanonicalFormKind.Any))
- return false;
- }
- else
- {
- if (method.IsCanonicalMethod(CanonicalFormKind.Universal))
- return false;
- }
-
- MethodDesc reflectionInvokeStub = GetCanonicalReflectionInvokeStub(method);
-
- if (reflectionInvokeStub == null)
- return false;
-
- // TODO: Generate DynamicInvokeTemplateMap dependencies correctly. For now, force all canonical stubs to go through the
- // calling convention converter interpreter path.
- if (reflectionInvokeStub.IsSharedByGenericInstantiations)
- return false;
-
- return true;
- }
-
-
- /// <summary>
/// Gets a stub that can be used to reflection-invoke a method with a given signature.
/// </summary>
public override MethodDesc GetCanonicalReflectionInvokeStub(MethodDesc method)
@@ -1040,5 +1023,45 @@ namespace ILCompiler
public bool IsBlocked(MethodDesc methodDef) => false;
public ModuleDesc GetModuleOfType(MetadataType typeDef) => typeDef.Module;
}
+
+ private sealed class PrecomputedDynamicInvokeThunkGenerationPolicy : DynamicInvokeThunkGenerationPolicy
+ {
+ private PrecomputedMetadataManager _parent;
+
+ public PrecomputedDynamicInvokeThunkGenerationPolicy()
+ {
+ }
+
+ public void SetParentWorkaround(PrecomputedMetadataManager parent)
+ {
+ _parent = parent;
+ }
+
+ public override bool HasStaticInvokeThunk(MethodDesc method)
+ {
+ if (!ProjectNDependencyBehavior.EnableFullAnalysis)
+ {
+ if (method.IsCanonicalMethod(CanonicalFormKind.Any))
+ return false;
+ }
+ else
+ {
+ if (method.IsCanonicalMethod(CanonicalFormKind.Universal))
+ return false;
+ }
+
+ MethodDesc reflectionInvokeStub = _parent.GetCanonicalReflectionInvokeStub(method);
+
+ if (reflectionInvokeStub == null)
+ return false;
+
+ // TODO: Generate DynamicInvokeTemplateMap dependencies correctly. For now, force all canonical stubs to go through the
+ // calling convention converter interpreter path.
+ if (reflectionInvokeStub.IsSharedByGenericInstantiations)
+ return false;
+
+ return true;
+ }
+ }
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/RuntimeConfigurationRootProvider.cs b/src/ILCompiler.Compiler/src/Compiler/RuntimeConfigurationRootProvider.cs
new file mode 100644
index 000000000..e4be79fc1
--- /dev/null
+++ b/src/ILCompiler.Compiler/src/Compiler/RuntimeConfigurationRootProvider.cs
@@ -0,0 +1,58 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+
+namespace ILCompiler
+{
+ /// <summary>
+ /// A root provider that provides a runtime configuration blob that influences runtime behaviors.
+ /// See RhConfigValues.h for allowed values.
+ /// </summary>
+ public class RuntimeConfigurationRootProvider : ICompilationRootProvider
+ {
+ private readonly IEnumerable<string> _runtimeOptions;
+
+ public RuntimeConfigurationRootProvider(IEnumerable<string> runtimeOptions)
+ {
+ _runtimeOptions = runtimeOptions;
+ }
+
+ void ICompilationRootProvider.AddCompilationRoots(IRootingServiceProvider rootProvider)
+ {
+ rootProvider.RootReadOnlyDataBlob(GetRuntimeOptionsBlob(), 4, "Runtime configuration information", "g_compilerEmbeddedSettingsBlob");
+ }
+
+ protected byte[] GetRuntimeOptionsBlob()
+ {
+ const int HeaderSize = 4;
+
+ ArrayBuilder<byte> options = new ArrayBuilder<byte>();
+
+ // Reserve space for the header
+ options.ZeroExtend(HeaderSize);
+
+ foreach (string option in _runtimeOptions)
+ {
+ byte[] optionBytes = System.Text.Encoding.ASCII.GetBytes(option);
+ options.Append(optionBytes);
+
+ // Emit a null to separate the next option
+ options.Add(0);
+ }
+
+ byte[] result = options.ToArray();
+
+ int length = options.Count - HeaderSize;
+
+ // Encode the size of the blob into the header
+ result[0] = (byte)length;
+ result[1] = (byte)(length >> 8);
+ result[2] = (byte)(length >> 0x10);
+ result[3] = (byte)(length >> 0x18);
+
+ return result;
+ }
+ }
+}
diff --git a/src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs b/src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs
index 773560798..f02559b4e 100644
--- a/src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs
@@ -86,7 +86,7 @@ namespace ILCompiler
jitFlagBuilder.Add(CorJitFlag.CORJIT_FLAG_FEATURE_SIMD);
}
- var interopStubManager = new CompilerGeneratedInteropStubManager(_compilationGroup, _context, new InteropStateManager(_compilationGroup.GeneratedAssembly));
+ var interopStubManager = new CompilerGeneratedInteropStubManager(_compilationGroup, _context, new InteropStateManager(_context.GeneratedAssembly));
var factory = new RyuJitNodeFactory(_context, _compilationGroup, _metadataManager, interopStubManager, _nameMangler, _vtableSliceProvider, _dictionaryLayoutProvider);
var jitConfig = new JitConfigProvider(jitFlagBuilder.ToArray(), _ryujitOptions);
diff --git a/src/ILCompiler.Compiler/src/Compiler/SimdHelper.cs b/src/ILCompiler.Compiler/src/Compiler/SimdHelper.cs
index 3f523b18d..53f606c57 100644
--- a/src/ILCompiler.Compiler/src/Compiler/SimdHelper.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/SimdHelper.cs
@@ -17,19 +17,27 @@ namespace ILCompiler
{
private ModuleDesc[] _simdModulesCached;
- public bool IsInSimdModule(TypeDesc type)
+ public bool IsSimdType(TypeDesc type)
{
- if (type is MetadataType)
+ if (type is MetadataType metadataType)
{
if (_simdModulesCached == null)
{
InitializeSimdModules(type);
}
- ModuleDesc typeModule = ((MetadataType)type).Module;
+ ModuleDesc typeModule = metadataType.Module;
foreach (ModuleDesc simdModule in _simdModulesCached)
if (typeModule == simdModule)
return true;
+
+ if (metadataType.IsIntrinsic)
+ {
+ string name = metadataType.Name;
+ if ((name == "Vector`1" || name == "Vector") &&
+ metadataType.Namespace == "System.Numerics")
+ return true;
+ }
}
return false;
@@ -54,7 +62,7 @@ namespace ILCompiler
public bool IsVectorOfT(TypeDesc type)
{
- return IsInSimdModule(type)
+ return IsSimdType(type)
&& ((MetadataType)type).Name == "Vector`1"
&& ((MetadataType)type).Namespace == "System.Numerics";
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/SingleFileCompilationModuleGroup.cs b/src/ILCompiler.Compiler/src/Compiler/SingleFileCompilationModuleGroup.cs
index ba4c23d79..90a0043be 100644
--- a/src/ILCompiler.Compiler/src/Compiler/SingleFileCompilationModuleGroup.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/SingleFileCompilationModuleGroup.cs
@@ -10,11 +10,6 @@ namespace ILCompiler
{
public class SingleFileCompilationModuleGroup : CompilationModuleGroup
{
- public SingleFileCompilationModuleGroup(TypeSystemContext context)
- : base(context)
- {
- }
-
public override bool ContainsType(TypeDesc type)
{
return true;
@@ -36,6 +31,11 @@ namespace ILCompiler
return ContainsMethodBody(method, false);
}
+ public override bool ImportsMethod(MethodDesc method, bool unboxingStub)
+ {
+ return false;
+ }
+
public override ExportForm GetExportTypeForm(TypeDesc type)
{
return ExportForm.None;
diff --git a/src/ILCompiler.Compiler/src/Compiler/SingleMethodCompilationModuleGroup.cs b/src/ILCompiler.Compiler/src/Compiler/SingleMethodCompilationModuleGroup.cs
index 61f220e09..9a1435217 100644
--- a/src/ILCompiler.Compiler/src/Compiler/SingleMethodCompilationModuleGroup.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/SingleMethodCompilationModuleGroup.cs
@@ -17,7 +17,6 @@ namespace ILCompiler
private MethodDesc _method;
public SingleMethodCompilationModuleGroup(MethodDesc method)
- : base(method.Context)
{
_method = method;
}
@@ -51,6 +50,11 @@ namespace ILCompiler
return false;
}
+ public override bool ImportsMethod(MethodDesc method, bool unboxingStub)
+ {
+ return false;
+ }
+
public override ExportForm GetExportTypeForm(TypeDesc type)
{
return ExportForm.None;
diff --git a/src/ILCompiler.Compiler/src/Compiler/TypeExtensions.cs b/src/ILCompiler.Compiler/src/Compiler/TypeExtensions.cs
index 5cf56d172..99b0de66c 100644
--- a/src/ILCompiler.Compiler/src/Compiler/TypeExtensions.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/TypeExtensions.cs
@@ -31,14 +31,11 @@ namespace ILCompiler
{
if (type.IsArray)
{
- var arrayType = (ArrayType)type;
- TypeDesc elementType = arrayType.ElementType;
- if (arrayType.IsSzArray && !elementType.IsPointer && !elementType.IsFunctionPointer)
- {
- MetadataType arrayShadowType = type.Context.SystemModule.GetKnownType("System", "Array`1");
- return arrayShadowType.MakeInstantiatedType(elementType);
- }
- return type.Context.GetWellKnownType(WellKnownType.Array);
+ if (type.IsArrayTypeWithoutGenericInterfaces())
+ return type.Context.GetWellKnownType(WellKnownType.Array);
+
+ MetadataType arrayShadowType = type.Context.SystemModule.GetKnownType("System", "Array`1");
+ return arrayShadowType.MakeInstantiatedType(((ArrayType)type).ElementType);
}
Debug.Assert(type is DefType);
@@ -183,5 +180,19 @@ namespace ILCompiler
return false;
}
+
+ /// <summary>
+ /// Determines whether an array type does implements the generic collection interfaces. This is the case
+ /// for multi-dimensional arrays, and arrays of pointers.
+ /// </summary>
+ public static bool IsArrayTypeWithoutGenericInterfaces(this TypeDesc type)
+ {
+ if (!type.IsArray)
+ return false;
+
+ var arrayType = (ArrayType)type;
+ TypeDesc elementType = arrayType.ElementType;
+ return type.IsMdArray || elementType.IsPointer || elementType.IsFunctionPointer;
+ }
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/UsageBasedMetadataManager.cs b/src/ILCompiler.Compiler/src/Compiler/UsageBasedMetadataManager.cs
index b5845786c..312a1a192 100644
--- a/src/ILCompiler.Compiler/src/Compiler/UsageBasedMetadataManager.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/UsageBasedMetadataManager.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System;
using System.Collections.Generic;
using Internal.TypeSystem;
@@ -23,6 +24,7 @@ namespace ILCompiler
{
private readonly CompilationModuleGroup _compilationModuleGroup;
+ internal readonly UsageBasedMetadataGenerationOptions _generationOptions;
private readonly bool _hasPreciseFieldUsageInformation;
private readonly List<ModuleDesc> _modulesWithMetadata = new List<ModuleDesc>();
@@ -34,13 +36,17 @@ namespace ILCompiler
CompilationModuleGroup group,
CompilerTypeSystemContext typeSystemContext,
MetadataBlockingPolicy blockingPolicy,
+ ManifestResourceBlockingPolicy resourceBlockingPolicy,
string logFile,
- StackTraceEmissionPolicy stackTracePolicy)
- : base(group.GeneratedAssembly, typeSystemContext, blockingPolicy, logFile, stackTracePolicy)
+ StackTraceEmissionPolicy stackTracePolicy,
+ DynamicInvokeThunkGenerationPolicy invokeThunkGenerationPolicy,
+ UsageBasedMetadataGenerationOptions generationOptions)
+ : base(typeSystemContext, blockingPolicy, resourceBlockingPolicy, logFile, stackTracePolicy, invokeThunkGenerationPolicy)
{
// We use this to mark places that would behave differently if we tracked exact fields used.
_hasPreciseFieldUsageInformation = false;
_compilationModuleGroup = group;
+ _generationOptions = generationOptions;
}
protected override void Graph_NewMarkedNode(DependencyNodeCore<NodeFactory> obj)
@@ -353,8 +359,8 @@ namespace ILCompiler
}
}
- return new AnalysisBasedMetadataManager(_compilationModuleGroup.GeneratedAssembly,
- _typeSystemContext, _blockingPolicy, _metadataLogFile, _stackTraceEmissionPolicy,
+ return new AnalysisBasedMetadataManager(
+ _typeSystemContext, _blockingPolicy, _resourceBlockingPolicy, _metadataLogFile, _stackTraceEmissionPolicy, _dynamicInvokeThunkGenerationPolicy,
_modulesWithMetadata, reflectableTypes.ToEnumerable(), reflectableMethods.ToEnumerable(),
reflectableFields.ToEnumerable());
}
@@ -438,4 +444,21 @@ namespace ILCompiler
}
}
}
+
+ [Flags]
+ public enum UsageBasedMetadataGenerationOptions
+ {
+ None = 0,
+
+ /// <summary>
+ /// Specifies that complete metadata should be generated for types.
+ /// </summary>
+ /// <remarks>
+ /// If this option is set, generated metadata will no longer be pay for play,
+ /// and a certain class of bugs will disappear (APIs returning "member doesn't
+ /// exist" at runtime, even though the member exists and we just didn't generate the metadata).
+ /// Reflection blocking still applies.
+ /// </remarks>
+ CompleteTypesOnly = 1,
+ }
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/UserDefinedTypeDescriptor.cs b/src/ILCompiler.Compiler/src/Compiler/UserDefinedTypeDescriptor.cs
index c91a1f08e..7427c4981 100644
--- a/src/ILCompiler.Compiler/src/Compiler/UserDefinedTypeDescriptor.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/UserDefinedTypeDescriptor.cs
@@ -81,7 +81,9 @@ namespace ILCompiler
descriptor.ReturnType = GetVariableTypeIndex(DebuggerCanonicalize(signature.ReturnType));
descriptor.ThisAdjust = 0;
descriptor.CallingConvention = 0x4; // Near fastcall
- descriptor.TypeIndexOfThisPointer = signature.IsStatic ? (uint)PrimitiveTypeDescriptor.TYPE_ENUM.T_VOID : GetThisTypeIndex(method.OwningType);
+ descriptor.TypeIndexOfThisPointer = signature.IsStatic ?
+ GetPrimitiveTypeIndex(method.OwningType.Context.GetWellKnownType(WellKnownType.Void)) :
+ GetThisTypeIndex(method.OwningType);
descriptor.ContainingClass = GetTypeIndex(method.OwningType, true);
try
@@ -139,7 +141,7 @@ namespace ILCompiler
uint variableTypeIndex = 0;
if (type.IsPrimitive)
{
- variableTypeIndex = PrimitiveTypeDescriptor.GetPrimitiveTypeIndex(type);
+ variableTypeIndex = GetPrimitiveTypeIndex(type);
}
else
{
@@ -180,6 +182,10 @@ namespace ILCompiler
variableTypeIndex = GetEnumTypeIndex(type);
GetTypeIndex(type, false); // Ensure regular structure record created
+
+ _enumTypes[type] = variableTypeIndex;
+
+ return variableTypeIndex;
}
variableTypeIndex = GetTypeIndex(type, needsCompleteIndex);
@@ -290,7 +296,7 @@ namespace ILCompiler
EnumTypeDescriptor enumTypeDescriptor = new EnumTypeDescriptor
{
ElementCount = (ulong)fieldsDescriptors.Count,
- ElementType = PrimitiveTypeDescriptor.GetPrimitiveTypeIndex(defType.UnderlyingType),
+ ElementType = GetPrimitiveTypeIndex(defType.UnderlyingType),
Name = _objectWriter.GetMangledName(type),
};
EnumRecordTypeDescriptor[] typeRecords = new EnumRecordTypeDescriptor[enumTypeDescriptor.ElementCount];
@@ -381,33 +387,69 @@ namespace ILCompiler
return 0;
}
- TypeDesc GetFieldDebugType(FieldDesc field)
+ bool ShouldUseCanonicalTypeRecord(TypeDesc type)
{
- TypeDesc type = field.FieldType;
-
// TODO: check the type's generic complexity
- if (NodeFactory.LazyGenericsPolicy.UsesLazyGenerics(type))
+ return type.GetGenericDepth() > NodeFactory.TypeSystemContext.GenericsConfig.MaxGenericDepthOfDebugRecord;
+ }
+
+ TypeDesc GetDebugType(TypeDesc type)
+ {
+ TypeDesc typeGenericComplexityInfo = type;
+
+ // Strip off pointer, array, and byref details.
+ while (typeGenericComplexityInfo is ParameterizedType paramType) {
+ typeGenericComplexityInfo = paramType.ParameterType;
+ }
+
+ // Types that have some canonical subtypes types should always be represented in normalized canonical form to the binder.
+ // Also, to avoid infinite generic recursion issues, attempt to use canonical form for fields with high generic complexity.
+ if (type.IsCanonicalSubtype(CanonicalFormKind.Specific) || (typeGenericComplexityInfo is DefType defType) && ShouldUseCanonicalTypeRecord(defType))
{
type = type.ConvertToCanonForm(CanonicalFormKind.Specific);
+
+ // Re-check if the canonical subtype has acceptable generic complexity
+ typeGenericComplexityInfo = type;
+
+ while (typeGenericComplexityInfo is ParameterizedType paramType) {
+ typeGenericComplexityInfo = paramType.ParameterType;
+ }
+
+ if ((typeGenericComplexityInfo is DefType canonDefType) && ShouldUseCanonicalTypeRecord(canonDefType))
+ {
+ type = type.ConvertToCanonForm(CanonicalFormKind.Universal);
+ }
}
return type;
}
+ TypeDesc GetFieldDebugType(FieldDesc field)
+ {
+ return GetDebugType(field.FieldType);
+ }
+
private uint GetClassTypeIndex(TypeDesc type, bool needsCompleteType)
{
- DefType defType = type as DefType;
+ TypeDesc debugType = GetDebugType(type);
+ DefType defType = debugType as DefType;
System.Diagnostics.Debug.Assert(defType != null, "GetClassTypeIndex was called with non def type");
ClassTypeDescriptor classTypeDescriptor = new ClassTypeDescriptor
{
IsStruct = type.IsValueType ? 1 : 0,
- Name = _objectWriter.GetMangledName(type),
- BaseClassId = 0
+ Name = _objectWriter.GetMangledName(defType),
+ BaseClassId = 0,
+ InstanceSize = 0
};
uint typeIndex = _objectWriter.GetClassTypeIndex(classTypeDescriptor);
_knownTypes[type] = typeIndex;
+ if (!defType.InstanceByteCount.IsIndeterminate)
+ {
+ classTypeDescriptor.InstanceSize = (ulong)defType.InstanceByteCount.AsInt;
+ }
+
if (type.HasBaseType && !type.IsValueType)
{
classTypeDescriptor.BaseClassId = GetTypeIndex(defType.BaseType, true);
@@ -417,6 +459,12 @@ namespace ILCompiler
List<DataFieldDescriptor> nonGcStaticFields = new List<DataFieldDescriptor>();
List<DataFieldDescriptor> gcStaticFields = new List<DataFieldDescriptor>();
List<DataFieldDescriptor> threadStaticFields = new List<DataFieldDescriptor>();
+ List<StaticDataFieldDescriptor> staticsDescs = new List<StaticDataFieldDescriptor>();
+
+ string nonGcStaticDataName = NodeFactory.NameMangler.NodeMangler.NonGCStatics(type);
+ string gcStaticDataName = NodeFactory.NameMangler.NodeMangler.GCStatics(type);
+ string threadStaticDataName = NodeFactory.NameMangler.NodeMangler.ThreadStatics(type);
+ bool IsCoreRTAbi = Abi == TargetAbi.CoreRT;
bool isCanonical = defType.IsCanonicalSubtype(CanonicalFormKind.Any);
@@ -439,6 +487,30 @@ namespace ILCompiler
if (fieldDesc.IsStatic)
{
+ if (NodeFactory.Target.OperatingSystem != TargetOS.Windows)
+ {
+ StaticDataFieldDescriptor staticDesc = new StaticDataFieldDescriptor
+ {
+ StaticOffset = (ulong)fieldOffsetEmit
+ };
+
+ // Mark field as static
+ field.Offset = 0xFFFFFFFF;
+
+ if (fieldDesc.IsThreadStatic) {
+ staticDesc.StaticDataName = threadStaticDataName;
+ staticDesc.IsStaticDataInObject = IsCoreRTAbi ? 1 : 0;
+ } else if (fieldDesc.HasGCStaticBase) {
+ staticDesc.StaticDataName = gcStaticDataName;
+ staticDesc.IsStaticDataInObject = IsCoreRTAbi ? 1 : 0;
+ } else {
+ staticDesc.StaticDataName = nonGcStaticDataName;
+ staticDesc.IsStaticDataInObject = 0;
+ }
+
+ staticsDescs.Add(staticDesc);
+ }
+
if (fieldDesc.IsThreadStatic)
threadStaticFields.Add(field);
else if (fieldDesc.HasGCStaticBase)
@@ -452,9 +524,18 @@ namespace ILCompiler
}
}
- InsertStaticFieldRegionMember(fieldsDescs, defType, nonGcStaticFields, WindowsNodeMangler.NonGCStaticMemberName, "__type_" + WindowsNodeMangler.NonGCStaticMemberName, false);
- InsertStaticFieldRegionMember(fieldsDescs, defType, gcStaticFields, WindowsNodeMangler.GCStaticMemberName, "__type_" + WindowsNodeMangler.GCStaticMemberName, Abi == TargetAbi.CoreRT);
- InsertStaticFieldRegionMember(fieldsDescs, defType, threadStaticFields, WindowsNodeMangler.ThreadStaticMemberName, "__type_" + WindowsNodeMangler.ThreadStaticMemberName, Abi == TargetAbi.CoreRT);
+ if (NodeFactory.Target.OperatingSystem == TargetOS.Windows)
+ {
+ InsertStaticFieldRegionMember(fieldsDescs, defType, nonGcStaticFields, WindowsNodeMangler.NonGCStaticMemberName, "__type_" + WindowsNodeMangler.NonGCStaticMemberName, false);
+ InsertStaticFieldRegionMember(fieldsDescs, defType, gcStaticFields, WindowsNodeMangler.GCStaticMemberName, "__type_" + WindowsNodeMangler.GCStaticMemberName, IsCoreRTAbi);
+ InsertStaticFieldRegionMember(fieldsDescs, defType, threadStaticFields, WindowsNodeMangler.ThreadStaticMemberName, "__type_" + WindowsNodeMangler.ThreadStaticMemberName, IsCoreRTAbi);
+ }
+ else
+ {
+ fieldsDescs.AddRange(nonGcStaticFields);
+ fieldsDescs.AddRange(gcStaticFields);
+ fieldsDescs.AddRange(threadStaticFields);
+ }
DataFieldDescriptor[] fields = new DataFieldDescriptor[fieldsDescs.Count];
for (int i = 0; i < fieldsDescs.Count; ++i)
@@ -462,15 +543,21 @@ namespace ILCompiler
fields[i] = fieldsDescs[i];
}
+ StaticDataFieldDescriptor[] statics = new StaticDataFieldDescriptor[staticsDescs.Count];
+ for (int i = 0; i < staticsDescs.Count; ++i)
+ {
+ statics[i] = staticsDescs[i];
+ }
+
LayoutInt elementSize = defType.GetElementSize();
int elementSizeEmit = elementSize.IsIndeterminate ? 0xBAAD : elementSize.AsInt;
ClassFieldsTypeDescriptor fieldsDescriptor = new ClassFieldsTypeDescriptor
{
Size = (ulong)elementSizeEmit,
- FieldsCount = fieldsDescs.Count
+ FieldsCount = fieldsDescs.Count,
};
- uint completeTypeIndex = _objectWriter.GetCompleteClassTypeIndex(classTypeDescriptor, fieldsDescriptor, fields);
+ uint completeTypeIndex = _objectWriter.GetCompleteClassTypeIndex(classTypeDescriptor, fieldsDescriptor, fields, statics);
_completeKnownTypes[type] = completeTypeIndex;
if (needsCompleteType)
@@ -502,7 +589,7 @@ namespace ILCompiler
classTypeDescriptor.BaseClassId = GetTypeIndex(defType.Context.GetWellKnownType(WellKnownType.Object), true);
}
- uint staticFieldRegionTypeIndex = _objectWriter.GetCompleteClassTypeIndex(classTypeDescriptor, fieldsDescriptor, staticFields.ToArray());
+ uint staticFieldRegionTypeIndex = _objectWriter.GetCompleteClassTypeIndex(classTypeDescriptor, fieldsDescriptor, staticFields.ToArray(), null);
uint staticFieldRegionSymbolTypeIndex = staticFieldRegionTypeIndex;
// This means that access to this static region is done via a double indirection
@@ -530,6 +617,21 @@ namespace ILCompiler
}
}
+ private uint GetPrimitiveTypeIndex(TypeDesc type)
+ {
+ Debug.Assert(type.IsPrimitive, "it is not a primitive type");
+
+ uint typeIndex;
+
+ if (_primitiveTypes.TryGetValue(type, out typeIndex))
+ return typeIndex;
+
+ typeIndex = _objectWriter.GetPrimitiveTypeIndex(type);
+ _primitiveTypes[type] = typeIndex;
+
+ return typeIndex;
+ }
+
private ITypesDebugInfoWriter _objectWriter;
private Dictionary<TypeDesc, uint> _knownTypes = new Dictionary<TypeDesc, uint>();
private Dictionary<TypeDesc, uint> _completeKnownTypes = new Dictionary<TypeDesc, uint>();
@@ -538,6 +640,7 @@ namespace ILCompiler
private Dictionary<TypeDesc, uint> _enumTypes = new Dictionary<TypeDesc, uint>();
private Dictionary<TypeDesc, uint> _byRefTypes = new Dictionary<TypeDesc, uint>();
private Dictionary<TypeDesc, uint> _thisTypes = new Dictionary<TypeDesc, uint>();
+ private Dictionary<TypeDesc, uint> _primitiveTypes = new Dictionary<TypeDesc, uint>();
private Dictionary<MethodDesc, uint> _methodIndices = new Dictionary<MethodDesc, uint>();
private Dictionary<MethodDesc, uint> _methodIdIndices = new Dictionary<MethodDesc, uint>();
diff --git a/src/ILCompiler.Compiler/src/Compiler/UtcNameMangler.cs b/src/ILCompiler.Compiler/src/Compiler/UtcNameMangler.cs
index 6eaf70a75..5a0aa6515 100644
--- a/src/ILCompiler.Compiler/src/Compiler/UtcNameMangler.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/UtcNameMangler.cs
@@ -40,15 +40,19 @@ namespace ILCompiler
private ImportExportOrdinals _importOrdinals;
private ImportExportOrdinals _exportOrdinals;
+ private Dictionary<EcmaModule, int> _inputModuleIndices;
+
private bool HasImport { get; set; }
private bool HasExport { get; set; }
+ private bool BuildingClassLib { get; }
- public UTCNameMangler(bool hasImport, bool hasExport, ImportExportOrdinals ordinals) : base(new UtcNodeMangler())
+ public UTCNameMangler(bool hasImport, bool hasExport, ImportExportOrdinals ordinals, TypeSystemContext context, List<EcmaModule> inputModules, bool buildingClassLib) : base(new UtcNodeMangler())
{
// Do not support both imports and exports for one module
Debug.Assert(!hasImport || !hasExport);
HasImport = hasImport;
HasExport = hasExport;
+ BuildingClassLib = buildingClassLib;
if (hasImport)
{
@@ -59,11 +63,35 @@ namespace ILCompiler
_exportOrdinals = ordinals;
}
+ _inputModuleIndices = new Dictionary<EcmaModule, int>();
+ for (int i = 0; i < inputModules.Count; i++)
+ _inputModuleIndices[inputModules[i]] = i;
+
// Use SHA256 hash here to provide a high degree of uniqueness to symbol names without requiring them to be long
// This hash function provides an exceedingly high likelihood that no two strings will be given equal symbol names
// This is not considered used for security purpose; however collisions would be highly unfortunate as they will cause compilation
// failure.
_sha256 = SHA256.Create();
+
+ // Special case primitive types and use shortened names. This reduces string sizes in symbol names, and reduces the overall native memory
+ // usage of the compiler
+ _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.Void), "void");
+ _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.Boolean), "bool");
+ _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.Char), "char");
+ _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.SByte), "sbyte");
+ _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.Byte), "byte");
+ _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.Int16), "short");
+ _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.UInt16), "ushort");
+ _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.Int32), "int");
+ _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.UInt32), "uint");
+ _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.Int64), "long");
+ _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.UInt64), "ulong");
+ _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.Single), "float");
+ _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.Double), "double");
+ _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.Object), "object");
+ _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.String), "string");
+ _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.IntPtr), "IntPtr");
+ _mangledTypeNames = _mangledTypeNames.Add(context.GetWellKnownType(WellKnownType.UIntPtr), "UIntPtr");
}
private bool GetMethodOrdinal(MethodDesc method, out uint ordinal)
@@ -157,6 +185,15 @@ namespace ILCompiler
continue;
}
+ if (sb != null)
+ {
+ if (c == '[' || c == ']' || c == '&' || c == '*' || c == '$' || c == '<' || c == '>')
+ {
+ sb.Append(c);
+ continue;
+ }
+ }
+
if (sb == null)
sb = new StringBuilder(s, 0, i, s.Length);
@@ -167,6 +204,13 @@ namespace ILCompiler
continue;
}
+ if (c == '$' && i == 0)
+ {
+ // '$' is used at the begining of the string as assembly identifiers (ex: $0_, similar to ProjectN)
+ sb.Append(c);
+ continue;
+ }
+
// Everything else is replaced by underscore.
// TODO: We assume that there won't be collisions with our own or C++ built-in identifiers.
sb.Append("_");
@@ -254,6 +298,20 @@ namespace ILCompiler
return EnterNameScopeSequence + name + ExitNameScopeSequence;
}
+ private string ComputeMangledModuleName(EcmaAssembly module)
+ {
+ // Do not prepend the module prefix when building pntestcl because the prefix is unknown
+ // when building an app against pntestcl.
+ if (!BuildingClassLib)
+ {
+ int index;
+ if (_inputModuleIndices.TryGetValue(module, out index))
+ return "$" + index;
+ }
+
+ return SanitizeName(module.GetName().Name);
+ }
+
/// <summary>
/// If given <param name="type"/> is an <see cref="EcmaType"/> precompute its mangled type name
/// along with all the other types from the same module as <param name="type"/>.
@@ -268,7 +326,7 @@ namespace ILCompiler
{
EcmaType ecmaType = (EcmaType)type;
- string prependAssemblyName = SanitizeName(((EcmaAssembly)ecmaType.EcmaModule).GetName().Name);
+ string prependAssemblyName = ComputeMangledModuleName((EcmaAssembly)ecmaType.EcmaModule);
var deduplicator = new HashSet<string>();
@@ -280,6 +338,15 @@ namespace ILCompiler
{
foreach (MetadataType t in ((EcmaType)type).EcmaModule.GetAllTypes())
{
+ if (_mangledTypeNames.ContainsKey(t))
+ {
+ Debug.Assert(
+ (t.Category & TypeFlags.CategoryMask) <= TypeFlags.Double ||
+ t == type.Context.GetWellKnownType(WellKnownType.Object) ||
+ t == type.Context.GetWellKnownType(WellKnownType.String));
+ continue;
+ }
+
string name = t.GetFullName();
// Include encapsulating type
@@ -290,8 +357,7 @@ namespace ILCompiler
containingType = containingType.ContainingType;
}
- name = SanitizeName(name, true);
- name = prependAssemblyName + "_" + name;
+ name = SanitizeName(prependAssemblyName + "_" + name, true);
// Ensure that name is unique and update our tables accordingly.
name = DisambiguateName(name, deduplicator);
@@ -310,22 +376,22 @@ namespace ILCompiler
{
case TypeFlags.Array:
case TypeFlags.SzArray:
- mangledName = GetMangledTypeName(((ArrayType)type).ElementType) + "__";
+ mangledName = GetMangledTypeName(((ArrayType)type).ElementType);
if (type.IsMdArray)
{
- mangledName += NestMangledName("ArrayRank" + ((ArrayType)type).Rank.ToStringInvariant());
+ mangledName += "[md" + ((ArrayType)type).Rank.ToString() + "]";
}
else
{
- mangledName += NestMangledName("Array");
+ mangledName += "[]";
}
break;
case TypeFlags.ByRef:
- mangledName = GetMangledTypeName(((ByRefType)type).ParameterType) + NestMangledName("ByRef");
+ mangledName = GetMangledTypeName(((ByRefType)type).ParameterType) + "&";
break;
case TypeFlags.Pointer:
- mangledName = GetMangledTypeName(((PointerType)type).ParameterType) + NestMangledName("Pointer");
+ mangledName = GetMangledTypeName(((PointerType)type).ParameterType) + "*";
break;
default:
diff --git a/src/ILCompiler.Compiler/src/Compiler/VirtualMethodCallHelper.cs b/src/ILCompiler.Compiler/src/Compiler/VirtualMethodCallHelper.cs
index 27b1198c6..19da1f6ae 100644
--- a/src/ILCompiler.Compiler/src/Compiler/VirtualMethodCallHelper.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/VirtualMethodCallHelper.cs
@@ -16,29 +16,74 @@ namespace ILCompiler
/// Given a virtual method decl, return its VTable slot if the method is used on its containing type.
/// Return -1 if the virtual method is not used.
/// </summary>
- public static int GetVirtualMethodSlot(NodeFactory factory, MethodDesc method, bool countDictionarySlots = true)
+ public static int GetVirtualMethodSlot(NodeFactory factory, MethodDesc method, TypeDesc implType, bool countDictionarySlots = true)
{
- // TODO: More efficient lookup of the slot
- TypeDesc owningType = method.OwningType;
- int baseSlots = GetNumberOfBaseSlots(factory, owningType, countDictionarySlots);
-
- // For types that have a generic dictionary, the introduced virtual method slots are
- // prefixed with a pointer to the generic dictionary.
- if (owningType.HasGenericDictionarySlot() && countDictionarySlots)
- baseSlots++;
-
- IReadOnlyList<MethodDesc> virtualSlots = factory.VTable(owningType).Slots;
- int methodSlot = -1;
- for (int slot = 0; slot < virtualSlots.Count; slot++)
+ if (method.CanMethodBeInSealedVTable())
{
- if (virtualSlots[slot] == method)
+ // If the method is a sealed newslot method, it will be put in the sealed vtable instead of the type's vtable. In this
+ // case, the slot index return should be the index in the sealed vtable, plus the total number of vtable slots.
+
+ // First, make sure we are not attempting to resolve the slot of a sealed vtable method on a special array type, which
+ // does not get any sealed vtable entries
+ Debug.Assert(!implType.IsArrayTypeWithoutGenericInterfaces());
+
+ // Ensure the sealed vtable is built before computing the slot
+ factory.SealedVTable(implType).BuildSealedVTableSlots(factory, relocsOnly: false /* GetVirtualMethodSlot is called in the final emission phase */);
+
+ int sealedVTableSlot = factory.SealedVTable(implType).ComputeSealedVTableSlot(method);
+ if (sealedVTableSlot == -1)
+ return -1;
+
+ // Now compute the total number of vtable slots that would exist on the type
+ int baseSlots = GetNumberOfBaseSlots(factory, implType, countDictionarySlots);
+
+ // For types that have a generic dictionary, the introduced virtual method slots are
+ // prefixed with a pointer to the generic dictionary.
+ if (implType.HasGenericDictionarySlot() && countDictionarySlots)
+ baseSlots++;
+
+ int numVTableSlots = baseSlots;
+ IReadOnlyList<MethodDesc> virtualSlots = factory.VTable(implType).Slots;
+ for (int slot = 0; slot < virtualSlots.Count; slot++)
{
- methodSlot = slot;
- break;
+ if (virtualSlots[slot].CanMethodBeInSealedVTable())
+ continue;
+ numVTableSlots++;
}
+
+ return numVTableSlots + sealedVTableSlot;
}
+ else
+ {
+ // TODO: More efficient lookup of the slot
+ TypeDesc owningType = method.OwningType;
+ int baseSlots = GetNumberOfBaseSlots(factory, owningType, countDictionarySlots);
- return methodSlot == -1 ? -1 : baseSlots + methodSlot;
+ // For types that have a generic dictionary, the introduced virtual method slots are
+ // prefixed with a pointer to the generic dictionary.
+ if (owningType.HasGenericDictionarySlot() && countDictionarySlots)
+ baseSlots++;
+
+ IReadOnlyList<MethodDesc> virtualSlots = factory.VTable(owningType).Slots;
+ int methodSlot = -1;
+ int numSealedVTableEntries = 0;
+ for (int slot = 0; slot < virtualSlots.Count; slot++)
+ {
+ if (virtualSlots[slot].CanMethodBeInSealedVTable())
+ {
+ numSealedVTableEntries++;
+ continue;
+ }
+
+ if (virtualSlots[slot] == method)
+ {
+ methodSlot = slot;
+ break;
+ }
+ }
+
+ return methodSlot == -1 ? -1 : baseSlots + methodSlot - numSealedVTableEntries;
+ }
}
private static int GetNumberOfBaseSlots(NodeFactory factory, TypeDesc owningType, bool countDictionarySlots)
@@ -83,7 +128,13 @@ namespace ILCompiler
baseSlots++;
IReadOnlyList<MethodDesc> baseVirtualSlots = factory.VTable(baseType).Slots;
- baseSlots += baseVirtualSlots.Count;
+ foreach (var vtableMethod in baseVirtualSlots)
+ {
+ // Methods in the sealed vtable should be excluded from the count
+ if (vtableMethod.CanMethodBeInSealedVTable())
+ continue;
+ baseSlots++;
+ }
baseType = baseType.BaseType;
templateBaseType = templateBaseType.BaseType;
diff --git a/src/ILCompiler.Compiler/src/Compiler/WindowsNodeMangler.cs b/src/ILCompiler.Compiler/src/Compiler/WindowsNodeMangler.cs
index 81f5e1592..0c3d3163a 100644
--- a/src/ILCompiler.Compiler/src/Compiler/WindowsNodeMangler.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/WindowsNodeMangler.cs
@@ -47,7 +47,10 @@ namespace ILCompiler
public sealed override string ThreadStatics(TypeDesc type)
{
- return NameMangler.CompilationUnitPrefix + NameMangler.GetMangledTypeName(type) + "::" + ThreadStaticMemberName;
+ if (type.Context.Target.Abi == TargetAbi.ProjectN)
+ return NameMangler.GetMangledTypeName(type) + "::" + ThreadStaticMemberName;
+ else
+ return NameMangler.CompilationUnitPrefix + NameMangler.GetMangledTypeName(type) + "::" + ThreadStaticMemberName;
}
public sealed override string TypeGenericDictionary(TypeDesc type)
diff --git a/src/ILCompiler.Compiler/src/IL/ILImporter.Scanner.cs b/src/ILCompiler.Compiler/src/IL/ILImporter.Scanner.cs
index 009dc068b..9468e25f1 100644
--- a/src/ILCompiler.Compiler/src/IL/ILImporter.Scanner.cs
+++ b/src/ILCompiler.Compiler/src/IL/ILImporter.Scanner.cs
@@ -19,6 +19,7 @@ namespace Internal.IL
partial class ILImporter
{
private readonly MethodIL _methodIL;
+ private readonly MethodIL _canonMethodIL;
private readonly ILScanner _compilation;
private readonly ILScanNodeFactory _factory;
@@ -84,6 +85,8 @@ namespace Internal.IL
_ilBytes = methodIL.GetILBytes();
+ _canonMethodIL = methodIL;
+
// Get the runtime determined method IL so that this works right in shared code
// and tokens in shared code resolve to runtime determined types.
MethodIL uninstantiatiedMethodIL = methodIL.GetMethodILDefinition();
@@ -266,11 +269,10 @@ namespace Internal.IL
private void ImportCall(ILOpcode opcode, int token)
{
- // Strip runtime determined characteristics off of the method (because that's how RyuJIT operates)
+ // We get both the canonical and runtime determined form - JitInterface mostly operates
+ // on the canonical form.
var runtimeDeterminedMethod = (MethodDesc)_methodIL.GetObject(token);
- MethodDesc method = runtimeDeterminedMethod;
- if (runtimeDeterminedMethod.IsRuntimeDeterminedExactMethod)
- method = runtimeDeterminedMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
+ var method = (MethodDesc)_canonMethodIL.GetObject(token);
if (method.IsRawPInvoke())
{
@@ -354,10 +356,14 @@ namespace Internal.IL
}
}
- if (method.OwningType.IsDelegate && method.Name == "Invoke")
+ if (method.OwningType.IsDelegate && method.Name == "Invoke" &&
+ opcode != ILOpcode.ldftn && opcode != ILOpcode.ldvirtftn)
{
- // TODO: might not want to do this if scanning for reflection.
- // This is expanded as an intrinsic, not a function call.
+ // This call is expanded as an intrinsic; it's not an actual function call.
+ // Before codegen realizes this is an intrinsic, it might still ask questions about
+ // the vtable of this virtual method, so let's make sure it's marked in the scanner's
+ // dependency graph.
+ _dependencies.Add(_factory.VTable(method.OwningType), reason);
return;
}
diff --git a/src/ILCompiler.Compiler/src/IL/Stubs/PInvokeILProvider.cs b/src/ILCompiler.Compiler/src/IL/Stubs/PInvokeILProvider.cs
index 4aec04036..7ae483dbc 100644
--- a/src/ILCompiler.Compiler/src/IL/Stubs/PInvokeILProvider.cs
+++ b/src/ILCompiler.Compiler/src/IL/Stubs/PInvokeILProvider.cs
@@ -29,5 +29,10 @@ namespace Internal.IL
{
return PInvokeILEmitter.EmitIL(method, _pInvokeILEmitterConfiguration, _interopStateManager);
}
+
+ public MethodDesc GetCalliStub(MethodSignature signature)
+ {
+ return _interopStateManager.GetPInvokeCalliStub(signature);
+ }
}
}
diff --git a/src/ILCompiler.Compiler/src/IL/Stubs/StartupCode/AppContextInitializerMethod.Sorting.cs b/src/ILCompiler.Compiler/src/IL/Stubs/StartupCode/AppContextInitializerMethod.Sorting.cs
new file mode 100644
index 000000000..67a2b612c
--- /dev/null
+++ b/src/ILCompiler.Compiler/src/IL/Stubs/StartupCode/AppContextInitializerMethod.Sorting.cs
@@ -0,0 +1,22 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.TypeSystem;
+
+using Debug = System.Diagnostics.Debug;
+
+namespace Internal.IL.Stubs.StartupCode
+{
+ partial class AppContextInitializerMethod
+ {
+ protected override int ClassCode => 15749517;
+
+ protected override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer)
+ {
+ // Should be a singleton
+ Debug.Assert(this == other);
+ return 0;
+ }
+ }
+}
diff --git a/src/ILCompiler.Compiler/src/IL/Stubs/StartupCode/AppContextInitializerMethod.cs b/src/ILCompiler.Compiler/src/IL/Stubs/StartupCode/AppContextInitializerMethod.cs
new file mode 100644
index 000000000..2c2d3a51a
--- /dev/null
+++ b/src/ILCompiler.Compiler/src/IL/Stubs/StartupCode/AppContextInitializerMethod.cs
@@ -0,0 +1,83 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+
+using Internal.TypeSystem;
+
+namespace Internal.IL.Stubs.StartupCode
+{
+ public sealed partial class AppContextInitializerMethod : ILStubMethod
+ {
+ private TypeDesc _owningType;
+ private MethodSignature _signature;
+ private IReadOnlyCollection<string> _switches;
+
+ public AppContextInitializerMethod(TypeDesc owningType, IEnumerable<string> switches)
+ {
+ _owningType = owningType;
+ _switches = new List<string>(switches);
+ }
+
+ public override TypeSystemContext Context
+ {
+ get
+ {
+ return _owningType.Context;
+ }
+ }
+
+ public override TypeDesc OwningType
+ {
+ get
+ {
+ return _owningType;
+ }
+ }
+
+ public override string Name
+ {
+ get
+ {
+ return "SetAppContextSwitches";
+ }
+ }
+
+ public override MethodIL EmitIL()
+ {
+ ILEmitter emitter = new ILEmitter();
+ ILCodeStream codeStream = emitter.NewCodeStream();
+
+ MetadataType appContextType = Context.SystemModule.GetKnownType("System", "AppContext");
+ MethodDesc setSwitchMethod = appContextType.GetKnownMethod("SetSwitch", null);
+ ILToken setSwitchToken = emitter.NewToken(setSwitchMethod);
+
+ foreach (string switchName in _switches)
+ {
+ codeStream.Emit(ILOpcode.ldstr, emitter.NewToken(switchName));
+ codeStream.EmitLdc(1);
+ codeStream.Emit(ILOpcode.call, setSwitchToken);
+ }
+
+ codeStream.Emit(ILOpcode.ret);
+
+ return emitter.Link(this);
+ }
+
+ public override MethodSignature Signature
+ {
+ get
+ {
+ if (_signature == null)
+ {
+ _signature = new MethodSignature(MethodSignatureFlags.Static, 0,
+ Context.GetWellKnownType(WellKnownType.Void),
+ TypeDesc.EmptyTypes);
+ }
+
+ return _signature;
+ }
+ }
+ }
+}
diff --git a/src/ILCompiler.Compiler/src/IL/Stubs/StartupCode/NativeLibraryStartupMethod.cs b/src/ILCompiler.Compiler/src/IL/Stubs/StartupCode/NativeLibraryStartupMethod.cs
index 80bd691a0..b04e5e988 100644
--- a/src/ILCompiler.Compiler/src/IL/Stubs/StartupCode/NativeLibraryStartupMethod.cs
+++ b/src/ILCompiler.Compiler/src/IL/Stubs/StartupCode/NativeLibraryStartupMethod.cs
@@ -17,9 +17,9 @@ namespace Internal.IL.Stubs.StartupCode
{
private TypeDesc _owningType;
private MethodSignature _signature;
- private IList<MethodDesc> _libraryInitializers;
+ private IReadOnlyCollection<MethodDesc> _libraryInitializers;
- public NativeLibraryStartupMethod(TypeDesc owningType, IList<MethodDesc> libraryInitializers)
+ public NativeLibraryStartupMethod(TypeDesc owningType, IReadOnlyCollection<MethodDesc> libraryInitializers)
{
_owningType = owningType;
_libraryInitializers = libraryInitializers;
diff --git a/src/ILCompiler.Compiler/src/IL/Stubs/StartupCode/StartupCodeMainMethod.cs b/src/ILCompiler.Compiler/src/IL/Stubs/StartupCode/StartupCodeMainMethod.cs
index f994a1d0a..fd16383f5 100644
--- a/src/ILCompiler.Compiler/src/IL/Stubs/StartupCode/StartupCodeMainMethod.cs
+++ b/src/ILCompiler.Compiler/src/IL/Stubs/StartupCode/StartupCodeMainMethod.cs
@@ -21,9 +21,9 @@ namespace Internal.IL.Stubs.StartupCode
private TypeDesc _owningType;
private MainMethodWrapper _mainMethod;
private MethodSignature _signature;
- private IList<MethodDesc> _libraryInitializers;
+ private IReadOnlyCollection<MethodDesc> _libraryInitializers;
- public StartupCodeMainMethod(TypeDesc owningType, MethodDesc mainMethod, IList<MethodDesc> libraryInitializers)
+ public StartupCodeMainMethod(TypeDesc owningType, MethodDesc mainMethod, IReadOnlyCollection<MethodDesc> libraryInitializers)
{
_owningType = owningType;
_mainMethod = new MainMethodWrapper(owningType, mainMethod);
diff --git a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj
index a29a5cd10..be2d84a43 100644
--- a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj
+++ b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj
@@ -58,9 +58,6 @@
<Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\ComparerIntrinsics.cs">
<Link>IL\Stubs\ComparerIntrinsics.cs</Link>
</Compile>
- <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DynamicInvokeMethodThunk.Sorting.cs">
- <Link>IL\Stubs\DynamicInvokeMethodThunk.Sorting.cs</Link>
- </Compile>
<Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\GetCanonTypeIntrinsic.cs">
<Link>IL\Stubs\GetCanonTypeIntrinsic.cs</Link>
</Compile>
@@ -73,9 +70,6 @@
<Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DelegateMethodILEmitter.cs">
<Link>IL\Stubs\DelegateMethodILEmitter.cs</Link>
</Compile>
- <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DynamicInvokeMethodThunk.cs">
- <Link>IL\Stubs\DynamicInvokeMethodThunk.cs</Link>
- </Compile>
<Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\EETypePtrOfIntrinsic.cs">
<Link>IL\Stubs\EETypePtrOfIntrinsic.cs</Link>
</Compile>
@@ -100,8 +94,6 @@
<Compile Include="Compiler\AnalysisBasedMetadataManager.cs" />
<Compile Include="Compiler\BlockedInternalsBlockingPolicy.cs" />
<Compile Include="Compiler\CodeGenerationFailedException.cs" />
- <Compile Include="Compiler\CompilerGeneratedType.cs" />
- <Compile Include="Compiler\CompilerGeneratedType.Sorting.cs" />
<Compile Include="Compiler\CompilerTypeSystemContext.BoxedTypes.cs" />
<Compile Include="Compiler\CompilerTypeSystemContext.Mangling.cs" />
<Compile Include="Compiler\CompilerTypeSystemContext.Sorting.cs" />
@@ -110,6 +102,8 @@
<Compile Include="Compiler\DependencyAnalysis\DefaultConstructorMapNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\ExternSymbolsImportedNodeProvider.cs" />
<Compile Include="Compiler\DependencyAnalysis\ExternSymbolsWithIndirectionImportedNodeProvider.cs" />
+ <Compile Include="Compiler\DependencyAnalysis\IndirectionExtensions.cs" />
+ <Compile Include="Compiler\DependencyAnalysis\InterfaceDispatchCellSectionNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\MrtImportImportedNodeProvider.cs" />
<Compile Include="Compiler\DependencyAnalysis\MrtImports.cs" />
<Compile Include="Compiler\DependencyAnalysis\MrtProcessedExportAddressTableNode.cs" />
@@ -132,14 +126,21 @@
<Compile Include="Compiler\DependencyAnalysis\IMethodBodyNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\IMethodBodyNodeWithFuncletSymbols.cs" />
<Compile Include="Compiler\DependencyAnalysis\ISymbolNodeWithFuncletId.cs" />
+ <Compile Include="Compiler\DependencyAnalysis\ISymbolNodeWithDebugInfo.cs" />
<Compile Include="Compiler\DependencyAnalysis\LoopHijackFlagNode.cs" />
<Compile Include="Compiler\DevirtualizationManager.cs" />
<Compile Include="Compiler\DictionaryLayoutProvider.cs" />
+ <Compile Include="Compiler\DynamicInvokeThunkGenerationPolicy.cs" />
<Compile Include="Compiler\EmptyInteropStubManager.cs" />
+ <Compile Include="Compiler\DependencyAnalysis\ISortableNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\SortableDependencyNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\ImportedNodeProvider.cs" />
+ <Compile Include="Compiler\FrameworkStringResourceBlockingPolicy.cs" />
<Compile Include="Compiler\GeneratingMetadataManager.cs" />
<Compile Include="Compiler\InternalCompilerErrorException.cs" />
+ <Compile Include="Compiler\ManifestResourceBlockingPolicy.cs" />
+ <Compile Include="Compiler\NoManifestResourceBlockingPolicy.cs" />
+ <Compile Include="Compiler\NoMetadataBlockingPolicy.cs" />
<Compile Include="Compiler\PreInitFieldInfo.cs" />
<Compile Include="Compiler\DependencyAnalysis\FrozenArrayNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\GCStaticsPreInitDataNode.cs" />
@@ -280,9 +281,9 @@
<Compile Include="Compiler\DependencyAnalysis\UtcThreadStaticsNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\TypeMetadataMapNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\UnboxingStubNode.cs" />
- <Compile Include="Compiler\DependencyAnalysis\UtcDictionaryLayoutNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\UtcNodeFactory.cs" />
<Compile Include="Compiler\DependencyAnalysis\VirtualMethodUseNode.cs" />
+ <Compile Include="Compiler\DependencyAnalysis\SealedVTableNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\StackTraceMethodMappingNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\StackTraceEmbeddedMetadataNode.cs" />
<Compile Include="Compiler\DependencyAnalysis\Target_X64\Register.cs" />
@@ -335,6 +336,7 @@
<Compile Include="Compiler\ExportsFileWriter.cs" />
<Compile Include="Compiler\PrecomputedMetadataManager.cs" />
<Compile Include="Compiler\ReadyToRun.cs" />
+ <Compile Include="Compiler\RuntimeConfigurationRootProvider.cs" />
<Compile Include="Compiler\RyuJitCompilation.cs" />
<Compile Include="Compiler\RyuJitCompilationBuilder.cs" />
<Compile Include="Compiler\SingleFileCompilationModuleGroup.cs" />
@@ -359,6 +361,8 @@
<Compile Include="Compiler\WindowsNodeMangler.cs" />
<Compile Include="IL\ILImporter.Scanner.cs" />
<Compile Include="IL\Stubs\PInvokeILProvider.cs" />
+ <Compile Include="IL\Stubs\StartupCode\AppContextInitializerMethod.cs" />
+ <Compile Include="IL\Stubs\StartupCode\AppContextInitializerMethod.Sorting.cs" />
<Compile Include="IL\Stubs\StartupCode\StartupCodeMainMethod.cs" />
<Compile Include="IL\Stubs\StartupCode\StartupCodeMainMethod.Sorting.cs" />
<Compile Include="IL\Stubs\StartupCode\NativeLibraryStartupMethod.cs" />
diff --git a/src/ILCompiler.Compiler/tests/DependencyGraphTests.cs b/src/ILCompiler.Compiler/tests/DependencyGraphTests.cs
index c4ace726b..a0a60efda 100644
--- a/src/ILCompiler.Compiler/tests/DependencyGraphTests.cs
+++ b/src/ILCompiler.Compiler/tests/DependencyGraphTests.cs
@@ -64,7 +64,7 @@ namespace ILCompiler.Compiler.Tests
//
var context = (CompilerTypeSystemContext)method.Context;
- CompilationModuleGroup compilationGroup = new SingleFileCompilationModuleGroup(context);
+ CompilationModuleGroup compilationGroup = new SingleFileCompilationModuleGroup();
CompilationBuilder builder = new RyuJitCompilationBuilder(context, compilationGroup);
IILScanner scanner = builder.GetILScannerBuilder()
diff --git a/src/ILCompiler.Compiler/tests/DevirtualizationTests.cs b/src/ILCompiler.Compiler/tests/DevirtualizationTests.cs
index 6b320fb17..0ebda0cbc 100644
--- a/src/ILCompiler.Compiler/tests/DevirtualizationTests.cs
+++ b/src/ILCompiler.Compiler/tests/DevirtualizationTests.cs
@@ -32,7 +32,7 @@ namespace ILCompiler.Compiler.Tests
private DevirtualizationManager GetDevirtualizationManagerFromScan(MethodDesc method)
{
- CompilationModuleGroup compilationGroup = new SingleFileCompilationModuleGroup(_context);
+ CompilationModuleGroup compilationGroup = new SingleFileCompilationModuleGroup();
CompilationBuilder builder = new RyuJitCompilationBuilder(_context, compilationGroup);
IILScanner scanner = builder.GetILScannerBuilder()
diff --git a/src/ILCompiler.Compiler/tests/ILCompiler.Compiler.Tests.Assets/ILCompiler.Compiler.Tests.Assets.csproj b/src/ILCompiler.Compiler/tests/ILCompiler.Compiler.Tests.Assets/ILCompiler.Compiler.Tests.Assets.csproj
index 44d852d96..a463d125f 100644
--- a/src/ILCompiler.Compiler/tests/ILCompiler.Compiler.Tests.Assets/ILCompiler.Compiler.Tests.Assets.csproj
+++ b/src/ILCompiler.Compiler/tests/ILCompiler.Compiler.Tests.Assets/ILCompiler.Compiler.Tests.Assets.csproj
@@ -4,7 +4,7 @@
<OutputType>Library</OutputType>
<AssemblyName>ILCompiler.Compiler.Tests.Assets</AssemblyName>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
- <RunTestsForProject>false</RunTestsForProject>
+ <SkipTestRun>true</SkipTestRun>
</PropertyGroup>
<ItemGroup>
diff --git a/src/ILCompiler.Compiler/tests/ILCompiler.Compiler.Tests.csproj b/src/ILCompiler.Compiler/tests/ILCompiler.Compiler.Tests.csproj
index 6e2a7f7f4..797bb79fe 100644
--- a/src/ILCompiler.Compiler/tests/ILCompiler.Compiler.Tests.csproj
+++ b/src/ILCompiler.Compiler/tests/ILCompiler.Compiler.Tests.csproj
@@ -4,11 +4,14 @@
<OutputType>Library</OutputType>
<AssemblyName>ILCompiler.Compiler.Tests</AssemblyName>
<RootNamespace>ILCompiler.Compiler.Tests</RootNamespace>
- <TargetFramework>netstandard1.3</TargetFramework>
+ <TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.DotNet.BuildTools.TestSuite">
- <Version>$(XunitNetcoreExtensionsVersion)</Version>
+ <PackageReference Include="xunit">
+ <Version>$(XUnitPackageVersion)</Version>
+ </PackageReference>
+ <PackageReference Include="Microsoft.DotNet.XUnitExtensions">
+ <Version>$(MicrosoftDotNetXUnitExtensionsVersion)</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
diff --git a/src/ILCompiler.CppCodeGen/src/Compiler/CppCodegenCompilationBuilder.cs b/src/ILCompiler.CppCodeGen/src/Compiler/CppCodegenCompilationBuilder.cs
index 8b4fe6360..0068f2da8 100644
--- a/src/ILCompiler.CppCodeGen/src/Compiler/CppCodegenCompilationBuilder.cs
+++ b/src/ILCompiler.CppCodeGen/src/Compiler/CppCodegenCompilationBuilder.cs
@@ -31,7 +31,7 @@ namespace ILCompiler
public override ICompilation ToCompilation()
{
- var interopStubManager = new CompilerGeneratedInteropStubManager(_compilationGroup, _context, new InteropStateManager(_compilationGroup.GeneratedAssembly));
+ var interopStubManager = new CompilerGeneratedInteropStubManager(_compilationGroup, _context, new InteropStateManager(_context.GeneratedAssembly));
CppCodegenNodeFactory factory = new CppCodegenNodeFactory(_context, _compilationGroup, _metadataManager, interopStubManager, _nameMangler, _vtableSliceProvider, _dictionaryLayoutProvider);
DependencyAnalyzerBase<NodeFactory> graph = CreateDependencyGraph(factory);
diff --git a/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppCodegenNodeFactory.cs b/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppCodegenNodeFactory.cs
index baf0339aa..d282e1f27 100644
--- a/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppCodegenNodeFactory.cs
+++ b/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppCodegenNodeFactory.cs
@@ -40,8 +40,7 @@ namespace ILCompiler.DependencyAnalysis
protected override IMethodNode CreateUnboxingStubNode(MethodDesc method)
{
- // TODO: this is wrong: this returns an assembly stub node
- return new UnboxingStubNode(method, Target);
+ return new CppUnboxingStubNode(method);
}
protected override ISymbolNode CreateReadyToRunHelperNode(ReadyToRunHelperKey helperCall)
diff --git a/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppMethodCodeNode.cs b/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppMethodCodeNode.cs
index 70a138649..49f610ef4 100644
--- a/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppMethodCodeNode.cs
+++ b/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppMethodCodeNode.cs
@@ -76,9 +76,9 @@ namespace ILCompiler.DependencyAnalysis
public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) => null;
public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null;
- int ISortableSymbolNode.ClassCode => 1643555522;
+ int ISortableNode.ClassCode => 1643555522;
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
+ int ISortableNode.CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_method, ((CppMethodCodeNode)other)._method);
}
diff --git a/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppUnboxingStubNode.cs b/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppUnboxingStubNode.cs
new file mode 100644
index 000000000..a47dca6db
--- /dev/null
+++ b/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppUnboxingStubNode.cs
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Diagnostics;
+
+using ILCompiler.DependencyAnalysisFramework;
+
+using Internal.Text;
+using Internal.TypeSystem;
+
+namespace ILCompiler.DependencyAnalysis
+{
+ internal class CppUnboxingStubNode : DependencyNodeCore<NodeFactory>, IMethodNode
+ {
+ public CppUnboxingStubNode(MethodDesc method)
+ {
+ Debug.Assert(method.OwningType.IsValueType && !method.Signature.IsStatic);
+ Method = method;
+ }
+
+ public MethodDesc Method { get; }
+
+ public int ClassCode => 17864523;
+
+ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
+ {
+ sb.Append("unbox_").Append(nameMangler.GetMangledMethodName(Method));
+ }
+
+ public int CompareToImpl(ISortableNode other, CompilerComparer comparer)
+ {
+ return comparer.Compare(this.Method, ((CppUnboxingStubNode)other).Method);
+ }
+
+ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
+ {
+ return new DependencyListEntry[] {
+ new DependencyListEntry(factory.MethodEntrypoint(Method), "Target of unboxing") };
+ }
+
+ protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
+
+ public static string GetMangledName(NameMangler nameMangler, MethodDesc method)
+ {
+ return "unbox_" + nameMangler.GetMangledMethodName(method);
+ }
+
+ public override bool StaticDependenciesAreComputed => true;
+ public override bool HasDynamicDependencies => false;
+ public override bool InterestingForDynamicDependencyAnalysis => false;
+ public override bool HasConditionalStaticDependencies => false;
+
+ public int Offset => throw new System.NotImplementedException();
+
+ public bool RepresentsIndirectionCell => throw new System.NotImplementedException();
+
+ public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory context)
+ {
+ return null;
+ }
+ public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context)
+ {
+ return null;
+ }
+ }
+}
diff --git a/src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs b/src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs
index ef08550b7..c813492bf 100644
--- a/src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs
+++ b/src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs
@@ -15,6 +15,8 @@ using Internal.Text;
using Internal.TypeSystem;
using Internal.TypeSystem.Ecma;
+using Debug = System.Diagnostics.Debug;
+
namespace ILCompiler.CppCodeGen
{
internal class CppWriter
@@ -586,17 +588,17 @@ namespace ILCompiler.CppCodeGen
if (explicitLayout || hasSize)
{
- if (classLayoutMetadata.Size > 0)
+ if (!explicitLayout)
{
+ sb.Exdent();
sb.AppendLine();
- sb.Append("struct { char __sizePadding[" + classLayoutMetadata.Size + "]; };");
+ sb.Append("};");
}
- if (!explicitLayout)
+ if (classLayoutMetadata.Size > 0)
{
- sb.Exdent();
sb.AppendLine();
- sb.Append("};");
+ sb.Append("struct { char __sizePadding[" + classLayoutMetadata.Size + "]; };");
}
sb.Exdent();
@@ -797,42 +799,61 @@ namespace ILCompiler.CppCodeGen
}
}
}
+
+ bool generateMethod = !(node is BlobNode);
+
string pointerType = node is EETypeNode ? "MethodTable * " : "void* ";
- nodeCode.Append(pointerType);
- if (node is EETypeNode)
+ if (generateMethod)
{
- nodeCode.Append(GetCppMethodDeclarationName((node as EETypeNode).Type, "__getMethodTable"));
+ nodeCode.Append(pointerType);
+ if (node is EETypeNode)
+ {
+ nodeCode.Append(GetCppMethodDeclarationName((node as EETypeNode).Type, "__getMethodTable"));
+ }
+ else
+ {
+ string mangledName = ((ISymbolNode)node).GetMangledName(factory.NameMangler);
+
+ // Rename generic composition and optional fields nodes to avoid name clash with types
+ bool shouldReplaceNamespaceQualifier = node is GenericCompositionNode || node is EETypeOptionalFieldsNode || node is SealedVTableNode;
+ nodeCode.Append(shouldReplaceNamespaceQualifier ? mangledName.Replace("::", "_") : mangledName);
+ }
+ nodeCode.Append("()");
+ nodeCode.AppendLine();
+ nodeCode.Append("{");
+ nodeCode.Indent();
+ nodeCode.AppendLine();
+ nodeCode.Append("static ");
}
else
{
- string mangledName = ((ISymbolNode)node).GetMangledName(factory.NameMangler);
-
- // Rename generic composition and optional fields nodes to avoid name clash with types
- bool shouldReplaceNamespaceQualifier = node is GenericCompositionNode || node is EETypeOptionalFieldsNode;
- nodeCode.Append(shouldReplaceNamespaceQualifier ? mangledName.Replace("::", "_") : mangledName);
+ nodeCode.Append("extern \"C\" ");
}
- nodeCode.Append("()");
- nodeCode.AppendLine();
- nodeCode.Append("{");
- nodeCode.Indent();
- nodeCode.AppendLine();
- nodeCode.Append("static struct {");
+ nodeCode.Append("struct {");
nodeCode.AppendLine();
nodeCode.Append(GetCodeForNodeStruct(nodeDataSections, node));
nodeCode.AppendLine();
- nodeCode.Append("} mt = {");
+
+ if (generateMethod)
+ nodeCode.Append("} mt = {");
+ else
+ nodeCode.Append(" } " + ((ISymbolNode)node).GetMangledName(factory.NameMangler) + " = {");
nodeCode.Append(GetCodeForNodeData(nodeDataSections, relocs, nodeData.Data, node, offset, factory));
nodeCode.Append("};");
- nodeCode.AppendLine();
- nodeCode.Append("return ( ");
- nodeCode.Append(pointerType);
- nodeCode.Append(")&mt;");
- nodeCode.Exdent();
- nodeCode.AppendLine();
- nodeCode.Append("}");
+
+ if (generateMethod)
+ {
+ nodeCode.AppendLine();
+ nodeCode.Append("return ( ");
+ nodeCode.Append(pointerType);
+ nodeCode.Append(")&mt;");
+ nodeCode.Exdent();
+ nodeCode.AppendLine();
+ nodeCode.Append("}");
+ }
nodeCode.AppendLine();
return nodeCode.ToString();
}
@@ -882,10 +903,15 @@ namespace ILCompiler.CppCodeGen
relocCode.Append("()");
}
// Node is either an non-emitted type or a generic composition - both are ignored for CPP codegen
- else if ((reloc.Target is TypeManagerIndirectionNode || reloc.Target is InterfaceDispatchMapNode || reloc.Target is EETypeOptionalFieldsNode || reloc.Target is GenericCompositionNode) && !(reloc.Target as ObjectNode).ShouldSkipEmittingObjectNode(factory))
+ else if ((reloc.Target is TypeManagerIndirectionNode ||
+ reloc.Target is InterfaceDispatchMapNode ||
+ reloc.Target is EETypeOptionalFieldsNode ||
+ reloc.Target is GenericCompositionNode ||
+ reloc.Target is SealedVTableNode
+ ) && !(reloc.Target as ObjectNode).ShouldSkipEmittingObjectNode(factory))
{
string mangledTargetName = reloc.Target.GetMangledName(factory.NameMangler);
- bool shouldReplaceNamespaceQualifier = reloc.Target is GenericCompositionNode || reloc.Target is EETypeOptionalFieldsNode;
+ bool shouldReplaceNamespaceQualifier = reloc.Target is GenericCompositionNode || reloc.Target is EETypeOptionalFieldsNode || reloc.Target is SealedVTableNode;
relocCode.Append(shouldReplaceNamespaceQualifier ? mangledTargetName.Replace("::", "_") : mangledTargetName);
relocCode.Append("()");
}
@@ -894,12 +920,12 @@ namespace ILCompiler.CppCodeGen
{
relocCode.Append("dispatchMapModule");
}
- else if(reloc.Target is UnboxingStubNode)
+ else if(reloc.Target is CppUnboxingStubNode)
{
- var method = reloc.Target as UnboxingStubNode;
+ var method = reloc.Target as CppUnboxingStubNode;
relocCode.Append("(void*)&");
- relocCode.Append(GetCppMethodDeclarationName(method.Method.OwningType, UnboxingStubNode.GetMangledName(factory.NameMangler, method.Method), false));
+ relocCode.Append(GetCppMethodDeclarationName(method.Method.OwningType, method.GetMangledName(factory.NameMangler), false));
}
else
{
@@ -1011,26 +1037,30 @@ namespace ILCompiler.CppCodeGen
//RTR header needs to be declared after all modules have already been output
string rtrHeader = string.Empty;
- // GetData stabilizes the indices of the embedded objects. This must be done manually
- // for C++ codegen since we don't currently emit the DispatchMapTable node directly.
- factory.DispatchMapTable.GetData(factory, false);
-
// Iterate through nodes
foreach (var node in nodeIterator.GetNodes())
{
if (node is EETypeNode)
OutputTypeNode(node as EETypeNode, factory, typeDefinitions, methodTables);
- else if ((node is EETypeOptionalFieldsNode || node is TypeManagerIndirectionNode || node is GenericCompositionNode) && !(node as ObjectNode).ShouldSkipEmittingObjectNode(factory))
+ else if ((node is EETypeOptionalFieldsNode ||
+ node is TypeManagerIndirectionNode ||
+ node is GenericCompositionNode ||
+ node is BlobNode ||
+ node is SealedVTableNode) && !(node as ObjectNode).ShouldSkipEmittingObjectNode(factory))
additionalNodes.Append(GetCodeForObjectNode(node as ObjectNode, factory));
- else if (node is InterfaceDispatchMapNode)
+ else if (node is ArrayOfEmbeddedPointersNode<InterfaceDispatchMapNode> dispatchMap)
{
- dispatchPointers.Append("(void *)");
- dispatchPointers.Append(((ISymbolNode)node).GetMangledName(factory.NameMangler));
- dispatchPointers.Append("(),");
- dispatchPointers.AppendLine();
- dispatchMapCount++;
- additionalNodes.Append(GetCodeForObjectNode(node as ObjectNode, factory));
-
+ var dispatchMapData = dispatchMap.GetData(factory, false);
+ Debug.Assert(dispatchMapData.Relocs.Length == dispatchMapData.Data.Length / factory.Target.PointerSize);
+ foreach (Relocation reloc in dispatchMapData.Relocs)
+ {
+ dispatchPointers.Append("(void *)");
+ dispatchPointers.Append(reloc.Target.GetMangledName(factory.NameMangler));
+ dispatchPointers.Append("(),");
+ dispatchPointers.AppendLine();
+ dispatchMapCount++;
+ additionalNodes.Append(GetCodeForObjectNode(reloc.Target as ObjectNode, factory));
+ }
}
else if (node is ReadyToRunHeaderNode)
rtrHeader = GetCodeForReadyToRunHeader(node as ReadyToRunHeaderNode, factory);
@@ -1202,23 +1232,15 @@ namespace ILCompiler.CppCodeGen
if (typeNode is ConstructedEETypeNode)
{
- IReadOnlyList<MethodDesc> virtualSlots = _compilation.NodeFactory.VTable(nodeType.GetClosestDefType()).Slots;
+ DefType closestDefType = nodeType.GetClosestDefType();
- int baseSlots = 0;
- var baseType = nodeType.BaseType;
- while (baseType != null)
- {
- IReadOnlyList<MethodDesc> baseVirtualSlots = _compilation.NodeFactory.VTable(baseType).Slots;
- if (baseVirtualSlots != null)
- baseSlots += baseVirtualSlots.Count;
- baseType = baseType.BaseType;
- }
+ IReadOnlyList<MethodDesc> virtualSlots = _compilation.NodeFactory.VTable(closestDefType).Slots;
- for (int slot = 0; slot < virtualSlots.Count; slot++)
+ foreach (MethodDesc slot in virtualSlots)
{
- MethodDesc virtualMethod = virtualSlots[slot];
typeDefinitions.AppendLine();
- typeDefinitions.Append(GetCodeForVirtualMethod(virtualMethod, baseSlots + slot));
+ int slotNumber = VirtualMethodSlotHelper.GetVirtualMethodSlot(_compilation.NodeFactory, slot, closestDefType);
+ typeDefinitions.Append(GetCodeForVirtualMethod(slot, slotNumber));
}
if (nodeType.IsDelegate)
@@ -1242,7 +1264,7 @@ namespace ILCompiler.CppCodeGen
typeDefinitions.AppendLine();
AppendCppMethodDeclaration(typeDefinitions, m, false);
typeDefinitions.AppendLine();
- AppendCppMethodDeclaration(typeDefinitions, m, false, null, null, UnboxingStubNode.GetMangledName(factory.NameMangler, m));
+ AppendCppMethodDeclaration(typeDefinitions, m, false, null, null, CppUnboxingStubNode.GetMangledName(factory.NameMangler, m));
}
}
@@ -1274,7 +1296,7 @@ namespace ILCompiler.CppCodeGen
rtrHeader.Append(GetCodeForObjectNode(headerNode, factory));
rtrHeader.AppendLine();
- rtrHeader.Append("void* RtRHeaderWrapper() {");
+ rtrHeader.Append("extern \"C\" void* RtRHeaderWrapper() {");
rtrHeader.Indent();
rtrHeader.AppendLine();
rtrHeader.Append("static struct {");
@@ -1342,13 +1364,13 @@ namespace ILCompiler.CppCodeGen
/// </summary>
/// <param name="unboxingStubNode">The unboxing stub node to be output</param>
/// <param name="methodImplementations">The buffer in which to write out the C++ code</param>
- private void OutputUnboxingStubNode(UnboxingStubNode unboxingStubNode)
+ private void OutputUnboxingStubNode(CppUnboxingStubNode unboxingStubNode)
{
Out.WriteLine();
CppGenerationBuffer sb = new CppGenerationBuffer();
sb.AppendLine();
- AppendCppMethodDeclaration(sb, unboxingStubNode.Method, true, null, null, UnboxingStubNode.GetMangledName(_compilation.NameMangler, unboxingStubNode.Method));
+ AppendCppMethodDeclaration(sb, unboxingStubNode.Method, true, null, null, unboxingStubNode.GetMangledName(_compilation.NameMangler));
sb.AppendLine();
sb.Append("{");
sb.Indent();
@@ -1405,8 +1427,8 @@ namespace ILCompiler.CppCodeGen
{
if (node is CppMethodCodeNode)
OutputMethodNode(node as CppMethodCodeNode);
- else if (node is UnboxingStubNode)
- OutputUnboxingStubNode(node as UnboxingStubNode);
+ else if (node is CppUnboxingStubNode)
+ OutputUnboxingStubNode(node as CppUnboxingStubNode);
}
Out.Dispose();
diff --git a/src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs b/src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs
index ae062dad6..33ab17d76 100644
--- a/src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs
+++ b/src/ILCompiler.CppCodeGen/src/CppCodeGen/ILToCppImporter.cs
@@ -1003,8 +1003,9 @@ namespace Internal.IL
if (IsTypeName(method, "System", "ByReference`1"))
{
var thisRef = _stack.Pop();
-
- PushExpression(StackValueKind.ValueType, ((ExpressionEntry)thisRef).Name + "->_value", method.Signature.ReturnType);
+ PushExpression(StackValueKind.ByRef,
+ String.Concat("(", GetSignatureTypeNameAndAddReference(method.Signature.ReturnType), ")", ((ExpressionEntry)thisRef).Name, "->_value"),
+ method.Signature.ReturnType);
return true;
}
break;
@@ -1151,7 +1152,7 @@ namespace Internal.IL
{
// TODO: Null checks
- if (method.IsVirtual)
+ if (method.IsVirtual && !method.IsFinal && !method.OwningType.IsSealed())
{
// TODO: Full resolution of virtual methods
if (!method.IsNewSlot)
@@ -2613,7 +2614,8 @@ namespace Internal.IL
private void ImportUnalignedPrefix(byte alignment)
{
- throw new NotImplementedException();
+ // TODO:
+ // throw new NotImplementedException();
}
private void ImportVolatilePrefix()
diff --git a/src/ILCompiler.CppCodeGen/src/ILCompiler.CppCodeGen.csproj b/src/ILCompiler.CppCodeGen/src/ILCompiler.CppCodeGen.csproj
index 1ef83f8bd..80a2a51f2 100644
--- a/src/ILCompiler.CppCodeGen/src/ILCompiler.CppCodeGen.csproj
+++ b/src/ILCompiler.CppCodeGen/src/ILCompiler.CppCodeGen.csproj
@@ -32,6 +32,7 @@
<Compile Include="Compiler\CppNodeMangler.cs" />
<Compile Include="Compiler\CppCodegenCompilation.cs" />
<Compile Include="Compiler\CppCodegenCompilationBuilder.cs" />
+ <Compile Include="Compiler\DependencyAnalysis\CppUnboxingStubNode.cs" />
<Compile Include="CppCodeGen\DependencyNodeIterator.cs" />
<Compile Include="CppCodeGen\EvaluationStack.cs" />
<Compile Include="CppCodeGen\CppGenerationBuffer.cs" />
diff --git a/src/ILCompiler.DependencyAnalysisFramework/tests/DependencyAnalysisFrameworkTests.cs b/src/ILCompiler.DependencyAnalysisFramework/tests/DependencyAnalysisFrameworkTests.cs
index 390299940..3b9cfc80e 100644
--- a/src/ILCompiler.DependencyAnalysisFramework/tests/DependencyAnalysisFrameworkTests.cs
+++ b/src/ILCompiler.DependencyAnalysisFramework/tests/DependencyAnalysisFrameworkTests.cs
@@ -50,8 +50,8 @@ namespace ILCompiler.DependencyAnalysisFramework.Tests
testGraph.AddRoot("A", "A is root");
List<string> results = testGraph.AnalysisResults;
- Assert.True(results.Contains("A"));
- Assert.True(results.Contains("B"));
+ Assert.Contains("A", results);
+ Assert.Contains("B", results);
});
}
@@ -64,9 +64,9 @@ namespace ILCompiler.DependencyAnalysisFramework.Tests
testGraph.AddRoot("A", "A is root");
List<string> results = testGraph.AnalysisResults;
- Assert.True(results.Contains("A"));
- Assert.False(results.Contains("B"));
- Assert.False(results.Contains("C"));
+ Assert.Contains("A", results);
+ Assert.DoesNotContain("B", results);
+ Assert.DoesNotContain("C", results);
Assert.True(results.Count == 1);
});
}
@@ -81,9 +81,9 @@ namespace ILCompiler.DependencyAnalysisFramework.Tests
testGraph.AddRoot("C", "C is root");
List<string> results = testGraph.AnalysisResults;
- Assert.True(results.Contains("A"));
- Assert.True(results.Contains("B"));
- Assert.True(results.Contains("C"));
+ Assert.Contains("A", results);
+ Assert.Contains("B", results);
+ Assert.Contains("C", results);
Assert.True(results.Count == 3);
});
}
diff --git a/src/ILCompiler.DependencyAnalysisFramework/tests/ILCompiler.DependencyAnalysisFramework.Tests.csproj b/src/ILCompiler.DependencyAnalysisFramework/tests/ILCompiler.DependencyAnalysisFramework.Tests.csproj
index 37f6e2a40..a352c7c0c 100644
--- a/src/ILCompiler.DependencyAnalysisFramework/tests/ILCompiler.DependencyAnalysisFramework.Tests.csproj
+++ b/src/ILCompiler.DependencyAnalysisFramework/tests/ILCompiler.DependencyAnalysisFramework.Tests.csproj
@@ -4,7 +4,7 @@
<OutputType>Library</OutputType>
<AssemblyName>ILCompiler.DependencyAnalysisFramework.Tests</AssemblyName>
<RootNamespace>ILCompiler.DependencyAnalysisFramework.Tests</RootNamespace>
- <TargetFramework>netstandard1.3</TargetFramework>
+ <TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\src\ILCompiler.DependencyAnalysisFramework.csproj" />
@@ -13,8 +13,11 @@
<PackageReference Include="System.Collections.Immutable">
<Version>1.3.1</Version>
</PackageReference>
- <PackageReference Include="Microsoft.DotNet.BuildTools.TestSuite">
- <Version>$(XunitNetcoreExtensionsVersion)</Version>
+ <PackageReference Include="xunit">
+ <Version>$(XUnitPackageVersion)</Version>
+ </PackageReference>
+ <PackageReference Include="Microsoft.DotNet.XUnitExtensions">
+ <Version>$(MicrosoftDotNetXUnitExtensionsVersion)</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
diff --git a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.CustomAttribute.cs b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.CustomAttribute.cs
index ecf9532e7..31f61c5e8 100644
--- a/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.CustomAttribute.cs
+++ b/src/ILCompiler.MetadataTransform/src/ILCompiler/Metadata/Transform.CustomAttribute.cs
@@ -117,14 +117,14 @@ namespace ILCompiler.Metadata
return new ConstantUInt64Value { Value = (ulong)value };
}
- if (type.IsString)
+ if (value == null)
{
- return HandleString((string)value);
+ return new ConstantReferenceValue();
}
- if (value == null)
+ if (type.IsString)
{
- return new ConstantReferenceValue();
+ return HandleString((string)value);
}
if (type.IsSzArray)
diff --git a/src/ILCompiler.MetadataTransform/tests/ExplicitScopeTests.cs b/src/ILCompiler.MetadataTransform/tests/ExplicitScopeTests.cs
index 6745b23ee..dad6f4e73 100644
--- a/src/ILCompiler.MetadataTransform/tests/ExplicitScopeTests.cs
+++ b/src/ILCompiler.MetadataTransform/tests/ExplicitScopeTests.cs
@@ -57,7 +57,7 @@ namespace MetadataTransformTests
return scope;
}
- public void CheckTypeDefinitionForProperWinRTHome(TypeDefinition typeDefinition, string module)
+ private void CheckTypeDefinitionForProperWinRTHome(TypeDefinition typeDefinition, string module)
{
ScopeDefinition scope = GetScopeDefinitionOfType(typeDefinition);
Assert.Equal(module, scope.Name.Value);
@@ -66,7 +66,7 @@ namespace MetadataTransformTests
}
- public void CheckTypeReferenceForProperWinRTHome(TypeReference typeReference, string module)
+ private void CheckTypeReferenceForProperWinRTHome(TypeReference typeReference, string module)
{
ScopeReference scope = GetScopeReferenceOfType(typeReference);
Assert.Equal(module, scope.Name.Value);
diff --git a/src/ILCompiler.MetadataTransform/tests/ILCompiler.MetadataTransform.Tests.csproj b/src/ILCompiler.MetadataTransform/tests/ILCompiler.MetadataTransform.Tests.csproj
index 9de4e1df7..1a3d8e52a 100644
--- a/src/ILCompiler.MetadataTransform/tests/ILCompiler.MetadataTransform.Tests.csproj
+++ b/src/ILCompiler.MetadataTransform/tests/ILCompiler.MetadataTransform.Tests.csproj
@@ -4,11 +4,14 @@
<OutputType>Library</OutputType>
<AssemblyName>ILCompiler.MetadataTransform.Tests</AssemblyName>
<RootNamespace>MetadataTransformTests</RootNamespace>
- <TargetFramework>netstandard1.3</TargetFramework>
+ <TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.DotNet.BuildTools.TestSuite">
- <Version>$(XunitNetcoreExtensionsVersion)</Version>
+ <PackageReference Include="xunit">
+ <Version>$(XUnitPackageVersion)</Version>
+ </PackageReference>
+ <PackageReference Include="Microsoft.DotNet.XUnitExtensions">
+ <Version>$(MicrosoftDotNetXUnitExtensionsVersion)</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
diff --git a/src/ILCompiler.MetadataTransform/tests/ILMetadataAssembly/ILMetadataAssembly.ilproj b/src/ILCompiler.MetadataTransform/tests/ILMetadataAssembly/ILMetadataAssembly.ilproj
index 8e383e067..63712c1f4 100644
--- a/src/ILCompiler.MetadataTransform/tests/ILMetadataAssembly/ILMetadataAssembly.ilproj
+++ b/src/ILCompiler.MetadataTransform/tests/ILMetadataAssembly/ILMetadataAssembly.ilproj
@@ -5,7 +5,7 @@
<PropertyGroup>
<OutputType>Library</OutputType>
<AssemblyName>ILMetadataAssembly</AssemblyName>
- <RunTestsForProject>false</RunTestsForProject>
+ <SkipTestRun>true</SkipTestRun>
</PropertyGroup>
<ItemGroup>
diff --git a/src/ILCompiler.MetadataTransform/tests/PrimaryMetadataAssembly/PrimaryMetadataAssembly.csproj b/src/ILCompiler.MetadataTransform/tests/PrimaryMetadataAssembly/PrimaryMetadataAssembly.csproj
index 82b325adf..a64f83430 100644
--- a/src/ILCompiler.MetadataTransform/tests/PrimaryMetadataAssembly/PrimaryMetadataAssembly.csproj
+++ b/src/ILCompiler.MetadataTransform/tests/PrimaryMetadataAssembly/PrimaryMetadataAssembly.csproj
@@ -5,7 +5,7 @@
<AssemblyName>PrimaryMetadataAssembly</AssemblyName>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<IsCoreAssembly>true</IsCoreAssembly>
- <RunTestsForProject>false</RunTestsForProject>
+ <SkipTestRun>true</SkipTestRun>
</PropertyGroup>
<ItemGroup>
<Compile Include="Platform.cs" />
diff --git a/src/ILCompiler.MetadataTransform/tests/SampleMetadataAssembly/SampleMetadataAssembly.csproj b/src/ILCompiler.MetadataTransform/tests/SampleMetadataAssembly/SampleMetadataAssembly.csproj
index 04ff2298d..796a387b6 100644
--- a/src/ILCompiler.MetadataTransform/tests/SampleMetadataAssembly/SampleMetadataAssembly.csproj
+++ b/src/ILCompiler.MetadataTransform/tests/SampleMetadataAssembly/SampleMetadataAssembly.csproj
@@ -4,7 +4,7 @@
<OutputType>Library</OutputType>
<AssemblyName>SampleMetadataAssembly</AssemblyName>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
- <RunTestsForProject>false</RunTestsForProject>
+ <SkipTestRun>true</SkipTestRun>
</PropertyGroup>
<ItemGroup>
diff --git a/src/ILCompiler.MetadataTransform/tests/SampleWinRTMetadataAssembly/SampleWinRTMetadataAssembly.csproj b/src/ILCompiler.MetadataTransform/tests/SampleWinRTMetadataAssembly/SampleWinRTMetadataAssembly.csproj
index 514982407..e228feb1f 100644
--- a/src/ILCompiler.MetadataTransform/tests/SampleWinRTMetadataAssembly/SampleWinRTMetadataAssembly.csproj
+++ b/src/ILCompiler.MetadataTransform/tests/SampleWinRTMetadataAssembly/SampleWinRTMetadataAssembly.csproj
@@ -4,7 +4,7 @@
<OutputType>Library</OutputType>
<AssemblyName>SampleWinRTMetadataAssembly</AssemblyName>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
- <RunTestsForProject>false</RunTestsForProject>
+ <SkipTestRun>true</SkipTestRun>
</PropertyGroup>
<ItemGroup>
diff --git a/src/ILCompiler.MetadataTransform/tests/SimpleTests.cs b/src/ILCompiler.MetadataTransform/tests/SimpleTests.cs
index b1d6d06a6..e3035321e 100644
--- a/src/ILCompiler.MetadataTransform/tests/SimpleTests.cs
+++ b/src/ILCompiler.MetadataTransform/tests/SimpleTests.cs
@@ -10,6 +10,8 @@ using Cts = Internal.TypeSystem;
using Xunit;
+#pragma warning disable xUnit2013 // Do not use Assert.Equal() to check for collection size
+
namespace MetadataTransformTests
{
public class SimpleTests
diff --git a/src/ILCompiler.MetadataTransform/tests/WindowsWinRTMetadataAssembly/WindowsWinRTMetadataAssembly.csproj b/src/ILCompiler.MetadataTransform/tests/WindowsWinRTMetadataAssembly/WindowsWinRTMetadataAssembly.csproj
index d6f36ace1..05853a005 100644
--- a/src/ILCompiler.MetadataTransform/tests/WindowsWinRTMetadataAssembly/WindowsWinRTMetadataAssembly.csproj
+++ b/src/ILCompiler.MetadataTransform/tests/WindowsWinRTMetadataAssembly/WindowsWinRTMetadataAssembly.csproj
@@ -4,7 +4,7 @@
<OutputType>Library</OutputType>
<AssemblyName>WindowsWinRTMetadataAssembly</AssemblyName>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
- <RunTestsForProject>false</RunTestsForProject>
+ <SkipTestRun>true</SkipTestRun>
</PropertyGroup>
<ItemGroup>
diff --git a/src/ILCompiler.MetadataWriter/src/Internal/Metadata/NativeFormat/Writer/NativeFormatWriterGen.cs b/src/ILCompiler.MetadataWriter/src/Internal/Metadata/NativeFormat/Writer/NativeFormatWriterGen.cs
index d503e858e..d4e199c70 100644
--- a/src/ILCompiler.MetadataWriter/src/Internal/Metadata/NativeFormat/Writer/NativeFormatWriterGen.cs
+++ b/src/ILCompiler.MetadataWriter/src/Internal/Metadata/NativeFormat/Writer/NativeFormatWriterGen.cs
@@ -2807,7 +2807,8 @@ namespace Internal.Metadata.NativeFormat.Writer
Debug.Assert(Constraints.TrueForAll(handle => handle == null ||
handle.HandleType == HandleType.TypeDefinition ||
handle.HandleType == HandleType.TypeReference ||
- handle.HandleType == HandleType.TypeSpecification));
+ handle.HandleType == HandleType.TypeSpecification ||
+ handle.HandleType == HandleType.ModifiedType));
writer.Write(Constraints);
writer.Write(CustomAttributes);
} // Save
diff --git a/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj b/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj
index c9b2ef2bf..ec7b134e6 100644
--- a/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj
+++ b/src/ILCompiler.TypeSystem/src/ILCompiler.TypeSystem.csproj
@@ -82,6 +82,9 @@
<Compile Include="..\..\Common\src\TypeSystem\CodeGen\TargetDetails.CodeGen.cs">
<Link>TypeSystem\CodeGen\TargetDetails.CodeGen.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\src\TypeSystem\CodeGen\TypeDesc.CodeGen.cs">
+ <Link>TypeSystem\CodeGen\TypeDesc.CodeGen.cs</Link>
+ </Compile>
<Compile Include="..\..\Common\src\TypeSystem\Common\AlignmentHelper.cs">
<Link>Utilities\AlignmentHelper.cs</Link>
</Compile>
@@ -355,12 +358,15 @@
<Compile Include="..\..\Common\src\TypeSystem\IL\DelegateInfo.cs">
<Link>IL\DelegateInfo.cs</Link>
</Compile>
- <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DelegateMarshallingMethodThunk.Sorting.cs">
- <Link>IL\Stubs\DelegateMarshallingMethodThunk.Sorting.cs</Link>
- </Compile>
<Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DelegateThunks.Sorting.cs">
<Link>IL\Stubs\DelegateThunks.Sorting.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DynamicInvokeMethodThunk.cs">
+ <Link>IL\Stubs\DynamicInvokeMethodThunk.cs</Link>
+ </Compile>
+ <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DynamicInvokeMethodThunk.Sorting.cs">
+ <Link>IL\Stubs\DynamicInvokeMethodThunk.Sorting.cs</Link>
+ </Compile>
<Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\EnumThunks.cs">
<Link>IL\Stubs\EnumThunks.cs</Link>
</Compile>
@@ -388,6 +394,15 @@
<Compile Include="..\..\Common\src\TypeSystem\IL\TypeSystemContext.DelegateInfo.cs">
<Link>IL\TypeSystemContext.DelegateInfo.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\src\TypeSystem\IL\TypeSystemContext.DynamicInvoke.cs">
+ <Link>IL\TypeSystemContext.DynamicInvoke.cs</Link>
+ </Compile>
+ <Compile Include="..\..\Common\src\TypeSystem\IL\TypeSystemContext.GeneratedAssembly.cs">
+ <Link>IL\TypeSystemContext.GeneratedAssembly.cs</Link>
+ </Compile>
+ <Compile Include="..\..\Common\src\TypeSystem\IL\TypeSystemContext.GeneratedAssembly.Sorting.cs">
+ <Link>IL\TypeSystemContext.GeneratedAssembly.Sorting.cs</Link>
+ </Compile>
<Compile Include="..\..\Common\src\TypeSystem\IL\EcmaMethodIL.cs">
<Link>IL\EcmaMethodIL.cs</Link>
</Compile>
@@ -457,12 +472,24 @@
<Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DebuggerSteppingHelpers.cs">
<Link>IL\Stubs\DebuggerSteppingHelpers.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\CalliMarshallingMethodThunk.cs">
+ <Link>IL\Stubs\CalliMarshallingMethodThunk.cs</Link>
+ </Compile>
+ <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\CalliMarshallingMethodThunk.Mangling.cs">
+ <Link>IL\Stubs\CalliMarshallingMethodThunk.Mangling.cs</Link>
+ </Compile>
+ <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\CalliMarshallingMethodThunk.Sorting.cs">
+ <Link>IL\Stubs\CalliMarshallingMethodThunk.Sorting.cs</Link>
+ </Compile>
<Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DelegateMarshallingMethodThunk.cs">
<Link>IL\Stubs\DelegateMarshallingMethodThunk.cs</Link>
</Compile>
<Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DelegateMarshallingMethodThunk.Mangling.cs">
<Link>IL\Stubs\DelegateMarshallingMethodThunk.Mangling.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DelegateMarshallingMethodThunk.Sorting.cs">
+ <Link>IL\Stubs\DelegateMarshallingMethodThunk.Sorting.cs</Link>
+ </Compile>
<Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\ForwardDelegateCreationThunk.cs">
<Link>IL\Stubs\ForwardDelegateCreationThunk.cs</Link>
</Compile>
@@ -544,6 +571,9 @@
<Compile Include="..\..\Common\src\TypeSystem\Mangling\IPrefixMangledType.cs">
<Link>TypeSystem\Mangling\IPrefixMangledType.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\src\TypeSystem\Mangling\IPrefixMangledSignature.cs">
+ <Link>TypeSystem\Mangling\IPrefixMangledSignature.cs</Link>
+ </Compile>
<Compile Include="..\..\Common\src\System\Collections\Generic\ArrayBuilder.cs">
<Link>Utilities\ArrayBuilder.cs</Link>
</Compile>
diff --git a/src/ILCompiler.TypeSystem/src/Utilities/UniqueTypeNameFormatter.cs b/src/ILCompiler.TypeSystem/src/Utilities/UniqueTypeNameFormatter.cs
index 62d4cc411..5da415a46 100644
--- a/src/ILCompiler.TypeSystem/src/Utilities/UniqueTypeNameFormatter.cs
+++ b/src/ILCompiler.TypeSystem/src/Utilities/UniqueTypeNameFormatter.cs
@@ -120,7 +120,7 @@ namespace Internal.TypeSystem
protected override void AppendNameForNestedType(StringBuilder sb, DefType nestedType, DefType containingType)
{
- AppendNameForNamespaceType(sb, containingType);
+ AppendName(sb, containingType);
sb.Append('+');
diff --git a/src/ILCompiler.TypeSystem/tests/CoreTestAssembly/CoreTestAssembly.csproj b/src/ILCompiler.TypeSystem/tests/CoreTestAssembly/CoreTestAssembly.csproj
index 447bf566f..efdb81aa4 100644
--- a/src/ILCompiler.TypeSystem/tests/CoreTestAssembly/CoreTestAssembly.csproj
+++ b/src/ILCompiler.TypeSystem/tests/CoreTestAssembly/CoreTestAssembly.csproj
@@ -5,7 +5,7 @@
<AssemblyName>CoreTestAssembly</AssemblyName>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<IsCoreAssembly>true</IsCoreAssembly>
- <RunTestsForProject>false</RunTestsForProject>
+ <SkipTestRun>true</SkipTestRun>
</PropertyGroup>
<ItemGroup>
<Compile Include="Canonicalization.cs" />
diff --git a/src/ILCompiler.TypeSystem/tests/GCPointerMapTests.cs b/src/ILCompiler.TypeSystem/tests/GCPointerMapTests.cs
index cc075cc12..7193a800b 100644
--- a/src/ILCompiler.TypeSystem/tests/GCPointerMapTests.cs
+++ b/src/ILCompiler.TypeSystem/tests/GCPointerMapTests.cs
@@ -35,19 +35,19 @@ namespace TypeSystemTests
{
var map = GCPointerMap.FromInstanceLayout(classWithArrayFields);
- Assert.Equal(map.Size, 3);
+ Assert.Equal(3, map.Size);
Assert.Equal("011", map.ToString());
}
{
var map = GCPointerMap.FromInstanceLayout(classWithStringField);
- Assert.Equal(map.Size, 4);
+ Assert.Equal(4, map.Size);
Assert.Equal("0010", map.ToString());
}
{
var map = GCPointerMap.FromInstanceLayout(mixedStruct);
- Assert.Equal(map.Size, 5);
+ Assert.Equal(5, map.Size);
Assert.Equal("01001", map.ToString());
}
@@ -60,19 +60,19 @@ namespace TypeSystemTests
{
var map = GCPointerMap.FromInstanceLayout(doubleMixedStructLayout);
- Assert.Equal(map.Size, 10);
+ Assert.Equal(10, map.Size);
Assert.Equal("0100101001", map.ToString());
}
{
var map = GCPointerMap.FromInstanceLayout(explicitlyFarPointer);
- Assert.Equal(map.Size, 117);
+ Assert.Equal(117, map.Size);
Assert.Equal("100000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000000000000000000001001", map.ToString());
}
{
var map = GCPointerMap.FromInstanceLayout(struct32GcPointers);
- Assert.Equal(map.Size, 32);
+ Assert.Equal(32, map.Size);
Assert.Equal("11111111111111111111111111111111", map.ToString());
}
}
@@ -82,20 +82,17 @@ namespace TypeSystemTests
{
MetadataType mixedStaticClass = _testModule.GetType("GCPointerMap", "MixedStaticClass");
var map = GCPointerMap.FromStaticLayout(mixedStaticClass);
- Assert.Equal(map.Size, 12);
+ Assert.Equal(12, map.Size);
Assert.Equal("010100101001", map.ToString());
}
-#if false
- // TODO: enable when IsThreadStatic stops lying
[Fact]
public void TestThreadStaticMap()
{
MetadataType mixedThreadStaticClass = _testModule.GetType("GCPointerMap", "MixedThreadStaticClass");
var map = GCPointerMap.FromThreadStaticLayout(mixedThreadStaticClass);
- Assert.Equal(map.Size, 14);
+ Assert.Equal(14, map.Size);
Assert.Equal("00010010100110", map.ToString());
}
-#endif
}
}
diff --git a/src/ILCompiler.TypeSystem/tests/GenericTypeAndMethodTests.cs b/src/ILCompiler.TypeSystem/tests/GenericTypeAndMethodTests.cs
index 66698ff0b..ddfe97e26 100644
--- a/src/ILCompiler.TypeSystem/tests/GenericTypeAndMethodTests.cs
+++ b/src/ILCompiler.TypeSystem/tests/GenericTypeAndMethodTests.cs
@@ -33,8 +33,7 @@ namespace TypeSystemTests
// Verify that we get just type definitions.
Assert.NotNull(t);
Assert.True(t.IsTypeDefinition);
- Assert.NotNull(t.Instantiation);
- Assert.Equal(t.Instantiation.Length, 1);
+ Assert.Equal(1, t.Instantiation.Length);
Assert.True(t.Instantiation[0].IsTypeDefinition);
// Verify that we got a method definition
@@ -50,14 +49,13 @@ namespace TypeSystemTests
// Verify properties of the instantiated type
Assert.NotNull(instantiatedType);
Assert.False(instantiatedType.IsTypeDefinition);
- Assert.NotNull(instantiatedType.Instantiation);
- Assert.Equal(instantiatedType.Instantiation.Length, 1);
- Assert.Equal(instantiatedType.Instantiation[0], _context.GetWellKnownType(WellKnownType.Int32));
+ Assert.Equal(1, instantiatedType.Instantiation.Length);
+ Assert.Equal(_context.GetWellKnownType(WellKnownType.Int32), instantiatedType.Instantiation[0]);
// Verify that we get an instantiated method with the proper signature
MethodDesc fooInstantiatedMethod = instantiatedType.GetMethods().First(m => m.Name == "Foo");
Assert.False(fooInstantiatedMethod.IsTypicalMethodDefinition);
- Assert.Equal(fooInstantiatedMethod.Signature.ReturnType, _context.GetWellKnownType(WellKnownType.Int32));
+ Assert.Equal(_context.GetWellKnownType(WellKnownType.Int32), fooInstantiatedMethod.Signature.ReturnType);
Assert.Same(fooInstantiatedMethod.GetTypicalMethodDefinition(), fooMethod);
// This is not a generic method, so they should be the same
Assert.Same(fooInstantiatedMethod.GetMethodDefinition(), fooInstantiatedMethod);
@@ -137,16 +135,16 @@ namespace TypeSystemTests
InstantiatedType genericOfIntString = genericOpenType.MakeInstantiatedType(intType, stringType);
InstantiatedType genericOfIntObject = genericOpenType.MakeInstantiatedType(intType, objectType);
- Assert.Equal(true, genericOfCharObject.IsConstructedOverType(new TypeDesc[] { charType }));
- Assert.Equal(true, genericOfCharObject.IsConstructedOverType(new TypeDesc[] { objectType }));
- Assert.Equal(false, genericOfCharObject.IsConstructedOverType(new TypeDesc[] { intType }));
- Assert.Equal(false, genericOfCharObject.IsConstructedOverType(new TypeDesc[] { stringType }));
- Assert.Equal(false, genericOfCharObject.IsConstructedOverType(new TypeDesc[] { genericOpenType }));
+ Assert.True(genericOfCharObject.IsConstructedOverType(new TypeDesc[] { charType }));
+ Assert.True(genericOfCharObject.IsConstructedOverType(new TypeDesc[] { objectType }));
+ Assert.False(genericOfCharObject.IsConstructedOverType(new TypeDesc[] { intType }));
+ Assert.False(genericOfCharObject.IsConstructedOverType(new TypeDesc[] { stringType }));
+ Assert.False(genericOfCharObject.IsConstructedOverType(new TypeDesc[] { genericOpenType }));
- Assert.Equal(true, genericOfCharString.IsConstructedOverType(new TypeDesc[] { charType }));
- Assert.Equal(false, genericOfCharString.IsConstructedOverType(new TypeDesc[] { objectType }));
- Assert.Equal(false, genericOfCharString.IsConstructedOverType(new TypeDesc[] { intType }));
- Assert.Equal(true, genericOfCharString.IsConstructedOverType(new TypeDesc[] { stringType }));
+ Assert.True(genericOfCharString.IsConstructedOverType(new TypeDesc[] { charType }));
+ Assert.False(genericOfCharString.IsConstructedOverType(new TypeDesc[] { objectType }));
+ Assert.False(genericOfCharString.IsConstructedOverType(new TypeDesc[] { intType }));
+ Assert.True(genericOfCharString.IsConstructedOverType(new TypeDesc[] { stringType }));
// Test direct replacement
TypeDesc testDirectReplaceAllTypes = genericOfCharObject.ReplaceTypesInConstructionOfType(new TypeDesc[] { charType, objectType }, new TypeDesc[] { intType, stringType });
@@ -197,8 +195,8 @@ namespace TypeSystemTests
TypeDesc testReplaceTypeInPointer = charPointer.ReplaceTypesInConstructionOfType(new TypeDesc[] { charType }, new TypeDesc[] { intType });
Assert.Equal(intPointer, testReplaceTypeInPointer);
- Assert.Equal(true, charPointer.IsConstructedOverType(new TypeDesc[] { charType }));
- Assert.Equal(false, charPointer.IsConstructedOverType(new TypeDesc[] { intType }));
+ Assert.True(charPointer.IsConstructedOverType(new TypeDesc[] { charType }));
+ Assert.False(charPointer.IsConstructedOverType(new TypeDesc[] { intType }));
// Test byref
TypeDesc charByRef = _context.GetByRefType(charType);
@@ -206,13 +204,13 @@ namespace TypeSystemTests
TypeDesc testReplaceTypeInByRef = charByRef.ReplaceTypesInConstructionOfType(new TypeDesc[] { charType }, new TypeDesc[] { intType });
Assert.Equal(intByRef, testReplaceTypeInByRef);
- Assert.Equal(true, charByRef.IsConstructedOverType(new TypeDesc[] { charType }));
- Assert.Equal(false, charByRef.IsConstructedOverType(new TypeDesc[] { intType }));
+ Assert.True(charByRef.IsConstructedOverType(new TypeDesc[] { charType }));
+ Assert.False(charByRef.IsConstructedOverType(new TypeDesc[] { intType }));
// Test replace type entirely
TypeDesc testReplaceTypeEntirely = charByRef.ReplaceTypesInConstructionOfType(new TypeDesc[] { charByRef }, new TypeDesc[] { intByRef });
Assert.Equal(intByRef, testReplaceTypeEntirely);
- Assert.Equal(true, charByRef.IsConstructedOverType(new TypeDesc[] { charByRef }));
+ Assert.True(charByRef.IsConstructedOverType(new TypeDesc[] { charByRef }));
}
[Fact]
@@ -273,4 +271,4 @@ namespace TypeSystemTests
Assert.Equal(getMethodOnMDCharArray, testArrayMethodCase);
}
}
-} \ No newline at end of file
+}
diff --git a/src/ILCompiler.TypeSystem/tests/ILTestAssembly/ILTestAssembly.ilproj b/src/ILCompiler.TypeSystem/tests/ILTestAssembly/ILTestAssembly.ilproj
index 5d65099c4..bce9574f9 100644
--- a/src/ILCompiler.TypeSystem/tests/ILTestAssembly/ILTestAssembly.ilproj
+++ b/src/ILCompiler.TypeSystem/tests/ILTestAssembly/ILTestAssembly.ilproj
@@ -4,7 +4,7 @@
<PropertyGroup>
<OutputType>Library</OutputType>
<AssemblyName>ILTestAssembly</AssemblyName>
- <RunTestsForProject>false</RunTestsForProject>
+ <SkipTestRun>true</SkipTestRun>
</PropertyGroup>
<ItemGroup>
diff --git a/src/ILCompiler.TypeSystem/tests/TestMetadataFieldLayoutAlgorithm.cs b/src/ILCompiler.TypeSystem/tests/TestMetadataFieldLayoutAlgorithm.cs
index a3dd93a22..ba96e1c7d 100644
--- a/src/ILCompiler.TypeSystem/tests/TestMetadataFieldLayoutAlgorithm.cs
+++ b/src/ILCompiler.TypeSystem/tests/TestMetadataFieldLayoutAlgorithm.cs
@@ -15,7 +15,7 @@ namespace TypeSystemTests
{
// GC statics start with a pointer to the "EEType" that signals the size and GCDesc to the GC
layout.GcStatics.Size = context.Target.LayoutPointerSize;
- layout.ThreadStatics.Size = context.Target.LayoutPointerSize;
+ layout.ThreadGcStatics.Size = context.Target.LayoutPointerSize;
}
protected override void FinalizeRuntimeSpecificStaticFieldLayout(TypeSystemContext context, ref ComputedStaticFieldLayout layout)
@@ -26,9 +26,9 @@ namespace TypeSystemTests
{
layout.GcStatics.Size = LayoutInt.Zero;
}
- if (layout.ThreadStatics.Size == context.Target.LayoutPointerSize)
+ if (layout.ThreadGcStatics.Size == context.Target.LayoutPointerSize)
{
- layout.ThreadStatics.Size = LayoutInt.Zero;
+ layout.ThreadGcStatics.Size = LayoutInt.Zero;
}
}
}
diff --git a/src/ILCompiler.TypeSystem/tests/TestTypeSystemContext.cs b/src/ILCompiler.TypeSystem/tests/TestTypeSystemContext.cs
index 005d98fee..5661b1a87 100644
--- a/src/ILCompiler.TypeSystem/tests/TestTypeSystemContext.cs
+++ b/src/ILCompiler.TypeSystem/tests/TestTypeSystemContext.cs
@@ -110,6 +110,9 @@ namespace TypeSystemTests
{
Debug.Assert(field.IsStatic);
+ if (field.IsThreadStatic)
+ return true;
+
TypeDesc fieldType = field.FieldType;
if (fieldType.IsValueType)
return ((DefType)fieldType).ContainsGCPointers;
diff --git a/src/ILCompiler.TypeSystem/tests/TypeSystem.Tests.csproj b/src/ILCompiler.TypeSystem/tests/TypeSystem.Tests.csproj
index 3c4e78516..cd4d34c18 100644
--- a/src/ILCompiler.TypeSystem/tests/TypeSystem.Tests.csproj
+++ b/src/ILCompiler.TypeSystem/tests/TypeSystem.Tests.csproj
@@ -4,16 +4,16 @@
<OutputType>Library</OutputType>
<AssemblyName>TypeSystem.Tests</AssemblyName>
<RootNamespace>TypeSystem.Tests</RootNamespace>
- <TargetFramework>netstandard1.3</TargetFramework>
+ <TargetFramework>netstandard2.0</TargetFramework>
<!-- Don't warn if some dependencies were rolled forward -->
<NoWarn>$(NoWarn);NU1603</NoWarn>
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.DotNet.BuildTools.TestSuite">
- <Version>$(XunitNetcoreExtensionsVersion)</Version>
+ <PackageReference Include="xunit">
+ <Version>$(XUnitPackageVersion)</Version>
</PackageReference>
- <PackageReference Include="Microsoft.xunit.netcore.extensions">
- <Version>$(XunitNetcoreExtensionsVersion)</Version>
+ <PackageReference Include="Microsoft.DotNet.XUnitExtensions">
+ <Version>$(MicrosoftDotNetXUnitExtensionsVersion)</Version>
</PackageReference>
<PackageReference Include="System.Reflection.Metadata">
<Version>1.4.2</Version>
diff --git a/src/ILCompiler.TypeSystem/tests/UniversalGenericFieldLayoutTests.cs b/src/ILCompiler.TypeSystem/tests/UniversalGenericFieldLayoutTests.cs
index 938828c79..8258cadf9 100644
--- a/src/ILCompiler.TypeSystem/tests/UniversalGenericFieldLayoutTests.cs
+++ b/src/ILCompiler.TypeSystem/tests/UniversalGenericFieldLayoutTests.cs
@@ -200,8 +200,8 @@ namespace TypeSystemTests
Assert.Equal(LayoutInt.Zero, context.UniversalCanonType.GCStaticFieldSize);
Assert.Equal(LayoutInt.Zero, context.UniversalCanonType.NonGCStaticFieldAlignment);
Assert.Equal(LayoutInt.Zero, context.UniversalCanonType.NonGCStaticFieldSize);
- Assert.Equal(LayoutInt.Zero, context.UniversalCanonType.ThreadStaticFieldAlignment);
- Assert.Equal(LayoutInt.Zero, context.UniversalCanonType.ThreadStaticFieldSize);
+ Assert.Equal(LayoutInt.Zero, context.UniversalCanonType.ThreadGcStaticFieldAlignment);
+ Assert.Equal(LayoutInt.Zero, context.UniversalCanonType.ThreadGcStaticFieldSize);
}
[Fact]
public void TestLayoutOfUniversalCanonType()
@@ -268,7 +268,7 @@ namespace TypeSystemTests
Assert.Equal(LayoutInt.Indeterminate, genOfUUU.GetFields().ElementAt(2).Offset);
}
- public void TestIndeterminatedNestedStructFieldPerContext(TypeSystemContext context, ModuleDesc testModule, out InstantiatedType genOfIntNestedInt, out InstantiatedType genOfLongNestedInt)
+ private void TestIndeterminatedNestedStructFieldPerContext(TypeSystemContext context, ModuleDesc testModule, out InstantiatedType genOfIntNestedInt, out InstantiatedType genOfLongNestedInt)
{
// Given a struct with all field universal, what is the layout?
MetadataType tGen = testModule.GetType("GenericTypes", "GenStruct`3");
@@ -310,7 +310,7 @@ namespace TypeSystemTests
Assert.Equal(LayoutInt.Indeterminate, genOfLongNestedInt.InstanceByteAlignment);
}
- public void AssertClassIndeterminateSize(TypeSystemContext context, MetadataType type, LayoutInt expectedIndeterminateByteAlignment)
+ private void AssertClassIndeterminateSize(TypeSystemContext context, MetadataType type, LayoutInt expectedIndeterminateByteAlignment)
{
Assert.Equal(context.Target.LayoutPointerSize, type.InstanceFieldAlignment);
Assert.Equal(context.Target.LayoutPointerSize, type.InstanceFieldSize);
diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/DebugMetadata.cs b/src/ILCompiler.WebAssembly/src/CodeGen/DebugMetadata.cs
new file mode 100644
index 000000000..30780db65
--- /dev/null
+++ b/src/ILCompiler.WebAssembly/src/CodeGen/DebugMetadata.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using LLVMSharp;
+
+namespace ILCompiler.WebAssembly
+{
+ class DebugMetadata
+ {
+ public DebugMetadata(LLVMMetadataRef file, LLVMMetadataRef compileUnit)
+ {
+ File = file;
+ CompileUnit = compileUnit;
+ }
+
+ public LLVMMetadataRef CompileUnit { get; }
+ public LLVMMetadataRef File { get; }
+ }
+}
diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/EvaluationStack.cs b/src/ILCompiler.WebAssembly/src/CodeGen/EvaluationStack.cs
index 92c191976..44b947ccd 100644
--- a/src/ILCompiler.WebAssembly/src/CodeGen/EvaluationStack.cs
+++ b/src/ILCompiler.WebAssembly/src/CodeGen/EvaluationStack.cs
@@ -199,7 +199,7 @@ namespace Internal.IL
else if (kind == StackValueKind.Int64)
return ValueAsInt64(builder, signExtend);
else if (kind == StackValueKind.Float)
- return ValueAsType(LLVM.FloatType(), builder);
+ return ValueAsType(LLVM.DoubleType(), builder);
else if (kind == StackValueKind.NativeInt || kind == StackValueKind.ByRef || kind == StackValueKind.ObjRef)
return ValueAsInt32(builder, false);
else
@@ -239,7 +239,7 @@ namespace Internal.IL
/// Create a new copy of current entry.
/// </summary>
/// <returns>A new instance of the same type as the current entry.</returns>
- public abstract StackEntry Duplicate();
+ public abstract StackEntry Duplicate(LLVMBuilderRef builder);
}
/// <summary>
@@ -298,7 +298,7 @@ namespace Internal.IL
}
}
- public override StackEntry Duplicate()
+ public override StackEntry Duplicate(LLVMBuilderRef builder)
{
return new Int32ConstantEntry(Value, Type);
}
@@ -333,7 +333,7 @@ namespace Internal.IL
{
}
- public override StackEntry Duplicate()
+ public override StackEntry Duplicate(LLVMBuilderRef builder)
{
return new Int64ConstantEntry(Value, Type);
}
@@ -397,7 +397,7 @@ namespace Internal.IL
return LLVM.ConstReal(type, Value);
}
- public override StackEntry Duplicate()
+ public override StackEntry Duplicate(LLVMBuilderRef builder)
{
return new FloatConstantEntry(Value, Type);
}
@@ -425,7 +425,7 @@ namespace Internal.IL
RawLLVMValue = llvmValue;
}
- public override StackEntry Duplicate()
+ public override StackEntry Duplicate(LLVMBuilderRef builder)
{
return new ExpressionEntry(Kind, Name, RawLLVMValue, Type);
}
@@ -433,7 +433,7 @@ namespace Internal.IL
protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend)
{
//TODO: deal with sign extension here
- return ILImporter.CastIfNecessary(builder, RawLLVMValue, type);
+ return ILImporter.CastIfNecessary(builder, RawLLVMValue, type, Name);
}
}
@@ -449,14 +449,14 @@ namespace Internal.IL
{
}
- public override StackEntry Duplicate()
+ public override StackEntry Duplicate(LLVMBuilderRef builder)
{
- return new LoadExpressionEntry(Kind, Name, RawLLVMValue, Type);
+ return new ExpressionEntry(Kind, "duplicate_" + Name, ILImporter.LoadValue(builder, RawLLVMValue, Type, ILImporter.GetLLVMTypeForTypeDesc(Type), false, "load_duplicate_" + Name), Type);
}
protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend)
{
- return ILImporter.LoadValue(builder, RawLLVMValue, Type, type, signExtend);
+ return ILImporter.LoadValue(builder, RawLLVMValue, Type, type, signExtend, $"Load{Name}");
}
}
@@ -472,14 +472,14 @@ namespace Internal.IL
{
}
- public override StackEntry Duplicate()
+ public override StackEntry Duplicate(LLVMBuilderRef builder)
{
- return new LoadExpressionEntry(Kind, Name, RawLLVMValue, Type);
+ return new AddressExpressionEntry(Kind, Name, RawLLVMValue, Type);
}
protected override LLVMValueRef ValueAsTypeInternal(LLVMTypeRef type, LLVMBuilderRef builder, bool signExtend)
{
- return ILImporter.CastIfNecessary(builder, RawLLVMValue, type);
+ return ILImporter.CastIfNecessary(builder, RawLLVMValue, type, Name);
}
}
@@ -501,7 +501,7 @@ namespace Internal.IL
IsVirtual = isVirtual;
}
- public override StackEntry Duplicate()
+ public override StackEntry Duplicate(LLVMBuilderRef builder)
{
return new FunctionPointerEntry(Name, Method, RawLLVMValue, Type, IsVirtual);
}
@@ -519,7 +519,7 @@ namespace Internal.IL
LdToken = token;
}
- public override StackEntry Duplicate()
+ public override StackEntry Duplicate(LLVMBuilderRef builder)
{
return new LdTokenEntry<T>(Kind, Name, LdToken, RawLLVMValue, Type);
}
@@ -529,7 +529,7 @@ namespace Internal.IL
if (RawLLVMValue.Pointer == IntPtr.Zero)
throw new NullReferenceException();
- return ILImporter.CastIfNecessary(builder, RawLLVMValue, type);
+ return ILImporter.CastIfNecessary(builder, RawLLVMValue, type, Name);
}
}
@@ -544,7 +544,7 @@ namespace Internal.IL
{
}
- public override StackEntry Duplicate()
+ public override StackEntry Duplicate(LLVMBuilderRef builder)
{
return this;
}
@@ -576,9 +576,17 @@ namespace Internal.IL
return ILImporter.CastIfNecessary(builder, value, type);
}
- public override StackEntry Duplicate()
+ public override StackEntry Duplicate(LLVMBuilderRef builder)
{
return new SpilledExpressionEntry(Kind, Name, Type, LocalIndex, _importer);
}
}
+
+ internal static class StackEntryExtensions
+ {
+ public static string Name(this StackEntry entry)
+ {
+ return (entry as ExpressionEntry)?.Name;
+ }
+ }
}
diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs
index 8b0936d1e..e828d6d97 100644
--- a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs
+++ b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter.cs
@@ -5,6 +5,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.IO;
+using System.Linq;
using Internal.TypeSystem;
using ILCompiler;
@@ -12,8 +14,8 @@ using LLVMSharp;
using ILCompiler.CodeGen;
using ILCompiler.DependencyAnalysis;
using ILCompiler.DependencyAnalysisFramework;
+using ILCompiler.WebAssembly;
using Internal.TypeSystem.Ecma;
-using System.Linq;
namespace Internal.IL
{
@@ -35,6 +37,7 @@ namespace Internal.IL
}
public LLVMModuleRef Module { get; }
+ public LLVMContextRef Context { get; }
private readonly MethodDesc _method;
private readonly MethodIL _methodIL;
private readonly MethodSignature _signature;
@@ -44,17 +47,20 @@ namespace Internal.IL
private LLVMBasicBlockRef _curBasicBlock;
private LLVMBuilderRef _builder;
private readonly LocalVariableDefinition[] _locals;
+ private readonly LLVMValueRef[] _localSlots;
+ private readonly LLVMValueRef[] _argSlots;
private List<SpilledExpressionEntry> _spilledExpressions = new List<SpilledExpressionEntry>();
private int _pointerSize;
private readonly byte[] _ilBytes;
+ private MethodDebugInformation _debugInformation;
+ private LLVMMetadataRef _debugFunction;
+ private TypeDesc _constrainedType = null;
/// <summary>
/// Stack of values pushed onto the IL stack: locals, arguments, values, function pointer, ...
/// </summary>
private EvaluationStack<StackEntry> _stack = new EvaluationStack<StackEntry>(0);
-
- LLVMTypeRef _universalSignature = LLVM.FunctionType(LLVM.VoidType(), new LLVMTypeRef[] { LLVM.PointerType(LLVM.Int8Type(), 0), LLVM.PointerType(LLVM.Int8Type(), 0) }, false);
-
+
private class BasicBlock
{
// Common fields
@@ -92,6 +98,8 @@ namespace Internal.IL
_methodIL = methodIL;
_ilBytes = methodIL.GetILBytes();
_locals = methodIL.GetLocals();
+ _localSlots = new LLVMValueRef[_locals.Length];
+ _argSlots = new LLVMValueRef[method.Signature.Length];
_signature = method.Signature;
_thisType = method.OwningType;
@@ -101,15 +109,21 @@ namespace Internal.IL
{
_exceptionRegions[i] = new ExceptionRegion() { ILRegion = ilExceptionRegions[i] };
}
- _llvmFunction = GetOrCreateLLVMFunction(mangledName);
+ _llvmFunction = GetOrCreateLLVMFunction(mangledName, method.Signature);
_builder = LLVM.CreateBuilder();
_pointerSize = compilation.NodeFactory.Target.PointerSize;
+
+ _debugInformation = _compilation.GetDebugInfo(_methodIL);
+
+ Context = LLVM.GetModuleContext(Module);
}
public void Import()
{
FindBasicBlocks();
+ GenerateProlog();
+
try
{
ImportBasicBlocks();
@@ -130,53 +144,182 @@ namespace Internal.IL
LLVM.PositionBuilderAtEnd(_builder, trapBlock);
EmitTrapCall();
- LLVM.BuildRetVoid(_builder);
throw;
}
finally
{
// Generate thunk for runtime exports
- if (_method.IsRuntimeExport)
+ if (_method.IsRuntimeExport || _method.IsNativeCallable)
{
- EmitNativeToManagedThunk(_compilation, _method, ((EcmaMethod)_method).GetRuntimeExportName(), _llvmFunction);
+ EcmaMethod ecmaMethod = ((EcmaMethod)_method);
+ string exportName = ecmaMethod.IsRuntimeExport ? ecmaMethod.GetRuntimeExportName() : ecmaMethod.GetNativeCallableExportName();
+ if (exportName == null)
+ {
+ exportName = ecmaMethod.Name;
+ }
+
+ EmitNativeToManagedThunk(_compilation, _method, exportName, _llvmFunction);
}
}
}
private void GenerateProlog()
{
- if (!_methodIL.IsInitLocals)
+ LLVMBasicBlockRef prologBlock = LLVM.AppendBasicBlock(_llvmFunction, "Prolog");
+ LLVM.PositionBuilderAtEnd(_builder, prologBlock);
+
+ // Copy arguments onto the stack to allow
+ // them to be referenced by address
+ int thisOffset = 0;
+ if (!_signature.IsStatic)
{
- return;
+ thisOffset = 1;
+ }
+
+ // Keep track of where we are in the llvm signature, starting after the
+ // shadow stack pointer and return adress
+ int signatureIndex = 1;
+ if (NeedsReturnStackSlot(_signature))
+ {
+ signatureIndex++;
+ }
+
+ string[] argNames = null;
+ if (_debugInformation != null)
+ {
+ argNames = _debugInformation.GetParameterNames()?.ToArray();
+ }
+
+ for (int i = 0; i < _signature.Length; i++)
+ {
+ if (CanStoreTypeOnStack(_signature[i]))
+ {
+ string argName = String.Empty;
+ if (argNames != null && argNames[i] != null)
+ {
+ argName = argNames[i] + "_";
+ }
+ argName += $"arg{i + thisOffset}_";
+
+ LLVMValueRef argStackSlot = LLVM.BuildAlloca(_builder, GetLLVMTypeForTypeDesc(_signature[i]), argName);
+ LLVM.BuildStore(_builder, LLVM.GetParam(_llvmFunction, (uint)signatureIndex), argStackSlot);
+ _argSlots[i] = argStackSlot;
+ signatureIndex++;
+ }
}
- int totalLocalSize = 0;
- foreach(LocalVariableDefinition local in _locals)
+ string[] localNames = new string[_locals.Length];
+ if (_debugInformation != null)
{
- totalLocalSize = PadNextOffset(local.Type, totalLocalSize);
+ foreach (ILLocalVariable localDebugInfo in _debugInformation.GetLocalVariables() ?? Enumerable.Empty<ILLocalVariable>())
+ {
+ // Check whether the slot still exists as the compiler may remove it for intrinsics
+ int slot = localDebugInfo.Slot;
+ if (slot < localNames.Length)
+ {
+ localNames[localDebugInfo.Slot] = localDebugInfo.Name;
+ }
+ }
}
- var sp = LLVM.GetFirstParam(_llvmFunction);
- int paramOffset = GetTotalParameterOffset();
- for (int i = 0; i < totalLocalSize; i++)
+ for (int i = 0; i < _locals.Length; i++)
{
- var stackOffset = LLVM.BuildGEP(_builder, sp, new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), (ulong)(paramOffset + i), LLVMMisc.False) }, String.Empty);
- LLVM.BuildStore(_builder, LLVM.ConstInt(LLVM.Int8Type(), 0, LLVMMisc.False), stackOffset);
+ if (CanStoreLocalOnStack(_locals[i].Type))
+ {
+ string localName = String.Empty;
+ if (localNames[i] != null)
+ {
+ localName = localNames[i] + "_";
+ }
+
+ localName += $"local{i}_";
+
+ LLVMValueRef localStackSlot = LLVM.BuildAlloca(_builder, GetLLVMTypeForTypeDesc(_locals[i].Type), localName);
+ _localSlots[i] = localStackSlot;
+ }
}
+
+ if (_methodIL.IsInitLocals)
+ {
+ for(int i = 0; i < _locals.Length; i++)
+ {
+ LLVMValueRef localAddr = LoadVarAddress(i, LocalVarKind.Local, out TypeDesc localType);
+ if(CanStoreLocalOnStack(localType))
+ {
+ LLVMTypeRef llvmType = GetLLVMTypeForTypeDesc(localType);
+ LLVMTypeKind typeKind = LLVM.GetTypeKind(llvmType);
+ switch (typeKind)
+ {
+ case LLVMTypeKind.LLVMIntegerTypeKind:
+ if (llvmType.Equals(LLVM.Int1Type()))
+ {
+ LLVM.BuildStore(_builder, BuildConstInt1(0), localAddr);
+ }
+ else if (llvmType.Equals(LLVM.Int8Type()))
+ {
+ LLVM.BuildStore(_builder, BuildConstInt8(0), localAddr);
+ }
+ else if (llvmType.Equals(LLVM.Int16Type()))
+ {
+ LLVM.BuildStore(_builder, BuildConstInt16(0), localAddr);
+ }
+ else if (llvmType.Equals(LLVM.Int32Type()))
+ {
+ LLVM.BuildStore(_builder, BuildConstInt32(0), localAddr);
+ }
+ else if (llvmType.Equals(LLVM.Int64Type()))
+ {
+ LLVM.BuildStore(_builder, BuildConstInt64(0), localAddr);
+ }
+ else
+ {
+ throw new Exception("Unexpected LLVM int type");
+ }
+ break;
+
+ case LLVMTypeKind.LLVMPointerTypeKind:
+ LLVM.BuildStore(_builder, LLVM.ConstPointerNull(llvmType), localAddr);
+ break;
+
+ default:
+ LLVMValueRef castAddr = LLVM.BuildPointerCast(_builder, localAddr, LLVM.PointerType(LLVM.Int8Type(), 0), $"cast_local{i}_");
+ ImportCallMemset(castAddr, 0, localType.GetElementSize().AsInt);
+ break;
+ }
+ }
+ else
+ {
+ LLVMValueRef castAddr = LLVM.BuildPointerCast(_builder, localAddr, LLVM.PointerType(LLVM.Int8Type(), 0), $"cast_local{i}_");
+ ImportCallMemset(castAddr, 0, localType.GetElementSize().AsInt);
+ }
+ }
+ }
+
+ MetadataType metadataType = (MetadataType)_thisType;
+ if (!metadataType.IsBeforeFieldInit)
+ {
+ if (!_method.IsStaticConstructor && _method.Signature.IsStatic || _method.IsConstructor || (_thisType.IsValueType && !_method.Signature.IsStatic))
+ {
+ TriggerCctor(metadataType);
+ }
+ }
+
+ LLVMBasicBlockRef block0 = GetLLVMBasicBlockForBlock(_basicBlocks[0]);
+ LLVM.BuildBr(_builder, block0);
}
- private LLVMValueRef CreateLLVMFunction(string mangledName)
+ private LLVMValueRef CreateLLVMFunction(string mangledName, MethodSignature signature)
{
- return LLVM.AddFunction(Module, mangledName , _universalSignature);
+ return LLVM.AddFunction(Module, mangledName, GetLLVMSignatureForMethod(signature));
}
- private LLVMValueRef GetOrCreateLLVMFunction(string mangledName)
+ private LLVMValueRef GetOrCreateLLVMFunction(string mangledName, MethodSignature signature)
{
LLVMValueRef llvmFunction = LLVM.GetNamedFunction(Module, mangledName);
if(llvmFunction.Pointer == IntPtr.Zero)
{
- return CreateLLVMFunction(mangledName);
+ return CreateLLVMFunction(mangledName, signature);
}
return llvmFunction;
}
@@ -274,23 +417,13 @@ namespace Internal.IL
int n = entryStack.Length;
for (int i = 0; i < n; i++)
{
- _stack.Push(entryStack[i].Duplicate());
+ _stack.Push(entryStack[i].Duplicate(_builder));
}
}
- bool isFirstBlock = false;
- if(_curBasicBlock.Equals(default(LLVMBasicBlockRef)))
- {
- isFirstBlock = true;
- }
_curBasicBlock = GetLLVMBasicBlockForBlock(basicBlock);
LLVM.PositionBuilderAtEnd(_builder, _curBasicBlock);
-
- if(isFirstBlock)
- {
- GenerateProlog();
- }
}
private void EndImportingBasicBlock(BasicBlock basicBlock)
@@ -302,22 +435,81 @@ namespace Internal.IL
{
if (_basicBlocks[_currentOffset].StartOffset == 0)
throw new InvalidProgramException();
-
+ MarkBasicBlock(_basicBlocks[_currentOffset]);
LLVM.BuildBr(_builder, GetLLVMBasicBlockForBlock(_basicBlocks[_currentOffset]));
}
- else
- {
- LLVM.BuildRet(_builder, default(LLVMValueRef));
- }
}
}
private void StartImportingInstruction()
{
+ if (_debugInformation != null)
+ {
+ bool foundSequencePoint = false;
+ ILSequencePoint curSequencePoint = default;
+ foreach (var sequencePoint in _debugInformation.GetSequencePoints() ?? Enumerable.Empty<ILSequencePoint>())
+ {
+ if (sequencePoint.Offset == _currentOffset)
+ {
+ curSequencePoint = sequencePoint;
+ foundSequencePoint = true;
+ break;
+ }
+ else if (sequencePoint.Offset < _currentOffset)
+ {
+ curSequencePoint = sequencePoint;
+ foundSequencePoint = true;
+ }
+ }
+
+ if (!foundSequencePoint)
+ {
+ return;
+ }
+
+ // LLVM can't process empty string file names
+ if (String.IsNullOrWhiteSpace(curSequencePoint.Document))
+ {
+ return;
+ }
+
+ DebugMetadata debugMetadata;
+ if (!_compilation.DebugMetadataMap.TryGetValue(curSequencePoint.Document, out debugMetadata))
+ {
+ string fullPath = curSequencePoint.Document;
+ string fileName = Path.GetFileName(fullPath);
+ string directory = Path.GetDirectoryName(fullPath) ?? String.Empty;
+ LLVMMetadataRef fileMetadata = LLVMPInvokes.LLVMDIBuilderCreateFile(_compilation.DIBuilder, fullPath, fullPath.Length,
+ directory, directory.Length);
+
+ // todo: get the right value for isOptimized
+ LLVMMetadataRef compileUnitMetadata = LLVMPInvokes.LLVMDIBuilderCreateCompileUnit(_compilation.DIBuilder, LLVMDWARFSourceLanguage.LLVMDWARFSourceLanguageC,
+ fileMetadata, "ILC", 3, isOptimized: false, String.Empty, 0, 1, String.Empty, 0, LLVMDWARFEmissionKind.LLVMDWARFEmissionFull, 0, false, false);
+ LLVM.AddNamedMetadataOperand(Module, "llvm.dbg.cu", LLVM.MetadataAsValue(Context, compileUnitMetadata));
+
+ debugMetadata = new DebugMetadata(fileMetadata, compileUnitMetadata);
+ _compilation.DebugMetadataMap[fullPath] = debugMetadata;
+ }
+
+ if (_debugFunction.Pointer == IntPtr.Zero)
+ {
+ _debugFunction = LLVM.DIBuilderCreateFunction(_compilation.DIBuilder, debugMetadata.CompileUnit, _method.Name, String.Empty, debugMetadata.File,
+ (uint)_debugInformation.GetSequencePoints().FirstOrDefault().LineNumber, default(LLVMMetadataRef), 1, 1, 1, 0, IsOptimized: 0, _llvmFunction);
+ }
+
+ LLVMMetadataRef currentLine = LLVMPInvokes.LLVMDIBuilderCreateDebugLocation(Context, (uint)curSequencePoint.LineNumber, 0, _debugFunction, default(LLVMMetadataRef));
+ LLVM.SetCurrentDebugLocation(_builder, LLVM.MetadataAsValue(Context, currentLine));
+ }
}
private void EndImportingInstruction()
{
+ // If this was constrained used in a call, it's already been cleared,
+ // but if it was on some other instruction, it shoudln't carry forward
+ _constrainedType = null;
+
+ // Reset the debug position so it doesn't end up applying to the wrong instructions
+ LLVM.SetCurrentDebugLocation(_builder, default(LLVMValueRef));
}
private void ImportNop()
@@ -337,40 +529,40 @@ namespace Internal.IL
private void ImportLoadVar(int index, bool argument)
{
LLVMValueRef typedLoadLocation = LoadVarAddress(index, argument ? LocalVarKind.Argument : LocalVarKind.Local, out TypeDesc type);
- PushLoadExpression(GetStackValueKind(type), "ld" + (argument ? "arg" : "loc") + index + "_", typedLoadLocation, type);
+ PushLoadExpression(GetStackValueKind(type), (argument ? "arg" : "loc") + index + "_", typedLoadLocation, type);
}
private LLVMValueRef LoadTemp(int index)
{
LLVMValueRef address = LoadVarAddress(index, LocalVarKind.Temp, out TypeDesc type);
- return LLVM.BuildLoad(_builder, CastToPointerToTypeDesc(address, type), "ldtemp");
+ return LLVM.BuildLoad(_builder, CastToPointerToTypeDesc(address, type, $"Temp{index}_"), $"LdTemp{index}_");
}
internal LLVMValueRef LoadTemp(int index, LLVMTypeRef asType)
{
LLVMValueRef address = LoadVarAddress(index, LocalVarKind.Temp, out TypeDesc type);
- return LLVM.BuildLoad(_builder, CastIfNecessary(address, LLVM.PointerType(asType, 0)), "ldtemp");
+ return LLVM.BuildLoad(_builder, CastIfNecessary(address, LLVM.PointerType(asType, 0), $"Temp{index}_"), $"LdTemp{index}_");
}
- private void StoreTemp(int index, LLVMValueRef value)
+ private void StoreTemp(int index, LLVMValueRef value, string name = null)
{
LLVMValueRef address = LoadVarAddress(index, LocalVarKind.Temp, out TypeDesc type);
- LLVM.BuildStore(_builder, CastToTypeDesc(value, type), CastToPointerToTypeDesc(address, type));
+ LLVM.BuildStore(_builder, CastToTypeDesc(value, type, name), CastToPointerToTypeDesc(address, type, $"Temp{index}_"));
}
- internal static LLVMValueRef LoadValue(LLVMBuilderRef builder, LLVMValueRef address, TypeDesc sourceType, LLVMTypeRef targetType, bool signExtend)
+ internal static LLVMValueRef LoadValue(LLVMBuilderRef builder, LLVMValueRef address, TypeDesc sourceType, LLVMTypeRef targetType, bool signExtend, string loadName = null)
{
var underlyingSourceType = sourceType.UnderlyingType;
if (targetType.TypeKind == LLVMTypeKind.LLVMIntegerTypeKind && underlyingSourceType.IsPrimitive && !underlyingSourceType.IsPointer)
{
var sourceLLVMType = ILImporter.GetLLVMTypeForTypeDesc(underlyingSourceType);
var typedAddress = CastIfNecessary(builder, address, LLVM.PointerType(sourceLLVMType, 0));
- return CastIntValue(builder, LLVM.BuildLoad(builder, typedAddress, "ldvalue"), targetType, signExtend);
+ return CastIntValue(builder, LLVM.BuildLoad(builder, typedAddress, loadName ?? "ldvalue"), targetType, signExtend);
}
else
{
var typedAddress = CastIfNecessary(builder, address, LLVM.PointerType(targetType, 0));
- return LLVM.BuildLoad(builder, typedAddress, "ldvalue");
+ return LLVM.BuildLoad(builder, typedAddress, loadName ?? "ldvalue");
}
}
@@ -427,7 +619,7 @@ namespace Internal.IL
varCountBase = 1;
}
- GetArgSizeAndOffsetAtIndex(index, out int argSize, out varOffset);
+ GetArgSizeAndOffsetAtIndex(index, out int argSize, out varOffset, out int realArgIndex);
if (!_signature.IsStatic && index == 0)
{
@@ -442,6 +634,13 @@ namespace Internal.IL
type = _signature[index - varCountBase];
}
valueType = GetLLVMTypeForTypeDesc(type);
+
+ // If the argument can be passed as a real argument rather than on the shadow stack,
+ // get its address here
+ if(realArgIndex != -1)
+ {
+ return _argSlots[realArgIndex];
+ }
}
else if (kind == LocalVarKind.Local)
{
@@ -449,6 +648,11 @@ namespace Internal.IL
GetLocalSizeAndOffsetAtIndex(index, out int localSize, out varOffset);
valueType = GetLLVMTypeForTypeDesc(_locals[index].Type);
type = _locals[index].Type;
+ if(varOffset == -1)
+ {
+ Debug.Assert(_localSlots[index].Pointer != IntPtr.Zero);
+ return _localSlots[index];
+ }
}
else
{
@@ -460,7 +664,7 @@ namespace Internal.IL
return LLVM.BuildGEP(_builder, LLVM.GetFirstParam(_llvmFunction),
new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), (uint)(varBase + varOffset), LLVMMisc.False) },
- String.Empty);
+ $"{kind}{index}_");
}
@@ -510,71 +714,71 @@ namespace Internal.IL
TypeDesc varType;
StackEntry toStore = _stack.Pop();
LLVMValueRef varAddress = LoadVarAddress(index, argument ? LocalVarKind.Argument : LocalVarKind.Local, out varType);
- CastingStore(varAddress, toStore, varType);
+ CastingStore(varAddress, toStore, varType, $"Variable{index}_");
}
- private void ImportStoreHelper(LLVMValueRef toStore, LLVMTypeRef valueType, LLVMValueRef basePtr, uint offset)
+ private void ImportStoreHelper(LLVMValueRef toStore, LLVMTypeRef valueType, LLVMValueRef basePtr, uint offset, string name = null)
{
- LLVMValueRef typedToStore = CastIfNecessary(toStore, valueType);
+ LLVMValueRef typedToStore = CastIfNecessary(toStore, valueType, name);
var storeLocation = LLVM.BuildGEP(_builder, basePtr,
new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), offset, LLVMMisc.False) },
String.Empty);
- var typedStoreLocation = CastIfNecessary(storeLocation, LLVM.PointerType(valueType, 0));
+ var typedStoreLocation = CastIfNecessary(storeLocation, LLVM.PointerType(valueType, 0), "TypedStore" + (name ?? ""));
LLVM.BuildStore(_builder, typedToStore, typedStoreLocation);
}
- private LLVMValueRef CastToRawPointer(LLVMValueRef source)
+ private LLVMValueRef CastToRawPointer(LLVMValueRef source, string name = null)
{
- return CastIfNecessary(source, LLVM.PointerType(LLVM.Int8Type(), 0));
+ return CastIfNecessary(source, LLVM.PointerType(LLVM.Int8Type(), 0), name);
}
- private LLVMValueRef CastToTypeDesc(LLVMValueRef source, TypeDesc type)
+ private LLVMValueRef CastToTypeDesc(LLVMValueRef source, TypeDesc type, string name = null)
{
- return CastIfNecessary(source, GetLLVMTypeForTypeDesc(type));
+ return CastIfNecessary(source, GetLLVMTypeForTypeDesc(type), (name ?? "") + type.ToString());
}
- private LLVMValueRef CastToPointerToTypeDesc(LLVMValueRef source, TypeDesc type)
+ private LLVMValueRef CastToPointerToTypeDesc(LLVMValueRef source, TypeDesc type, string name = null)
{
- return CastIfNecessary(source, LLVM.PointerType(GetLLVMTypeForTypeDesc(type), 0));
+ return CastIfNecessary(source, LLVM.PointerType(GetLLVMTypeForTypeDesc(type), 0), (name ?? "") + type.ToString());
}
- private void CastingStore(LLVMValueRef address, StackEntry value, TypeDesc targetType)
+ private void CastingStore(LLVMValueRef address, StackEntry value, TypeDesc targetType, string targetName = null)
{
- var typedStoreLocation = CastToPointerToTypeDesc(address, targetType);
+ var typedStoreLocation = CastToPointerToTypeDesc(address, targetType, targetName);
LLVM.BuildStore(_builder, value.ValueAsType(targetType, _builder), typedStoreLocation);
}
- private LLVMValueRef CastIfNecessary(LLVMValueRef source, LLVMTypeRef valueType)
+ private LLVMValueRef CastIfNecessary(LLVMValueRef source, LLVMTypeRef valueType, string name = null)
{
- return CastIfNecessary(_builder, source, valueType);
+ return CastIfNecessary(_builder, source, valueType, name);
}
- internal static LLVMValueRef CastIfNecessary(LLVMBuilderRef builder, LLVMValueRef source, LLVMTypeRef valueType)
+ internal static LLVMValueRef CastIfNecessary(LLVMBuilderRef builder, LLVMValueRef source, LLVMTypeRef valueType, string name = null)
{
LLVMTypeRef sourceType = LLVM.TypeOf(source);
if (sourceType.Pointer == valueType.Pointer)
return source;
- LLVMTypeKind toStoreKind = LLVM.GetTypeKind(LLVM.TypeOf(source));
+ LLVMTypeKind toStoreKind = LLVM.GetTypeKind(sourceType);
LLVMTypeKind valueTypeKind = LLVM.GetTypeKind(valueType);
LLVMValueRef typedToStore = source;
if (toStoreKind == LLVMTypeKind.LLVMPointerTypeKind && valueTypeKind == LLVMTypeKind.LLVMPointerTypeKind)
{
- typedToStore = LLVM.BuildPointerCast(builder, source, valueType, "CastIfNecessaryPtr");
+ typedToStore = LLVM.BuildPointerCast(builder, source, valueType, "CastPtr" + (name ?? ""));
}
else if (toStoreKind == LLVMTypeKind.LLVMPointerTypeKind && valueTypeKind == LLVMTypeKind.LLVMIntegerTypeKind)
{
- typedToStore = LLVM.BuildPtrToInt(builder, source, valueType, "CastIfNecessaryInt");
+ typedToStore = LLVM.BuildPtrToInt(builder, source, valueType, "CastInt" + (name ?? ""));
}
else if (toStoreKind == LLVMTypeKind.LLVMIntegerTypeKind && valueTypeKind == LLVMTypeKind.LLVMArrayTypeKind)
{
- typedToStore = LLVM.BuildLoad(builder, CastIfNecessary(builder, source, LLVM.PointerType(valueType, 0)), "CastIfNecessaryArrayLoad");
+ typedToStore = LLVM.BuildLoad(builder, CastIfNecessary(builder, source, LLVM.PointerType(valueType, 0), name), "CastArrayLoad" + (name ?? ""));
}
else if (toStoreKind == LLVMTypeKind.LLVMPointerTypeKind && valueTypeKind == LLVMTypeKind.LLVMArrayTypeKind)
{
- typedToStore = LLVM.BuildLoad(builder, CastIfNecessary(builder, source, LLVM.PointerType(valueType, 0)), "CastIfNecessaryArrayLoad");
+ typedToStore = LLVM.BuildLoad(builder, CastIfNecessary(builder, source, LLVM.PointerType(valueType, 0), name), "CastArrayLoad" + (name ?? ""));
}
else if (toStoreKind == LLVMTypeKind.LLVMPointerTypeKind && valueTypeKind != LLVMTypeKind.LLVMIntegerTypeKind)
{
@@ -582,7 +786,7 @@ namespace Internal.IL
}
else if (toStoreKind == LLVMTypeKind.LLVMIntegerTypeKind && valueTypeKind == LLVMTypeKind.LLVMPointerTypeKind)
{
- typedToStore = LLVM.BuildIntToPtr(builder, source, valueType, "CastIfNecessaryPtr");
+ typedToStore = LLVM.BuildIntToPtr(builder, source, valueType, "CastPtr" + (name ?? ""));
}
else if (toStoreKind != LLVMTypeKind.LLVMIntegerTypeKind && valueTypeKind == LLVMTypeKind.LLVMPointerTypeKind)
{
@@ -590,12 +794,12 @@ namespace Internal.IL
}
else if (toStoreKind == LLVMTypeKind.LLVMFloatTypeKind && valueTypeKind == LLVMTypeKind.LLVMDoubleTypeKind)
{
- typedToStore = LLVM.BuildFPExt(builder, source, valueType, "FloatToDouble");
+ typedToStore = LLVM.BuildFPExt(builder, source, valueType, "CastFloatToDouble" + (name ?? ""));
}
else if (toStoreKind == LLVMTypeKind.LLVMDoubleTypeKind && valueTypeKind == LLVMTypeKind.LLVMFloatTypeKind)
{
- typedToStore = LLVM.BuildFPTrunc(builder, source, valueType, "DoubleToFloat");
+ typedToStore = LLVM.BuildFPTrunc(builder, source, valueType, "CastDoubleToFloat" + (name ?? ""));
}
else if (toStoreKind != valueTypeKind && toStoreKind != LLVMTypeKind.LLVMIntegerTypeKind && valueTypeKind != LLVMTypeKind.LLVMIntegerTypeKind)
{
@@ -604,21 +808,18 @@ namespace Internal.IL
else if (toStoreKind == valueTypeKind && toStoreKind == LLVMTypeKind.LLVMIntegerTypeKind)
{
Debug.Assert(toStoreKind != LLVMTypeKind.LLVMPointerTypeKind && valueTypeKind != LLVMTypeKind.LLVMPointerTypeKind);
- typedToStore = LLVM.BuildIntCast(builder, source, valueType, "CastIfNecessaryInt");
+ typedToStore = LLVM.BuildIntCast(builder, source, valueType, "CastInt" + (name ?? ""));
}
- else if (toStoreKind != LLVMTypeKind.LLVMFloatTypeKind && valueTypeKind == LLVMTypeKind.LLVMFloatTypeKind)
+ else if (toStoreKind == LLVMTypeKind.LLVMIntegerTypeKind && (valueTypeKind == LLVMTypeKind.LLVMDoubleTypeKind || valueTypeKind == LLVMTypeKind.LLVMFloatTypeKind))
{
- typedToStore = LLVM.BuildFPCast(builder, source, valueType, "CastIfNecessaryFloat");
+ //TODO: keep track of the TypeDesc so we can call BuildUIToFP when the integer is unsigned
+ typedToStore = LLVM.BuildSIToFP(builder, source, valueType, "CastSIToFloat" + (name ?? ""));
}
else if ((toStoreKind == LLVMTypeKind.LLVMDoubleTypeKind || toStoreKind == LLVMTypeKind.LLVMFloatTypeKind) &&
valueTypeKind == LLVMTypeKind.LLVMIntegerTypeKind)
{
//TODO: keep track of the TypeDesc so we can call BuildFPToUI when the integer is unsigned
- typedToStore = LLVM.BuildFPToSI(builder, source, valueType, "CastIfNecessaryFloat");
- }
- else if (toStoreKind == LLVMTypeKind.LLVMIntegerTypeKind && valueTypeKind == LLVMTypeKind.LLVMDoubleTypeKind)
- {
- throw new NotImplementedException();
+ typedToStore = LLVM.BuildFPToSI(builder, source, valueType, "CastFloatSI" + (name ?? ""));
}
return typedToStore;
@@ -667,7 +868,37 @@ namespace Internal.IL
case TypeFlags.ValueType:
case TypeFlags.Nullable:
- return LLVM.ArrayType(LLVM.Int8Type(), (uint)type.GetElementSize().AsInt);
+ {
+ int structSize = type.GetElementSize().AsInt;
+
+ // LLVM thinks certain sizes of struct have a different calling convention than Clang does.
+ // Treating them as ints fixes that and is more efficient in general
+ switch (structSize)
+ {
+ case 1:
+ return LLVM.Int8Type();
+ case 2:
+ return LLVM.Int16Type();
+ case 4:
+ return LLVM.Int32Type();
+ case 8:
+ return LLVM.Int64Type();
+ }
+
+ int numInts = structSize / 4;
+ int numBytes = structSize - numInts * 4;
+ LLVMTypeRef[] structMembers = new LLVMTypeRef[numInts + numBytes];
+ for (int i = 0; i < numInts; i++)
+ {
+ structMembers[i] = LLVM.Int32Type();
+ }
+ for (int i = 0; i < numBytes; i++)
+ {
+ structMembers[i + numInts] = LLVM.Int8Type();
+ }
+
+ return LLVM.StructType(structMembers, true);
+ }
case TypeFlags.Enum:
return GetLLVMTypeForTypeDesc(type.UnderlyingType);
@@ -695,17 +926,65 @@ namespace Internal.IL
int offset = 0;
for (int i = 0; i < _locals.Length; i++)
{
- offset = PadNextOffset(_locals[i].Type, offset);
+ TypeDesc localType = _locals[i].Type;
+ if (!CanStoreLocalOnStack(localType))
+ {
+ offset = PadNextOffset(localType, offset);
+ }
}
return offset.AlignUp(_pointerSize);
}
+ private bool CanStoreLocalOnStack(TypeDesc localType)
+ {
+ // Keep all locals on the shadow stack if there is exception
+ // handling so funclets can access them
+ if (_exceptionRegions.Length == 0)
+ {
+ return CanStoreTypeOnStack(localType);
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Returns true if the type can be stored on the local stack
+ /// instead of the shadow stack in this method.
+ /// </summary>
+ private static bool CanStoreTypeOnStack(TypeDesc type)
+ {
+ if (type is DefType defType)
+ {
+ if (!defType.IsGCPointer && !defType.ContainsGCPointers)
+ {
+ return true;
+ }
+ }
+ else if (type is PointerType)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Returns true if the method returns a type that must be kept
+ /// on the shadow stack
+ /// </summary>
+ private static bool NeedsReturnStackSlot(MethodSignature signature)
+ {
+ return !signature.ReturnType.IsVoid && !CanStoreTypeOnStack(signature.ReturnType);
+ }
+
private int GetTotalParameterOffset()
{
int offset = 0;
for (int i = 0; i < _signature.Length; i++)
{
- offset = PadNextOffset(_signature[i], offset);
+ if (!CanStoreTypeOnStack(_signature[i]))
+ {
+ offset = PadNextOffset(_signature[i], offset);
+ }
}
if (!_signature.IsStatic)
{
@@ -723,8 +1002,10 @@ namespace Internal.IL
return offset.AlignUp(_pointerSize);
}
- private void GetArgSizeAndOffsetAtIndex(int index, out int size, out int offset)
+ private void GetArgSizeAndOffsetAtIndex(int index, out int size, out int offset, out int realArgIndex)
{
+ realArgIndex = -1;
+
int thisSize = 0;
if (!_signature.IsStatic)
{
@@ -744,10 +1025,28 @@ namespace Internal.IL
var argType = _signature[index];
size = argType.GetElementSize().AsInt;
+ int potentialRealArgIndex = 0;
+
offset = thisSize;
for (int i = 0; i < index; i++)
{
- offset = PadNextOffset(_signature[i], offset);
+ // We could compact the set of argSlots to only those that we'd keep on the stack, but currently don't
+ potentialRealArgIndex++;
+
+ if (!CanStoreTypeOnStack(_signature[i]))
+ {
+ offset = PadNextOffset(_signature[i], offset);
+ }
+ }
+
+ if (CanStoreTypeOnStack(argType))
+ {
+ realArgIndex = potentialRealArgIndex;
+ offset = -1;
+ }
+ else
+ {
+ offset = PadOffset(argType, offset);
}
}
@@ -756,10 +1055,21 @@ namespace Internal.IL
LocalVariableDefinition local = _locals[index];
size = local.Type.GetElementSize().AsInt;
- offset = 0;
- for (int i = 0; i < index; i++)
+ if (CanStoreLocalOnStack(local.Type))
{
- offset = PadNextOffset(_locals[i].Type, offset);
+ offset = -1;
+ }
+ else
+ {
+ offset = 0;
+ for (int i = 0; i < index; i++)
+ {
+ if (!CanStoreLocalOnStack(_locals[i].Type))
+ {
+ offset = PadNextOffset(_locals[i].Type, offset);
+ }
+ }
+ offset = PadOffset(local.Type, offset);
}
}
@@ -773,6 +1083,7 @@ namespace Internal.IL
{
offset = PadNextOffset(_spilledExpressions[i].Type, offset);
}
+ offset = PadOffset(spill.Type, offset);
}
public int PadNextOffset(TypeDesc type, int atOffset)
@@ -810,12 +1121,14 @@ namespace Internal.IL
{
TypeDesc type;
LLVMValueRef typedLoadLocation = LoadVarAddress(index, argument ? LocalVarKind.Argument : LocalVarKind.Local, out type);
- _stack.Push(new AddressExpressionEntry(StackValueKind.ByRef, "ldloca", typedLoadLocation, type.MakePointerType()));
+ _stack.Push(new AddressExpressionEntry(StackValueKind.ByRef, "ldloca", typedLoadLocation, type.MakeByRefType()));
}
private void ImportDup()
{
- _stack.Push(_stack.Peek().Duplicate());
+ var entry = _stack.Pop();
+ _stack.Push(entry.Duplicate(_builder));
+ _stack.Push(entry.Duplicate(_builder));
}
private void ImportPop()
@@ -858,14 +1171,25 @@ namespace Internal.IL
private void ImportReturn()
{
- if (_signature.ReturnType != GetWellKnownType(WellKnownType.Void))
+ if (_signature.ReturnType.IsVoid)
{
- StackEntry retVal = _stack.Pop();
- LLVMTypeRef valueType = GetLLVMTypeForTypeDesc(_signature.ReturnType);
- ImportStoreHelper(retVal.ValueAsType(valueType, _builder), valueType, LLVM.GetNextParam(LLVM.GetFirstParam(_llvmFunction)), 0);
+ LLVM.BuildRetVoid(_builder);
+ return;
}
- LLVM.BuildRetVoid(_builder);
+ StackEntry retVal = _stack.Pop();
+ LLVMTypeRef valueType = GetLLVMTypeForTypeDesc(_signature.ReturnType);
+ LLVMValueRef castValue = retVal.ValueAsType(valueType, _builder);
+
+ if (NeedsReturnStackSlot(_signature))
+ {
+ ImportStoreHelper(castValue, valueType, LLVM.GetNextParam(LLVM.GetFirstParam(_llvmFunction)), 0);
+ LLVM.BuildRetVoid(_builder);
+ }
+ else
+ {
+ LLVM.BuildRet(_builder, castValue);
+ }
}
private void ImportCall(ILOpcode opcode, int token)
@@ -879,7 +1203,7 @@ namespace Internal.IL
}
}
- if (callee.IsPInvoke || (callee.IsInternalCall && callee.HasCustomAttribute("System.Runtime", "RuntimeImportAttribute")))
+ if (callee.IsRawPInvoke() || (callee.IsInternalCall && callee.HasCustomAttribute("System.Runtime", "RuntimeImportAttribute")))
{
ImportRawPInvoke(callee);
return;
@@ -888,7 +1212,28 @@ namespace Internal.IL
if (opcode == ILOpcode.newobj)
{
TypeDesc newType = callee.OwningType;
- if (newType.IsString)
+ if (newType.IsArray)
+ {
+ var paramCnt = callee.Signature.Length;
+ var eeTypeDesc = _compilation.TypeSystemContext.SystemModule.GetKnownType("Internal.Runtime", "EEType").MakePointerType();
+ LLVMValueRef dimensions = LLVM.BuildArrayAlloca(_builder, LLVMTypeRef.Int32Type(), BuildConstInt32(paramCnt), "newobj_array_pdims_" + _currentOffset);
+ for (int i = paramCnt - 1; i >= 0; --i)
+ {
+ LLVM.BuildStore(_builder, _stack.Pop().ValueAsInt32(_builder, true),
+ LLVM.BuildGEP(_builder, dimensions, new LLVMValueRef[] { BuildConstInt32(i) }, "pdims_ptr"));
+ }
+ var arguments = new StackEntry[]
+ {
+ new LoadExpressionEntry(StackValueKind.ValueType, "eeType", GetEETypePointerForTypeDesc(newType, true), eeTypeDesc),
+ new Int32ConstantEntry(paramCnt),
+ new AddressExpressionEntry(StackValueKind.ValueType, "newobj_array_pdims", dimensions)
+ };
+ MetadataType helperType = _compilation.TypeSystemContext.SystemModule.GetKnownType("Internal.Runtime.CompilerHelpers", "ArrayHelpers");
+ MethodDesc helperMethod = helperType.GetKnownMethod("NewObjArray", null);
+ PushNonNull(HandleCall(helperMethod, helperMethod.Signature, arguments, forcedReturnType: newType));
+ return;
+ }
+ else if (newType.IsString)
{
// String constructors actually look like regular method calls
IMethodNode node = _compilation.NodeFactory.StringAllocator(callee);
@@ -927,12 +1272,6 @@ namespace Internal.IL
}
}
- // we don't really have virtual call support, but we'll treat it as direct for now
- if (opcode != ILOpcode.call && opcode != ILOpcode.callvirt && opcode != ILOpcode.newobj)
- {
- throw new NotImplementedException();
- }
-
if (opcode == ILOpcode.newobj && callee.OwningType.IsDelegate)
{
FunctionPointerEntry functionPointer = ((FunctionPointerEntry)_stack.Peek());
@@ -940,16 +1279,26 @@ namespace Internal.IL
callee = delegateInfo.Constructor.Method;
if (callee.Signature.Length == 3)
{
- PushExpression(StackValueKind.NativeInt, "thunk", GetOrCreateLLVMFunction(_compilation.NodeFactory.NameMangler.GetMangledMethodName(delegateInfo.Thunk.Method).ToString()));
+ PushExpression(StackValueKind.NativeInt, "thunk", GetOrCreateLLVMFunction(_compilation.NodeFactory.NameMangler.GetMangledMethodName(delegateInfo.Thunk.Method).ToString(), delegateInfo.Thunk.Method.Signature));
}
}
- HandleCall(callee, callee.Signature, opcode);
+ TypeDesc localConstrainedType = _constrainedType;
+ _constrainedType = null;
+ HandleCall(callee, callee.Signature, opcode, localConstrainedType);
}
- private LLVMValueRef LLVMFunctionForMethod(MethodDesc callee, StackEntry thisPointer, bool isCallVirt)
+ private LLVMValueRef LLVMFunctionForMethod(MethodDesc callee, StackEntry thisPointer, bool isCallVirt, TypeDesc constrainedType)
{
string calleeName = _compilation.NameMangler.GetMangledMethodName(callee).ToString();
+
+ // Sealed methods must not be called virtually due to sealed vTables, so call them directly
+ if(callee.IsFinal || callee.OwningType.IsSealed())
+ {
+ AddMethodReference(callee);
+ return GetOrCreateLLVMFunction(calleeName, callee.Signature);
+ }
+
if (thisPointer != null && callee.IsVirtual && isCallVirt)
{
// TODO: Full resolution of virtual methods
@@ -959,44 +1308,125 @@ namespace Internal.IL
if (!_compilation.HasFixedSlotVTable(callee.OwningType))
AddVirtualMethodReference(callee);
- //TODO: needs runtime support for DispatchByInterface
- if (callee.OwningType.IsInterface)
- throw new NotImplementedException("Interface call");
+ bool isValueTypeCall = false;
+ TypeDesc thisType = thisPointer.Type;
+ TypeFlags category = thisType.Category;
+ MethodDesc targetMethod = null;
+ TypeDesc parameterType = null;
+
+ if (category == TypeFlags.ByRef)
+ {
+ parameterType = ((ByRefType)thisType).ParameterType;
+ if (parameterType.IsValueType)
+ {
+ isValueTypeCall = true;
+ }
+ }
+
+ if(constrainedType != null && constrainedType.IsValueType)
+ {
+ isValueTypeCall = true;
+ }
+
+ if (isValueTypeCall)
+ {
+ if (constrainedType != null)
+ {
+ targetMethod = constrainedType.TryResolveConstraintMethodApprox(callee.OwningType, callee, out _);
+ }
+ else if (callee.OwningType.IsInterface)
+ {
+ targetMethod = parameterType.ResolveInterfaceMethodTarget(callee);
+ }
+ else
+ {
+ targetMethod = parameterType.FindVirtualFunctionTargetMethodOnObjectType(callee);
+ }
+ }
+
+ if (targetMethod != null)
+ {
+ AddMethodReference(targetMethod);
+ return GetOrCreateLLVMFunction(_compilation.NameMangler.GetMangledMethodName(targetMethod).ToString(), callee.Signature);
+ }
+
+ return GetCallableVirtualMethod(thisPointer, callee);
- return GetCallableVirtualMethod(thisPointer.ValueAsType(LLVM.PointerType(LLVM.Int8Type(), 0), _builder), callee);
}
else
{
- return GetOrCreateLLVMFunction(calleeName);
+ return GetOrCreateLLVMFunction(calleeName, callee.Signature);
}
}
-
+
private LLVMValueRef GetOrCreateMethodSlot(MethodDesc method)
{
var vtableSlotSymbol = _compilation.NodeFactory.VTableSlot(method);
_dependencies.Add(vtableSlotSymbol);
LLVMValueRef slot = LoadAddressOfSymbolNode(vtableSlotSymbol);
- return LLVM.BuildLoad(_builder, slot, string.Empty);
+ return LLVM.BuildLoad(_builder, slot, $"{method.Name}_slot");
}
- private LLVMValueRef GetCallableVirtualMethod(LLVMValueRef objectPtr, MethodDesc method)
+ private LLVMValueRef GetCallableVirtualMethod(StackEntry objectPtr, MethodDesc method)
{
Debug.Assert(method.IsVirtual);
+ LLVMValueRef slot = GetOrCreateMethodSlot(method);
+ var pointerSize = method.Context.Target.PointerSize;
+ LLVMTypeRef llvmSignature = GetLLVMSignatureForMethod(method.Signature);
+ LLVMValueRef functionPtr;
if (method.OwningType.IsInterface)
{
- throw new NotImplementedException();
+ var eeTypeDesc = _compilation.TypeSystemContext.SystemModule.GetKnownType("System", "EETypePtr");
+ var interfaceEEType = new LoadExpressionEntry(StackValueKind.ValueType, "interfaceEEType", GetEETypePointerForTypeDesc(method.OwningType, true), eeTypeDesc);
+ var eeTypeExpression = new LoadExpressionEntry(StackValueKind.ValueType, "eeType", objectPtr.ValueAsType(LLVM.PointerType(LLVM.Int8Type(), 0), _builder), eeTypeDesc);
+ var targetEntry = CallRuntime(_compilation.TypeSystemContext, DispatchResolve, "FindInterfaceMethodImplementationTarget", new StackEntry[] { eeTypeExpression, interfaceEEType, new ExpressionEntry(StackValueKind.Int32, "slot", slot, GetWellKnownType(WellKnownType.UInt16)) });
+ functionPtr = targetEntry.ValueAsType(LLVM.PointerType(llvmSignature, 0), _builder);
}
else
{
- LLVMValueRef slot = GetOrCreateMethodSlot(method);
- var pointerSize = method.Context.Target.PointerSize;
- LLVMTypeRef universalSignature = LLVM.FunctionType(LLVM.VoidType(), new LLVMTypeRef[] { LLVM.PointerType(LLVM.Int8Type(), 0), LLVM.PointerType(LLVM.Int8Type(), 0) }, false);
- var rawObjectPtr = CastIfNecessary(objectPtr, LLVM.PointerType(LLVM.PointerType(LLVM.PointerType(universalSignature, 0), 0), 0));
+ var rawObjectPtr = CastIfNecessary(objectPtr.ValueAsType(LLVM.PointerType(LLVM.Int8Type(), 0), _builder), LLVM.PointerType(LLVM.PointerType(LLVM.PointerType(llvmSignature, 0), 0), 0), objectPtr.Name());
var eeType = LLVM.BuildLoad(_builder, rawObjectPtr, "ldEEType");
var slotPtr = LLVM.BuildGEP(_builder, eeType, new LLVMValueRef[] { slot }, "__getslot__");
- var functionPtr = LLVM.BuildLoad(_builder, slotPtr, "ld__getslot__");
- return functionPtr;
+ functionPtr = LLVM.BuildLoad(_builder, slotPtr, "ld__getslot__");
+ }
+
+ return functionPtr;
+ }
+
+ private LLVMTypeRef GetLLVMSignatureForMethod(MethodSignature signature)
+ {
+ TypeDesc returnType = signature.ReturnType;
+ LLVMTypeRef llvmReturnType;
+ bool returnOnStack = false;
+ if (!NeedsReturnStackSlot(signature))
+ {
+ returnOnStack = true;
+ llvmReturnType = GetLLVMTypeForTypeDesc(returnType);
+ }
+ else
+ {
+ llvmReturnType = LLVM.VoidType();
+ }
+
+ List<LLVMTypeRef> signatureTypes = new List<LLVMTypeRef>();
+ signatureTypes.Add(LLVM.PointerType(LLVM.Int8Type(), 0)); // Shadow stack pointer
+
+ if (!returnOnStack && returnType != GetWellKnownType(WellKnownType.Void))
+ {
+ signatureTypes.Add(LLVM.PointerType(LLVM.Int8Type(), 0));
}
+
+ // Intentionally skipping the 'this' pointer since it could always be a GC reference
+ // and thus must be on the shadow stack
+ foreach (TypeDesc type in signature)
+ {
+ if (CanStoreTypeOnStack(type))
+ {
+ signatureTypes.Add(GetLLVMTypeForTypeDesc(type));
+ }
+ }
+
+ return LLVM.FunctionType(llvmReturnType, signatureTypes.ToArray(), false);
}
private ExpressionEntry AllocateObject(TypeDesc type)
@@ -1019,11 +1449,21 @@ namespace Internal.IL
return LLVM.ConstInt(LLVM.Int8Type(), number, LLVMMisc.False);
}
+ private static LLVMValueRef BuildConstInt16(byte number)
+ {
+ return LLVM.ConstInt(LLVM.Int16Type(), number, LLVMMisc.False);
+ }
+
private static LLVMValueRef BuildConstInt32(int number)
{
return LLVM.ConstInt(LLVM.Int32Type(), (ulong)number, LLVMMisc.False);
}
+ private static LLVMValueRef BuildConstInt64(long number)
+ {
+ return LLVM.ConstInt(LLVM.Int64Type(), (ulong)number, LLVMMisc.False);
+ }
+
private LLVMValueRef GetEETypeForTypeDesc(TypeDesc target, bool constructed)
{
var eeTypePointer = GetEETypePointerForTypeDesc(target, constructed);
@@ -1129,12 +1569,29 @@ namespace Internal.IL
return true;
}
break;
+ case ".ctor":
+ if (metadataType.IsByReferenceOfT)
+ {
+ StackEntry byRefValueParamHolder = _stack.Pop();
+
+ // Allocate a slot on the shadow stack for the ByReference type
+ int spillIndex = _spilledExpressions.Count;
+ SpilledExpressionEntry spillEntry = new SpilledExpressionEntry(StackValueKind.ByRef, "byref" + _currentOffset, metadataType, spillIndex, this);
+ _spilledExpressions.Add(spillEntry);
+ LLVMValueRef addrOfValueType = LoadVarAddress(spillIndex, LocalVarKind.Temp, out TypeDesc unused);
+ var typedAddress = CastIfNecessary(_builder, addrOfValueType, LLVM.PointerType(LLVM.Int32Type(), 0));
+ LLVM.BuildStore(_builder, byRefValueParamHolder.ValueForStackKind(StackValueKind.ByRef, _builder, false), typedAddress);
+
+ _stack.Push(spillEntry);
+ return true;
+ }
+ break;
}
return false;
}
- private void HandleCall(MethodDesc callee, MethodSignature signature, ILOpcode opcode = ILOpcode.call, LLVMValueRef calliTarget = default(LLVMValueRef))
+ private void HandleCall(MethodDesc callee, MethodSignature signature, ILOpcode opcode = ILOpcode.call, TypeDesc constrainedType = null, LLVMValueRef calliTarget = default(LLVMValueRef))
{
var parameterCount = signature.Length + (signature.IsStatic ? 0 : 1);
// The last argument is the top of the stack. We need to reverse them and store starting at the first argument
@@ -1143,10 +1600,34 @@ namespace Internal.IL
{
argumentValues[argumentValues.Length - i - 1] = _stack.Pop();
}
- PushNonNull(HandleCall(callee, signature, argumentValues, opcode, calliTarget));
+
+ if (constrainedType != null)
+ {
+ if (signature.IsStatic)
+ {
+ // Constrained call on static method
+ ThrowHelper.ThrowInvalidProgramException(ExceptionStringID.InvalidProgramSpecific, _method);
+ }
+ StackEntry thisByRef = argumentValues[0];
+ if (thisByRef.Kind != StackValueKind.ByRef)
+ {
+ // Constrained call without byref
+ ThrowHelper.ThrowInvalidProgramException(ExceptionStringID.InvalidProgramSpecific, _method);
+ }
+
+ // If this is a constrained call and the 'this' pointer is a reference type, it's a byref,
+ // dereference it before calling.
+ if (!constrainedType.IsValueType)
+ {
+ TypeDesc objectType = thisByRef.Type.GetParameterType();
+ argumentValues[0] = new LoadExpressionEntry(StackValueKind.ObjRef, "thisPtr", thisByRef.ValueAsType(objectType, _builder), objectType);
+ }
+ }
+
+ PushNonNull(HandleCall(callee, signature, argumentValues, opcode, constrainedType, calliTarget));
}
- private ExpressionEntry HandleCall(MethodDesc callee, MethodSignature signature, StackEntry[] argumentValues, ILOpcode opcode = ILOpcode.call, LLVMValueRef calliTarget = default(LLVMValueRef), TypeDesc forcedReturnType = null)
+ private ExpressionEntry HandleCall(MethodDesc callee, MethodSignature signature, StackEntry[] argumentValues, ILOpcode opcode = ILOpcode.call, TypeDesc constrainedType = null, LLVMValueRef calliTarget = default(LLVMValueRef), TypeDesc forcedReturnType = null)
{
if (opcode == ILOpcode.callvirt && callee.IsVirtual)
{
@@ -1159,10 +1640,12 @@ namespace Internal.IL
var pointerSize = _compilation.NodeFactory.Target.PointerSize;
LLVMValueRef returnAddress;
- LLVMValueRef castReturnAddress;
+ LLVMValueRef castReturnAddress = default;
TypeDesc returnType = signature.ReturnType;
+
+ bool needsReturnSlot = NeedsReturnStackSlot(signature);
SpilledExpressionEntry returnSlot = null;
- if (!returnType.IsVoid)
+ if (needsReturnSlot)
{
int returnIndex = _spilledExpressions.Count;
returnSlot = new SpilledExpressionEntry(GetStackValueKind(returnType), callee?.Name + "_return", returnType, returnIndex, this);
@@ -1170,11 +1653,6 @@ namespace Internal.IL
returnAddress = LoadVarAddress(returnIndex, LocalVarKind.Temp, out TypeDesc unused);
castReturnAddress = LLVM.BuildPointerCast(_builder, returnAddress, LLVM.PointerType(LLVM.Int8Type(), 0), callee?.Name + "_castreturn");
}
- else
- {
- returnAddress = LLVM.ConstNull(LLVM.PointerType(LLVM.Int8Type(), 0));
- castReturnAddress = returnAddress;
- }
int offset = GetTotalParameterOffset() + GetTotalLocalOffset();
LLVMValueRef shadowStack = LLVM.BuildGEP(_builder, LLVM.GetFirstParam(_llvmFunction),
@@ -1182,16 +1660,25 @@ namespace Internal.IL
String.Empty);
var castShadowStack = LLVM.BuildPointerCast(_builder, shadowStack, LLVM.PointerType(LLVM.Int8Type(), 0), "castshadowstack");
- // argument offset
+ List<LLVMValueRef> llvmArgs = new List<LLVMValueRef>();
+ llvmArgs.Add(castShadowStack);
+ if (needsReturnSlot)
+ {
+ llvmArgs.Add(castReturnAddress);
+ }
+
+ // argument offset on the shadow stack
int argOffset = 0;
var instanceAdjustment = signature.IsStatic ? 0 : 1;
for (int index = 0; index < argumentValues.Length; index++)
{
StackEntry toStore = argumentValues[index];
+ bool isThisParameter = false;
TypeDesc argType;
if (index == 0 && !signature.IsStatic)
{
+ isThisParameter = true;
if (opcode == ILOpcode.calli)
argType = toStore.Type;
else if (callee.OwningType.IsValueType)
@@ -1205,10 +1692,23 @@ namespace Internal.IL
}
LLVMTypeRef valueType = GetLLVMTypeForTypeDesc(argType);
+ LLVMValueRef argValue = toStore.ValueAsType(valueType, _builder);
+
+ // Pass arguments as parameters if possible
+ if (!isThisParameter && CanStoreTypeOnStack(argType))
+ {
+ llvmArgs.Add(argValue);
+ }
+ // Otherwise store them on the shadow stack
+ else
+ {
+ // The previous argument might have left this type unaligned, so pad if necessary
+ argOffset = PadOffset(argType, argOffset);
- ImportStoreHelper(toStore.ValueAsType(valueType, _builder), valueType, castShadowStack, (uint)argOffset);
+ ImportStoreHelper(argValue, valueType, castShadowStack, (uint)argOffset);
- argOffset = PadNextOffset(argType, argOffset);
+ argOffset += argType.GetElementSize().AsInt;
+ }
}
LLVMValueRef fn;
@@ -1218,17 +1718,21 @@ namespace Internal.IL
}
else
{
- fn = LLVMFunctionForMethod(callee, signature.IsStatic ? null : argumentValues[0], opcode == ILOpcode.callvirt);
+ fn = LLVMFunctionForMethod(callee, signature.IsStatic ? null : argumentValues[0], opcode == ILOpcode.callvirt, constrainedType);
}
- LLVM.BuildCall(_builder, fn, new LLVMValueRef[] {
- castShadowStack,
- castReturnAddress}, string.Empty);
-
+ LLVMValueRef llvmReturn = LLVM.BuildCall(_builder, fn, llvmArgs.ToArray(), string.Empty);
if (!returnType.IsVoid)
{
- return returnSlot;
+ if (needsReturnSlot)
+ {
+ return returnSlot;
+ }
+ else
+ {
+ return new ExpressionEntry(GetStackValueKind(returnType), callee?.Name + "_return", llvmReturn, returnType);
+ }
}
else
{
@@ -1268,7 +1772,15 @@ namespace Internal.IL
string realMethodName = method.Name;
- if (!method.IsPInvoke && method is TypeSystem.Ecma.EcmaMethod)
+ if (method.IsPInvoke)
+ {
+ string entrypointName = method.GetPInvokeMethodMetadata().Name;
+ if(!String.IsNullOrEmpty(entrypointName))
+ {
+ realMethodName = entrypointName;
+ }
+ }
+ else if (!method.IsPInvoke && method is TypeSystem.Ecma.EcmaMethod)
{
realMethodName = ((TypeSystem.Ecma.EcmaMethod)method).GetRuntimeImportName() ?? method.Name;
}
@@ -1382,25 +1894,88 @@ namespace Internal.IL
LLVMTypeRef thunkSig = LLVM.FunctionType(GetLLVMTypeForTypeDesc(method.Signature.ReturnType), llvmParams, false);
LLVMValueRef thunkFunc = LLVM.AddFunction(compilation.Module, nativeName, thunkSig);
- LLVMBasicBlockRef block = LLVM.AppendBasicBlock(thunkFunc, "Block0");
+ LLVMBasicBlockRef shadowStackSetupBlock = LLVM.AppendBasicBlock(thunkFunc, "ShadowStackSetupBlock");
+ LLVMBasicBlockRef allocateShadowStackBlock = LLVM.AppendBasicBlock(thunkFunc, "allocateShadowStackBlock");
+ LLVMBasicBlockRef managedCallBlock = LLVM.AppendBasicBlock(thunkFunc, "ManagedCallBlock");
+
LLVMBuilderRef builder = LLVM.CreateBuilder();
- LLVM.PositionBuilderAtEnd(builder, block);
+ LLVM.PositionBuilderAtEnd(builder, shadowStackSetupBlock);
+
+ // Allocate shadow stack if it's null
+ LLVMValueRef shadowStackPtr = LLVM.BuildAlloca(builder, LLVM.PointerType(LLVM.Int8Type(), 0), "ShadowStackPtr");
+ LLVMValueRef savedShadowStack = LLVM.BuildLoad(builder, ShadowStackTop, "SavedShadowStack");
+ LLVM.BuildStore(builder, savedShadowStack, shadowStackPtr);
+ LLVMValueRef shadowStackNull = LLVM.BuildICmp(builder, LLVMIntPredicate.LLVMIntEQ, savedShadowStack, LLVM.ConstPointerNull(LLVM.PointerType(LLVM.Int8Type(), 0)), "ShadowStackNull");
+ LLVM.BuildCondBr(builder, shadowStackNull, allocateShadowStackBlock, managedCallBlock);
+
+ LLVM.PositionBuilderAtEnd(builder, allocateShadowStackBlock);
- LLVMValueRef shadowStack = LLVM.BuildLoad(builder, ShadowStackTop, "");
+ LLVMValueRef newShadowStack = LLVM.BuildArrayMalloc(builder, LLVM.Int8Type(), BuildConstInt32(1000000), "NewShadowStack");
+ LLVM.BuildStore(builder, newShadowStack, shadowStackPtr);
+ LLVM.BuildBr(builder, managedCallBlock);
+ LLVM.PositionBuilderAtEnd(builder, managedCallBlock);
+ LLVMTypeRef reversePInvokeFrameType = LLVM.StructType(new LLVMTypeRef[] { LLVM.PointerType(LLVM.Int8Type(), 0), LLVM.PointerType(LLVM.Int8Type(), 0) }, false);
+ LLVMValueRef reversePInvokeFrame = default(LLVMValueRef);
+ LLVMTypeRef reversePInvokeFunctionType = LLVM.FunctionType(LLVM.VoidType(), new LLVMTypeRef[] { LLVM.PointerType(reversePInvokeFrameType, 0) }, false);
+ if (method.IsNativeCallable)
+ {
+ reversePInvokeFrame = LLVM.BuildAlloca(builder, reversePInvokeFrameType, "ReversePInvokeFrame");
+ LLVMValueRef RhpReversePInvoke2 = GetOrCreateLLVMFunction("RhpReversePInvoke2", reversePInvokeFunctionType);
+ LLVM.BuildCall(builder, RhpReversePInvoke2, new LLVMValueRef[] { reversePInvokeFrame }, "");
+ }
+
+ LLVMValueRef shadowStack = LLVM.BuildLoad(builder, shadowStackPtr, "ShadowStack");
int curOffset = 0;
+ curOffset = PadNextOffset(method.Signature.ReturnType, curOffset);
+ LLVMValueRef calleeFrame = LLVM.BuildGEP(builder, shadowStack, new LLVMValueRef[] { BuildConstInt32(curOffset) }, "calleeFrame");
+
+ List<LLVMValueRef> llvmArgs = new List<LLVMValueRef>();
+ llvmArgs.Add(calleeFrame);
+
+ bool needsReturnSlot = NeedsReturnStackSlot(method.Signature);
+
+ if (needsReturnSlot)
+ {
+ // Slot for return value if necessary
+ llvmArgs.Add(shadowStack);
+ }
+
for (int i = 0; i < llvmParams.Length; i++)
{
- LLVMValueRef argAddr = LLVM.BuildGEP(builder, shadowStack, new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), (ulong)curOffset, LLVMMisc.False) }, "arg" + i);
- LLVM.BuildStore(builder, LLVM.GetParam(thunkFunc, (uint)i), CastIfNecessary(builder, argAddr, LLVM.PointerType(llvmParams[i], 0)));
- curOffset = PadNextOffset(method.Signature[i], curOffset);
+ LLVMValueRef argValue = LLVM.GetParam(thunkFunc, (uint)i);
+
+ if (CanStoreTypeOnStack(method.Signature[i]))
+ {
+ llvmArgs.Add(argValue);
+ }
+ else
+ {
+ curOffset = PadOffset(method.Signature[i], curOffset);
+ LLVMValueRef argAddr = LLVM.BuildGEP(builder, shadowStack, new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), (ulong)curOffset, LLVMMisc.False) }, "arg" + i);
+ LLVM.BuildStore(builder, argValue, CastIfNecessary(builder, argAddr, LLVM.PointerType(llvmParams[i], 0), $"parameter{i}_"));
+ curOffset = PadNextOffset(method.Signature[i], curOffset);
+ }
+ }
+
+ LLVMValueRef llvmReturnValue = LLVM.BuildCall(builder, managedFunction, llvmArgs.ToArray(), "");
+
+ if (method.IsNativeCallable)
+ {
+ LLVMValueRef RhpReversePInvokeReturn2 = GetOrCreateLLVMFunction("RhpReversePInvokeReturn2", reversePInvokeFunctionType);
+ LLVM.BuildCall(builder, RhpReversePInvokeReturn2, new LLVMValueRef[] { reversePInvokeFrame }, "");
}
- LLVMValueRef retAddr = LLVM.BuildGEP(builder, shadowStack, new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), (ulong)curOffset, LLVMMisc.False) }, "retAddr");
- LLVM.BuildCall(builder, managedFunction, new LLVMValueRef[] { shadowStack, retAddr }, "");
- if (method.Signature.ReturnType != compilation.TypeSystemContext.GetWellKnownType(WellKnownType.Void))
+ if (!method.Signature.ReturnType.IsVoid)
{
- LLVM.BuildRet(builder, LLVM.BuildLoad(builder, CastIfNecessary(builder, retAddr, LLVM.PointerType(GetLLVMTypeForTypeDesc(method.Signature.ReturnType), 0)), ""));
+ if (needsReturnSlot)
+ {
+ LLVM.BuildRet(builder, LLVM.BuildLoad(builder, CastIfNecessary(builder, shadowStack, LLVM.PointerType(GetLLVMTypeForTypeDesc(method.Signature.ReturnType), 0)), "returnValue"));
+ }
+ else
+ {
+ LLVM.BuildRet(builder, llvmReturnValue);
+ }
}
else
{
@@ -1411,7 +1986,7 @@ namespace Internal.IL
private void ImportCalli(int token)
{
MethodSignature methodSignature = (MethodSignature)_methodIL.GetObject(token);
- HandleCall(null, methodSignature, ILOpcode.calli, ((ExpressionEntry)_stack.Pop()).ValueAsType(LLVM.PointerType(_universalSignature, 0), _builder));
+ HandleCall(null, methodSignature, ILOpcode.calli, calliTarget: ((ExpressionEntry)_stack.Pop()).ValueAsType(LLVM.PointerType(GetLLVMSignatureForMethod(methodSignature), 0), _builder));
}
private void ImportLdFtn(int token, ILOpcode opCode)
@@ -1423,7 +1998,7 @@ namespace Internal.IL
StackEntry thisPointer = _stack.Pop();
if (method.IsVirtual)
{
- targetLLVMFunction = LLVMFunctionForMethod(method, thisPointer, true);
+ targetLLVMFunction = LLVMFunctionForMethod(method, thisPointer, true, null);
AddVirtualMethodReference(method);
}
}
@@ -1434,7 +2009,7 @@ namespace Internal.IL
if (targetLLVMFunction.Pointer.Equals(IntPtr.Zero))
{
- targetLLVMFunction = GetOrCreateLLVMFunction(_compilation.NameMangler.GetMangledMethodName(method).ToString());
+ targetLLVMFunction = GetOrCreateLLVMFunction(_compilation.NameMangler.GetMangledMethodName(method).ToString(), method.Signature);
}
var entry = new FunctionPointerEntry("ldftn", method, targetLLVMFunction, GetWellKnownType(WellKnownType.IntPtr), opCode == ILOpcode.ldvirtftn);
@@ -1470,9 +2045,6 @@ namespace Internal.IL
if (opcode == ILOpcode.br)
{
ImportFallthrough(target);
- //TODO: why does this illegal branch happen in System.Reflection.MemberFilter.ctor
- if (target.StartOffset == 0)
- throw new InvalidProgramException();
LLVM.BuildBr(_builder, GetLLVMBasicBlockForBlock(target));
}
else
@@ -1593,9 +2165,6 @@ namespace Internal.IL
}
}
}
- //TODO: why did this happen only during an optimized build of [System.Private.CoreLib]System.Threading.Lock.ReleaseContended
- if (target.StartOffset == 0)
- throw new NotImplementedException("cant branch to entry basic block");
ImportFallthrough(target);
ImportFallthrough(fallthrough);
@@ -1630,11 +2199,11 @@ namespace Internal.IL
var expressionPointer = pointer as ExpressionEntry;
if(type == null)
{
- type = GetWellKnownType(WellKnownType.Object).MakeByRefType();
+ type = GetWellKnownType(WellKnownType.Object);
}
LLVMValueRef pointerElementType = pointer.ValueAsType(type.MakePointerType(), _builder);
- _stack.Push(new LoadExpressionEntry(type != null ? GetStackValueKind(type) : StackValueKind.ByRef, "ldind",
+ _stack.Push(new LoadExpressionEntry(type != null ? GetStackValueKind(type) : StackValueKind.ByRef, $"Indirect{pointer.Name()}",
pointerElementType, type));
}
@@ -1827,6 +2396,7 @@ namespace Internal.IL
if(enumCleanTargetType != null && targetType.IsPrimitive)
{
if(enumCleanTargetType.IsWellKnownType(WellKnownType.Byte) ||
+ enumCleanTargetType.IsWellKnownType(WellKnownType.Char) ||
enumCleanTargetType.IsWellKnownType(WellKnownType.UInt16) ||
enumCleanTargetType.IsWellKnownType(WellKnownType.UInt32) ||
enumCleanTargetType.IsWellKnownType(WellKnownType.UInt64) ||
@@ -1915,26 +2485,12 @@ namespace Internal.IL
private void ImportConvert(WellKnownType wellKnownType, bool checkOverflow, bool unsigned)
{
StackEntry value = _stack.Pop();
- LLVMValueRef convertedValue;
TypeDesc destType = GetWellKnownType(wellKnownType);
- //conv.u for a pointer should change to a int8*
- if (wellKnownType == WellKnownType.UIntPtr)
- {
- if (value.Kind == StackValueKind.Int32)
- {
- convertedValue = LLVM.BuildIntToPtr(_builder, value.ValueAsInt32(_builder, false), LLVM.PointerType(LLVM.Int8Type(), 0), "conv.u");
- }
- else
- {
- convertedValue = value.ValueAsType(destType, _builder);
- }
- }
- else
- {
- convertedValue = value.ValueAsType(destType, _builder);
- }
- PushExpression(GetStackValueKind(destType), "conv", convertedValue, destType);
+ // Load the value and then convert it instead of using ValueAsType to avoid loading the incorrect size
+ LLVMValueRef loadedValue = value.ValueAsType(value.Type, _builder);
+ LLVMValueRef converted = CastIfNecessary(loadedValue, GetLLVMTypeForTypeDesc(destType), value.Name());
+ PushExpression(GetStackValueKind(destType), "conv", converted, destType);
}
private void ImportUnaryOperation(ILOpcode opCode)
@@ -2053,7 +2609,8 @@ namespace Internal.IL
else if (ldtokenValue is FieldDesc)
{
ldtokenKind = WellKnownType.RuntimeFieldHandle;
- value = new LdTokenEntry<FieldDesc>(StackValueKind.ValueType, null, (FieldDesc)ldtokenValue, LLVM.ConstInt(LLVM.Int32Type(), 0, LLVMMisc.False), GetWellKnownType(ldtokenKind));
+ LLVMValueRef fieldHandle = LLVM.ConstStruct(new LLVMValueRef[] { BuildConstInt32(0) }, true);
+ value = new LdTokenEntry<FieldDesc>(StackValueKind.ValueType, null, (FieldDesc)ldtokenValue, fieldHandle, GetWellKnownType(ldtokenKind));
_stack.Push(value);
}
else if (ldtokenValue is MethodDesc)
@@ -2126,6 +2683,7 @@ namespace Internal.IL
private void ImportConstrainedPrefix(int token)
{
+ _constrainedType = (TypeDesc)_methodIL.GetObject(token);
}
private void ImportNoPrefix(byte mask)
@@ -2186,7 +2744,49 @@ namespace Internal.IL
if (!isStatic)
_stack.Pop();
- return WebAssemblyObjectWriter.EmitGlobal(Module, field, _compilation.NameMangler);
+ ISymbolNode node;
+ MetadataType owningType = (MetadataType)field.OwningType;
+ LLVMValueRef staticBase;
+ int fieldOffset = field.Offset.AsInt;
+
+ // TODO: We need the right thread static per thread
+ if (field.IsThreadStatic)
+ {
+ node = _compilation.NodeFactory.TypeThreadStaticsSymbol(owningType);
+ staticBase = LoadAddressOfSymbolNode(node);
+ }
+
+ else if (field.HasGCStaticBase)
+ {
+ node = _compilation.NodeFactory.TypeGCStaticsSymbol(owningType);
+
+ // We can't use GCStatics in the data section until we can successfully call
+ // InitializeModules on startup, so stick with globals for now
+ //LLVMValueRef basePtrPtr = LoadAddressOfSymbolNode(node);
+ //staticBase = LLVM.BuildLoad(_builder, LLVM.BuildLoad(_builder, LLVM.BuildPointerCast(_builder, basePtrPtr, LLVM.PointerType(LLVM.PointerType(LLVM.PointerType(LLVM.Int8Type(), 0), 0), 0), "castBasePtrPtr"), "basePtr"), "base");
+ staticBase = WebAssemblyObjectWriter.EmitGlobal(Module, field, _compilation.NameMangler);
+ fieldOffset = 0;
+ }
+ else
+ {
+ node = _compilation.NodeFactory.TypeNonGCStaticsSymbol(owningType);
+ staticBase = LoadAddressOfSymbolNode(node);
+ }
+
+ _dependencies.Add(node);
+
+ // Run static constructor if necessary
+ // If the type is non-BeforeFieldInit, this is handled before calling any methods on it
+ if (owningType.IsBeforeFieldInit || (!owningType.IsBeforeFieldInit && owningType != _thisType))
+ {
+ TriggerCctor(owningType);
+ }
+
+ LLVMValueRef castStaticBase = LLVM.BuildPointerCast(_builder, staticBase, LLVM.PointerType(LLVM.Int8Type(), 0), owningType.Name + "_statics");
+ LLVMValueRef fieldAddr = LLVM.BuildGEP(_builder, castStaticBase, new LLVMValueRef[] { BuildConstInt32(fieldOffset) }, field.Name + "_addr");
+
+
+ return fieldAddr;
}
else
{
@@ -2194,18 +2794,39 @@ namespace Internal.IL
}
}
+ /// <summary>
+ /// Triggers a static constructor check and call for types that have them
+ /// </summary>
+ private void TriggerCctor(MetadataType type)
+ {
+ if (_compilation.TypeSystemContext.HasLazyStaticConstructor(type))
+ {
+ ISymbolNode classConstructionContextSymbol = _compilation.NodeFactory.TypeNonGCStaticsSymbol(type);
+ _dependencies.Add(classConstructionContextSymbol);
+ LLVMValueRef firstNonGcStatic = LoadAddressOfSymbolNode(classConstructionContextSymbol);
+
+ // TODO: Codegen could check whether it has already run rather than calling into EnsureClassConstructorRun
+ // but we'd have to figure out how to manage the additional basic blocks
+ LLVMValueRef classConstructionContextPtr = LLVM.BuildGEP(_builder, firstNonGcStatic, new LLVMValueRef[] { BuildConstInt32(-2) }, "classConstructionContext");
+ StackEntry classConstructionContext = new AddressExpressionEntry(StackValueKind.NativeInt, "classConstructionContext", classConstructionContextPtr, GetWellKnownType(WellKnownType.IntPtr));
+ MetadataType helperType = _compilation.TypeSystemContext.SystemModule.GetKnownType("System.Runtime.CompilerServices", "ClassConstructorRunner");
+ MethodDesc helperMethod = helperType.GetKnownMethod("EnsureClassConstructorRun", null);
+ HandleCall(helperMethod, helperMethod.Signature, new StackEntry[] { classConstructionContext });
+ }
+ }
+
private void ImportLoadField(int token, bool isStatic)
{
FieldDesc field = (FieldDesc)_methodIL.GetObject(token);
LLVMValueRef fieldAddress = GetFieldAddress(field, isStatic);
- PushLoadExpression(GetStackValueKind(field.FieldType), "ldfld_" + field.Name, fieldAddress, field.FieldType);
+ PushLoadExpression(GetStackValueKind(field.FieldType), $"Field_{field.Name}", fieldAddress, field.FieldType);
}
private void ImportAddressOfField(int token, bool isStatic)
{
FieldDesc field = (FieldDesc)_methodIL.GetObject(token);
LLVMValueRef fieldAddress = GetFieldAddress(field, isStatic);
- _stack.Push(new AddressExpressionEntry(StackValueKind.ByRef, "ldflda", fieldAddress, field.FieldType.MakePointerType()));
+ _stack.Push(new AddressExpressionEntry(StackValueKind.ByRef, $"FieldAddress_{field.Name}", fieldAddress, field.FieldType.MakeByRefType()));
}
private void ImportStoreField(int token, bool isStatic)
@@ -2240,8 +2861,10 @@ namespace Internal.IL
TypeDesc type = ResolveTypeToken(token);
var valueEntry = _stack.Pop();
var llvmType = GetLLVMTypeForTypeDesc(type);
- if (llvmType.TypeKind == LLVMTypeKind.LLVMArrayTypeKind)
+ if (llvmType.TypeKind == LLVMTypeKind.LLVMStructTypeKind)
+ {
ImportCallMemset(valueEntry.ValueAsType(LLVM.PointerType(LLVM.Int8Type(), 0), _builder), 0, type.GetElementSize().AsInt);
+ }
else if (llvmType.TypeKind == LLVMTypeKind.LLVMIntegerTypeKind)
LLVM.BuildStore(_builder, LLVM.ConstInt(llvmType, 0, LLVMMisc.False), valueEntry.ValueAsType(LLVM.PointerType(llvmType, 0), _builder));
else if (llvmType.TypeKind == LLVMTypeKind.LLVMPointerTypeKind)
@@ -2319,7 +2942,7 @@ namespace Internal.IL
StackEntry index = _stack.Pop();
StackEntry arrayReference = _stack.Pop();
var nullSafeElementType = elementType ?? GetWellKnownType(WellKnownType.Object);
- PushLoadExpression(GetStackValueKind(nullSafeElementType), "ldelem", GetElementAddress(index.ValueAsInt32(_builder, true), arrayReference.ValueAsType(LLVM.PointerType(LLVM.Int8Type(), 0), _builder), nullSafeElementType), nullSafeElementType);
+ PushLoadExpression(GetStackValueKind(nullSafeElementType), $"{arrayReference.Name()}Element", GetElementAddress(index.ValueAsInt32(_builder, true), arrayReference.ValueAsType(LLVM.PointerType(LLVM.Int8Type(), 0), _builder), nullSafeElementType), nullSafeElementType);
}
private void ImportStoreElement(int token)
@@ -2352,7 +2975,7 @@ namespace Internal.IL
StackEntry index = _stack.Pop();
StackEntry arrayReference = _stack.Pop();
- PushExpression(GetStackValueKind(byRefElement), "ldelema", GetElementAddress(index.ValueAsInt32(_builder, true), arrayReference.ValueAsType(LLVM.PointerType(LLVM.Int8Type(), 0), _builder), elementType), byRefElement);
+ PushExpression(GetStackValueKind(byRefElement), $"{arrayReference.Name()}ElementAddress", GetElementAddress(index.ValueAsInt32(_builder, true), arrayReference.ValueAsType(LLVM.PointerType(LLVM.Int8Type(), 0), _builder), elementType), byRefElement);
}
private LLVMValueRef GetElementAddress(LLVMValueRef elementPosition, LLVMValueRef arrayReference, TypeDesc arrayElementType)
@@ -2372,6 +2995,9 @@ namespace Internal.IL
private void ImportEndFinally()
{
+ // These are currently unreachable since we can't get into finally blocks.
+ // We'll need to change this once we have other finally block handling.
+ LLVM.BuildUnreachable(_builder);
}
private void ImportFallthrough(BasicBlock next)
@@ -2418,9 +3044,6 @@ namespace Internal.IL
if (entry == null)
throw new InvalidProgramException();
- if (currentEntry is SpilledExpressionEntry)
- continue; //this is already a sharable value
-
StoreTemp(entry.LocalIndex, currentEntry.ValueAsType(entry.Type, _builder));
}
}
@@ -2433,6 +3056,7 @@ namespace Internal.IL
private const string RuntimeImport = "RuntimeImports";
private const string InternalCalls = "InternalCalls";
private const string TypeCast = "TypeCast";
+ private const string DispatchResolve = "DispatchResolve";
private ExpressionEntry CallRuntime(TypeSystemContext context, string className, string methodName, StackEntry[] arguments, TypeDesc forcedReturnType = null)
{
MetadataType helperType = context.SystemModule.GetKnownType("System.Runtime", className);
@@ -2453,16 +3077,11 @@ namespace Internal.IL
private StackEntry NewSpillSlot(StackEntry entry)
{
- if (entry is SpilledExpressionEntry)
- return entry;
- else
- {
- var entryType = entry.Type ?? GetWellKnownType(WellKnownType.Object); //type is required here, currently the only time entry.Type is null is if someone has pushed a null literal
- var entryIndex = _spilledExpressions.Count;
- var newEntry = new SpilledExpressionEntry(entry.Kind, entry is ExpressionEntry ? ((ExpressionEntry)entry).Name : "spilled" + entryIndex, entryType, entryIndex, this);
- _spilledExpressions.Add(newEntry);
- return newEntry;
- }
+ var entryType = entry.Type ?? GetWellKnownType(WellKnownType.Object); //type is required here, currently the only time entry.Type is null is if someone has pushed a null literal
+ var entryIndex = _spilledExpressions.Count;
+ var newEntry = new SpilledExpressionEntry(entry.Kind, entry is ExpressionEntry ? ((ExpressionEntry)entry).Name : "spilled" + entryIndex, entryType, entryIndex, this);
+ _spilledExpressions.Add(newEntry);
+ return newEntry;
}
private StackEntry TakeAddressOf(StackEntry entry)
@@ -2535,6 +3154,7 @@ namespace Internal.IL
TrapFunction = LLVM.AddFunction(Module, "llvm.trap", LLVM.FunctionType(LLVM.VoidType(), Array.Empty<LLVMTypeRef>(), false));
}
LLVM.BuildCall(_builder, TrapFunction, Array.Empty<LLVMValueRef>(), string.Empty);
+ LLVM.BuildUnreachable(_builder);
}
private void EmitDoNothingCall()
diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter_Statics.cs b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter_Statics.cs
index ad6bc1c78..5bbfc2906 100644
--- a/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter_Statics.cs
+++ b/src/ILCompiler.WebAssembly/src/CodeGen/ILToWebAssemblyImporter_Statics.cs
@@ -51,8 +51,9 @@ namespace Internal.IL
try
{
string mangledName;
- // TODO: We should use the startup node to generate StartupCodeMain and avoid special casing here
- if (methodCodeNodeNeedingCode.Method.Signature.IsStatic && methodCodeNodeNeedingCode.Method.Name == "Main")
+
+ // TODO: Better detection of the StartupCodeMain method
+ if (methodCodeNodeNeedingCode.Method.Signature.IsStatic && methodCodeNodeNeedingCode.Method.Name == "StartupCodeMain")
{
mangledName = "StartupCodeMain";
}
@@ -96,6 +97,17 @@ namespace Internal.IL
//methodCodeNodeNeedingCode.SetCode(sb.ToString(), Array.Empty<Object>());
}
+ // Uncomment the block below to get specific method failures when LLVM fails for cryptic reasons
+#if false
+ LLVMBool result = LLVM.VerifyFunction(ilImporter._llvmFunction, LLVMVerifierFailureAction.LLVMPrintMessageAction);
+ if (result.Value != 0)
+ {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine($"Error compliling {method.OwningType}.{method}");
+ Console.ResetColor();
+ }
+#endif // false
+
// Ensure dependencies show up regardless of exceptions to avoid breaking LLVM
methodCodeNodeNeedingCode.SetDependencies(ilImporter.GetDependencies());
}
diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/LLVMPInvokes.cs b/src/ILCompiler.WebAssembly/src/CodeGen/LLVMPInvokes.cs
new file mode 100644
index 000000000..708ef5b51
--- /dev/null
+++ b/src/ILCompiler.WebAssembly/src/CodeGen/LLVMPInvokes.cs
@@ -0,0 +1,78 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+using LLVMSharp;
+
+namespace ILCompiler.WebAssembly
+{
+ // LLVM P/Invokes copied from LLVMSharp that match the current LLVM surface area.
+ // If we get a new version of LLVMSharp containing these, this file should be removed.
+ internal class LLVMPInvokes
+ {
+ const string libraryPath = "libLLVM";
+ [DllImport(libraryPath, CallingConvention = CallingConvention.Cdecl)]
+ public static extern LLVMDIBuilderRef LLVMCreateDIBuilder(LLVMModuleRef M);
+
+ [DllImport(libraryPath, EntryPoint = "LLVMDIBuilderCreateCompileUnit", CallingConvention = CallingConvention.Cdecl)]
+ public static extern LLVMMetadataRef LLVMDIBuilderCreateCompileUnit(LLVMDIBuilderRef @Builder, LLVMDWARFSourceLanguage @Lang, LLVMMetadataRef @FileRef, [MarshalAs(UnmanagedType.LPStr)] string @Producer, size_t @ProducerLen, LLVMBool @isOptimized, [MarshalAs(UnmanagedType.LPStr)] string @Flags, size_t @FlagsLen, uint @RuntimeVer, [MarshalAs(UnmanagedType.LPStr)] string @SplitName, size_t @SplitNameLen, LLVMDWARFEmissionKind @Kind, uint @DWOId, LLVMBool @SplitDebugInlining, LLVMBool @DebugInfoForProfiling);
+
+ [DllImport(libraryPath, EntryPoint = "LLVMDIBuilderCreateFile", CallingConvention = CallingConvention.Cdecl)]
+ public static extern LLVMMetadataRef LLVMDIBuilderCreateFile(LLVMDIBuilderRef @Builder, [MarshalAs(UnmanagedType.LPStr)] string @Filename, size_t @FilenameLen, [MarshalAs(UnmanagedType.LPStr)] string @Directory, size_t @DirectoryLen);
+
+ [DllImport(libraryPath, EntryPoint = "LLVMDIBuilderCreateDebugLocation", CallingConvention = CallingConvention.Cdecl)]
+ public static extern LLVMMetadataRef LLVMDIBuilderCreateDebugLocation(LLVMContextRef @Ctx, uint @Line, uint @Column, LLVMMetadataRef @Scope, LLVMMetadataRef @InlinedAt);
+ }
+
+ internal enum LLVMDWARFSourceLanguage : int
+ {
+ @LLVMDWARFSourceLanguageC89 = 0,
+ @LLVMDWARFSourceLanguageC = 1,
+ @LLVMDWARFSourceLanguageAda83 = 2,
+ @LLVMDWARFSourceLanguageC_plus_plus = 3,
+ @LLVMDWARFSourceLanguageCobol74 = 4,
+ @LLVMDWARFSourceLanguageCobol85 = 5,
+ @LLVMDWARFSourceLanguageFortran77 = 6,
+ @LLVMDWARFSourceLanguageFortran90 = 7,
+ @LLVMDWARFSourceLanguagePascal83 = 8,
+ @LLVMDWARFSourceLanguageModula2 = 9,
+ @LLVMDWARFSourceLanguageJava = 10,
+ @LLVMDWARFSourceLanguageC99 = 11,
+ @LLVMDWARFSourceLanguageAda95 = 12,
+ @LLVMDWARFSourceLanguageFortran95 = 13,
+ @LLVMDWARFSourceLanguagePLI = 14,
+ @LLVMDWARFSourceLanguageObjC = 15,
+ @LLVMDWARFSourceLanguageObjC_plus_plus = 16,
+ @LLVMDWARFSourceLanguageUPC = 17,
+ @LLVMDWARFSourceLanguageD = 18,
+ @LLVMDWARFSourceLanguagePython = 19,
+ @LLVMDWARFSourceLanguageOpenCL = 20,
+ @LLVMDWARFSourceLanguageGo = 21,
+ @LLVMDWARFSourceLanguageModula3 = 22,
+ @LLVMDWARFSourceLanguageHaskell = 23,
+ @LLVMDWARFSourceLanguageC_plus_plus_03 = 24,
+ @LLVMDWARFSourceLanguageC_plus_plus_11 = 25,
+ @LLVMDWARFSourceLanguageOCaml = 26,
+ @LLVMDWARFSourceLanguageRust = 27,
+ @LLVMDWARFSourceLanguageC11 = 28,
+ @LLVMDWARFSourceLanguageSwift = 29,
+ @LLVMDWARFSourceLanguageJulia = 30,
+ @LLVMDWARFSourceLanguageDylan = 31,
+ @LLVMDWARFSourceLanguageC_plus_plus_14 = 32,
+ @LLVMDWARFSourceLanguageFortran03 = 33,
+ @LLVMDWARFSourceLanguageFortran08 = 34,
+ @LLVMDWARFSourceLanguageRenderScript = 35,
+ @LLVMDWARFSourceLanguageBLISS = 36,
+ @LLVMDWARFSourceLanguageMips_Assembler = 37,
+ @LLVMDWARFSourceLanguageGOOGLE_RenderScript = 38,
+ @LLVMDWARFSourceLanguageBORLAND_Delphi = 39,
+ }
+
+ internal enum LLVMDWARFEmissionKind : int
+ {
+ @LLVMDWARFEmissionNone = 0,
+ @LLVMDWARFEmissionFull = 1,
+ @LLVMDWARFEmissionLineTablesOnly = 2,
+ }
+}
diff --git a/src/ILCompiler.WebAssembly/src/CodeGen/WebAssemblyObjectWriter.cs b/src/ILCompiler.WebAssembly/src/CodeGen/WebAssemblyObjectWriter.cs
index 8808a2e02..f89f1ce97 100644
--- a/src/ILCompiler.WebAssembly/src/CodeGen/WebAssemblyObjectWriter.cs
+++ b/src/ILCompiler.WebAssembly/src/CodeGen/WebAssemblyObjectWriter.cs
@@ -144,6 +144,8 @@ namespace ILCompiler.DependencyAnalysis
// this is the llvm instance.
public LLVMModuleRef Module { get; }
+ public LLVMDIBuilderRef DIBuilder { get; }
+
// This is used to build mangled names
private Utf8StringBuilder _sb = new Utf8StringBuilder();
@@ -181,6 +183,9 @@ namespace ILCompiler.DependencyAnalysis
}
EmitNativeMain();
+
+ EmitDebugMetadata();
+
LLVM.WriteBitcodeToFile(Module, _objectFilePath);
#if DEBUG
LLVM.PrintModuleToFile(Module, Path.ChangeExtension(_objectFilePath, ".txt"), out string unused2);
@@ -190,6 +195,25 @@ namespace ILCompiler.DependencyAnalysis
//throw new NotImplementedException(); // This function isn't complete
}
+ private void EmitDebugMetadata()
+ {
+ var dwarfVersion = LLVM.MDNode(new[]
+ {
+ LLVM.ConstInt(LLVM.Int32Type(), 2, false),
+ LLVM.MDString("Dwarf Version", 13),
+ LLVM.ConstInt(LLVM.Int32Type(), 4, false)
+ });
+ var dwarfSchemaVersion = LLVM.MDNode(new[]
+ {
+ LLVM.ConstInt(LLVM.Int32Type(), 2, false),
+ LLVM.MDString("Debug Info Version", 18),
+ LLVM.ConstInt(LLVM.Int32Type(), 3, false)
+ });
+ LLVM.AddNamedMetadataOperand(Module, "llvm.module.flags", dwarfVersion);
+ LLVM.AddNamedMetadataOperand(Module, "llvm.module.flags", dwarfSchemaVersion);
+ LLVM.DIBuilderFinalize(DIBuilder);
+ }
+
public static LLVMValueRef GetConstZeroArray(int length)
{
var int8Type = LLVM.Int8Type();
@@ -225,6 +249,19 @@ namespace ILCompiler.DependencyAnalysis
throw new NotImplementedException();
}
+ private void EmitReadyToRunHeaderCallback()
+ {
+ LLVMTypeRef intPtr = LLVM.PointerType(LLVM.Int32Type(), 0);
+ LLVMTypeRef intPtrPtr = LLVM.PointerType(intPtr, 0);
+ var callback = LLVM.AddFunction(Module, "RtRHeaderWrapper", LLVM.FunctionType(intPtrPtr, new LLVMTypeRef[0], false));
+ var builder = LLVM.CreateBuilder();
+ var block = LLVM.AppendBasicBlock(callback, "Block");
+ LLVM.PositionBuilderAtEnd(builder, block);
+
+ LLVMValueRef rtrHeaderPtr = GetSymbolValuePointer(Module, _nodeFactory.ReadyToRunHeader, _nodeFactory.NameMangler, false);
+ LLVMValueRef castRtrHeaderPtr = LLVM.BuildPointerCast(builder, rtrHeaderPtr, intPtrPtr, "castRtrHeaderPtr");
+ LLVM.BuildRet(builder, castRtrHeaderPtr);
+ }
private void EmitNativeMain()
{
@@ -243,20 +280,32 @@ namespace ILCompiler.DependencyAnalysis
LLVMTypeRef reversePInvokeFrameType = LLVM.StructType(new LLVMTypeRef[] { LLVM.PointerType(LLVM.Int8Type(), 0), LLVM.PointerType(LLVM.Int8Type(), 0) }, false);
LLVMValueRef reversePinvokeFrame = LLVM.BuildAlloca(builder, reversePInvokeFrameType, "ReversePInvokeFrame");
- LLVMValueRef RhpReversePInvoke2 = LLVM.AddFunction(Module, "RhpReversePInvoke2", LLVM.FunctionType(LLVM.VoidType(), new LLVMTypeRef[] { LLVM.PointerType(reversePInvokeFrameType, 0) }, false));
+ LLVMValueRef RhpReversePInvoke2 = LLVM.GetNamedFunction(Module, "RhpReversePInvoke2");
+
+ if (RhpReversePInvoke2.Pointer == IntPtr.Zero)
+ {
+ RhpReversePInvoke2 = LLVM.AddFunction(Module, "RhpReversePInvoke2", LLVM.FunctionType(LLVM.VoidType(), new LLVMTypeRef[] { LLVM.PointerType(reversePInvokeFrameType, 0) }, false));
+ }
+
LLVM.BuildCall(builder, RhpReversePInvoke2, new LLVMValueRef[] { reversePinvokeFrame }, "");
var shadowStack = LLVM.BuildMalloc(builder, LLVM.ArrayType(LLVM.Int8Type(), 1000000), String.Empty);
var castShadowStack = LLVM.BuildPointerCast(builder, shadowStack, LLVM.PointerType(LLVM.Int8Type(), 0), String.Empty);
LLVM.BuildStore(builder, castShadowStack, shadowStackTop);
- LLVM.BuildCall(builder, managedMain, new LLVMValueRef[]
+
+ // Pass on main arguments
+ LLVMValueRef argc = LLVM.GetParam(mainFunc, 0);
+ LLVMValueRef argv = LLVM.GetParam(mainFunc, 1);
+
+ LLVMValueRef mainReturn = LLVM.BuildCall(builder, managedMain, new LLVMValueRef[]
{
castShadowStack,
- LLVM.ConstPointerNull(LLVM.PointerType(LLVM.Int8Type(), 0))
+ argc,
+ argv,
},
- String.Empty);
+ "returnValue");
- LLVM.BuildRet(builder, LLVM.ConstInt(LLVM.Int32Type(), 42, LLVMMisc.False));
+ LLVM.BuildRet(builder, mainReturn);
LLVM.SetLinkage(mainFunc, LLVMLinkage.LLVMExternalLinkage);
}
@@ -474,13 +523,15 @@ namespace ILCompiler.DependencyAnalysis
delta = checked(delta + sizeof(int));
}
+ int totalOffset = checked(delta + offsetFromSymbolName);
+
EmitBlob(new byte[this._nodeFactory.Target.PointerSize]);
if (relocType == RelocType.IMAGE_REL_BASED_REL32)
{
return this._nodeFactory.Target.PointerSize;
}
- _currentObjectSymbolRefs.Add(symbolStartOffset, new SymbolRefData(isFunction, realSymbolName, delta));
+ _currentObjectSymbolRefs.Add(symbolStartOffset, new SymbolRefData(isFunction, realSymbolName, totalOffset));
return _nodeFactory.Target.PointerSize;
}
@@ -618,6 +669,7 @@ namespace ILCompiler.DependencyAnalysis
_nodeFactory = factory;
_objectFilePath = objectFilePath;
Module = compilation.Module;
+ DIBuilder = compilation.DIBuilder;
}
public void Dispose()
@@ -699,6 +751,7 @@ namespace ILCompiler.DependencyAnalysis
try
{
+ objectWriter.EmitReadyToRunHeaderCallback();
//ObjectNodeSection managedCodeSection = null;
var listOfOffsets = new List<int>();
diff --git a/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyCodegenNodeFactory.cs b/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyCodegenNodeFactory.cs
index a43a1e572..2c09fc8fd 100644
--- a/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyCodegenNodeFactory.cs
+++ b/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyCodegenNodeFactory.cs
@@ -51,7 +51,7 @@ namespace ILCompiler.DependencyAnalysis
protected override IMethodNode CreateUnboxingStubNode(MethodDesc method)
{
- return new WebAssemblyMethodCodeNode(TypeSystemContext.GetUnboxingThunk(method, CompilationModuleGroup.GeneratedAssembly));
+ return new WebAssemblyMethodCodeNode(TypeSystemContext.GetUnboxingThunk(method, TypeSystemContext.GeneratedAssembly));
}
protected override ISymbolNode CreateReadyToRunHelperNode(ReadyToRunHelperKey helperCall)
diff --git a/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyMethodCodeNode.cs b/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyMethodCodeNode.cs
index 0cfd4382c..0405b88d2 100644
--- a/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyMethodCodeNode.cs
+++ b/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyMethodCodeNode.cs
@@ -68,9 +68,9 @@ namespace ILCompiler.DependencyAnalysis
public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) => null;
public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null;
- int ISortableSymbolNode.ClassCode => -1502960727;
+ int ISortableNode.ClassCode => -1502960727;
- int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer)
+ int ISortableNode.CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_method, ((WebAssemblyMethodCodeNode)other)._method);
}
diff --git a/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyVTableSlotNode.cs b/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyVTableSlotNode.cs
index 6f7897a8f..5122f8dc0 100644
--- a/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyVTableSlotNode.cs
+++ b/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyVTableSlotNode.cs
@@ -61,15 +61,24 @@ namespace ILCompiler.DependencyAnalysis
if (!relocsOnly)
{
- var tableOffset = EETypeNode.GetVTableOffset(factory.Target.PointerSize) / factory.Target.PointerSize;
- objData.EmitInt(tableOffset + VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, _targetMethod));
+ int tableOffset;
+ if (_targetMethod.OwningType.IsInterface)
+ {
+ tableOffset = 0;
+ }
+ else
+ {
+ tableOffset = EETypeNode.GetVTableOffset(factory.Target.PointerSize) / factory.Target.PointerSize;
+ }
+
+ objData.EmitInt(tableOffset + VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, _targetMethod, _targetMethod.OwningType));
}
return objData.ToObjectData();
}
- protected override int ClassCode => 0;
+ public override int ClassCode => 0;
- protected override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer)
+ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
{
return comparer.Compare(_targetMethod, ((WebAssemblyVTableSlotNode)other)._targetMethod);
}
diff --git a/src/ILCompiler.WebAssembly/src/Compiler/WebAssemblyCodegenCompilation.cs b/src/ILCompiler.WebAssembly/src/Compiler/WebAssemblyCodegenCompilation.cs
index 5a32248a7..e49cbba16 100644
--- a/src/ILCompiler.WebAssembly/src/Compiler/WebAssemblyCodegenCompilation.cs
+++ b/src/ILCompiler.WebAssembly/src/Compiler/WebAssemblyCodegenCompilation.cs
@@ -9,6 +9,7 @@ using Internal.TypeSystem;
using ILCompiler.DependencyAnalysis;
using ILCompiler.DependencyAnalysisFramework;
using LLVMSharp;
+using ILCompiler.WebAssembly;
namespace ILCompiler
{
@@ -17,18 +18,23 @@ namespace ILCompiler
internal WebAssemblyCodegenConfigProvider Options { get; }
internal LLVMModuleRef Module { get; }
public new WebAssemblyCodegenNodeFactory NodeFactory { get; }
+ internal LLVMDIBuilderRef DIBuilder { get; }
+ internal Dictionary<string, DebugMetadata> DebugMetadataMap { get; }
internal WebAssemblyCodegenCompilation(
DependencyAnalyzerBase<NodeFactory> dependencyGraph,
WebAssemblyCodegenNodeFactory nodeFactory,
IEnumerable<ICompilationRootProvider> roots,
+ DebugInformationProvider debugInformationProvider,
Logger logger,
WebAssemblyCodegenConfigProvider options)
- : base(dependencyGraph, nodeFactory, GetCompilationRoots(roots, nodeFactory), null, null, logger)
+ : base(dependencyGraph, nodeFactory, GetCompilationRoots(roots, nodeFactory), debugInformationProvider, null, logger)
{
NodeFactory = nodeFactory;
Module = LLVM.ModuleCreateWithName("netscripten");
LLVM.SetTarget(Module, "asmjs-unknown-emscripten");
Options = options;
+ DIBuilder = LLVMPInvokes.LLVMCreateDIBuilder(Module);
+ DebugMetadataMap = new Dictionary<string, DebugMetadata>();
}
private static IEnumerable<ICompilationRootProvider> GetCompilationRoots(IEnumerable<ICompilationRootProvider> existingRoots, NodeFactory factory)
diff --git a/src/ILCompiler.WebAssembly/src/Compiler/WebAssemblyCodegenCompilationBuilder.cs b/src/ILCompiler.WebAssembly/src/Compiler/WebAssemblyCodegenCompilationBuilder.cs
index 48bfaa15b..3b40a60f7 100644
--- a/src/ILCompiler.WebAssembly/src/Compiler/WebAssemblyCodegenCompilationBuilder.cs
+++ b/src/ILCompiler.WebAssembly/src/Compiler/WebAssemblyCodegenCompilationBuilder.cs
@@ -31,11 +31,10 @@ namespace ILCompiler
public override ICompilation ToCompilation()
{
- var interopStubManager = new CompilerGeneratedInteropStubManager(_compilationGroup, _context, new InteropStateManager(_compilationGroup.GeneratedAssembly));
+ var interopStubManager = new CompilerGeneratedInteropStubManager(_compilationGroup, _context, new InteropStateManager(_context.GeneratedAssembly));
WebAssemblyCodegenNodeFactory factory = new WebAssemblyCodegenNodeFactory(_context, _compilationGroup, _metadataManager, interopStubManager, _nameMangler, _vtableSliceProvider, _dictionaryLayoutProvider);
- DependencyAnalyzerBase<NodeFactory> graph = CreateDependencyGraph(factory);
-
- return new WebAssemblyCodegenCompilation(graph, factory, _compilationRoots, _logger, _config);
+ DependencyAnalyzerBase<NodeFactory> graph = CreateDependencyGraph(factory, new ObjectNode.ObjectNodeComparer(new CompilerComparer()));
+ return new WebAssemblyCodegenCompilation(graph, factory, _compilationRoots, _debugInformationProvider, _logger, _config);
}
}
diff --git a/src/ILCompiler.WebAssembly/src/ILCompiler.WebAssembly.csproj b/src/ILCompiler.WebAssembly/src/ILCompiler.WebAssembly.csproj
index 58b4c14eb..26e9f3253 100644
--- a/src/ILCompiler.WebAssembly/src/ILCompiler.WebAssembly.csproj
+++ b/src/ILCompiler.WebAssembly/src/ILCompiler.WebAssembly.csproj
@@ -37,8 +37,10 @@
<Compile Include="..\..\Common\src\TypeSystem\IL\HelperExtensions.cs">
<Link>IL\HelperExtensions.cs</Link>
</Compile>
+ <Compile Include="CodeGen\DebugMetadata.cs" />
<Compile Include="CodeGen\ILToWebAssemblyImporter_Statics.cs" />
<Compile Include="CodeGen\LLVMMisc.cs" />
+ <Compile Include="CodeGen\LLVMPInvokes.cs" />
<Compile Include="CodeGen\WebAssemblyObjectWriter.cs" />
<Compile Include="Compiler\DependencyAnalysis\RawMainMethodRootProvider.cs" />
<Compile Include="Compiler\DependencyAnalysis\WebAssemblyCodegenNodeFactory.cs" />
@@ -56,13 +58,13 @@
<Content Include="..\..\..\packages\llvmsharp\5.0.0\lib\netstandard1.1\LLVMSharp.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="..\..\..\packages\libllvm\4.0.0\runtimes\osx\native\libLLVM.dylib" Condition="'$(NuPkgRid)' == 'osx-x64'">
+ <Content Include="..\..\..\packages\libllvm\6.0.0-beta1\runtimes\osx\native\libLLVM.dylib" Condition="'$(NuPkgRid)' == 'osx-x64'">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="..\..\..\packages\libllvm\4.0.0\runtimes\linux-x64\native\libLLVM.so" Condition="'$(NuPkgRid)' == 'linux-x64'">
+ <Content Include="..\..\..\packages\libllvm\6.0.0-beta1\runtimes\linux-x64\native\libLLVM.so" Condition="'$(NuPkgRid)' == 'linux-x64'">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
- <Content Include="..\..\..\packages\libllvm\4.0.0\runtimes\win-x64\native\libLLVM.dll" Condition="'$(NuPkgRid)' == 'win-x64' or '$(NuPkgRid)' == ''">
+ <Content Include="..\..\..\packages\libllvm\6.0.0-beta1\runtimes\win-x64\native\libLLVM.dll" Condition="'$(NuPkgRid)' == 'win-x64' or '$(NuPkgRid)' == ''">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
diff --git a/src/ILCompiler.WebAssembly/src/libLLVMdep.depproj b/src/ILCompiler.WebAssembly/src/libLLVMdep.depproj
index 5c1bac3da..97b7dd4b9 100644
--- a/src/ILCompiler.WebAssembly/src/libLLVMdep.depproj
+++ b/src/ILCompiler.WebAssembly/src/libLLVMdep.depproj
@@ -13,7 +13,7 @@
<ItemGroup>
<PackageReference Include="libLLVM">
- <Version>4.0.0</Version>
+ <Version>6.0.0-beta1</Version>
</PackageReference>
</ItemGroup>
diff --git a/src/ILCompiler/ObjectWriter/ObjectWriter.depproj b/src/ILCompiler/ObjectWriter/ObjectWriter.depproj
index d1f46b4ae..6046fd628 100644
--- a/src/ILCompiler/ObjectWriter/ObjectWriter.depproj
+++ b/src/ILCompiler/ObjectWriter/ObjectWriter.depproj
@@ -5,12 +5,9 @@
</PropertyGroup>
<PropertyGroup>
- <NuGetTargetMoniker>.NETCoreApp,Version=v2.0</NuGetTargetMoniker>
- <TargetFramework>netcoreapp2.0</TargetFramework>
+ <NuGetTargetMoniker>.NETCoreApp,Version=v2.1</NuGetTargetMoniker>
+ <TargetFramework>netcoreapp2.1</TargetFramework>
<RuntimeIdentifiers>$(NuPkgRid)</RuntimeIdentifiers>
- <RuntimeIdentifiers Condition="'$(NuPkgRid)'=='win-x64'">win7-x64</RuntimeIdentifiers>
- <RuntimeIdentifiers Condition="'$(NuPkgRid)'=='osx-x64'">osx.10.10-x64</RuntimeIdentifiers>
- <RuntimeIdentifiers Condition="'$(NuPkgRid)'=='linux-x64'">ubuntu.14.04-x64</RuntimeIdentifiers>
<RidSpecificAssets>true</RidSpecificAssets>
</PropertyGroup>
diff --git a/src/ILCompiler/RyuJIT/RyuJIT.depproj b/src/ILCompiler/RyuJIT/RyuJIT.depproj
index 1eb94f741..c8aa48a87 100644
--- a/src/ILCompiler/RyuJIT/RyuJIT.depproj
+++ b/src/ILCompiler/RyuJIT/RyuJIT.depproj
@@ -5,8 +5,8 @@
</PropertyGroup>
<PropertyGroup>
- <NuGetTargetMoniker>.NETCoreApp,Version=v2.0</NuGetTargetMoniker>
- <TargetFramework>netcoreapp2.0</TargetFramework>
+ <NuGetTargetMoniker>.NETCoreApp,Version=v2.1</NuGetTargetMoniker>
+ <TargetFramework>netcoreapp2.1</TargetFramework>
<RuntimeIdentifiers>$(NuPkgRid)</RuntimeIdentifiers>
<RidSpecificAssets>true</RidSpecificAssets>
</PropertyGroup>
diff --git a/src/ILCompiler/netcoreapp/ilc.csproj b/src/ILCompiler/netcoreapp/ilc.csproj
index 1feb02316..06240cfef 100644
--- a/src/ILCompiler/netcoreapp/ilc.csproj
+++ b/src/ILCompiler/netcoreapp/ilc.csproj
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
- <TargetFramework>netcoreapp2.0</TargetFramework>
+ <TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
diff --git a/src/ILCompiler/repro/repro.csproj b/src/ILCompiler/repro/repro.csproj
index 5e3e75312..e8ec9a042 100644
--- a/src/ILCompiler/repro/repro.csproj
+++ b/src/ILCompiler/repro/repro.csproj
@@ -3,16 +3,22 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<AssemblyName>repro</AssemblyName>
- <TargetFramework>netcoreapp2.0</TargetFramework>
+ <TargetFramework>netcoreapp2.1</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<SkipSigning>true</SkipSigning>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<CopyNuGetImplementations>false</CopyNuGetImplementations>
+
+ <!-- Supress warnings that often happen in repro code -->
+ <NoWarn>169;414</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NETCore.App">
<Version>$(MicrosoftNETCoreAppPackageVersion)</Version>
</PackageReference>
+ <PackageReference Include="System.Runtime.CompilerServices.Unsafe">
+ <Version>4.5.1</Version>
+ </PackageReference>
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
diff --git a/src/ILCompiler/repro/repro.ilproj b/src/ILCompiler/repro/repro.ilproj
index 2c4942695..8fdd23d40 100644
--- a/src/ILCompiler/repro/repro.ilproj
+++ b/src/ILCompiler/repro/repro.ilproj
@@ -3,7 +3,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<AssemblyName>repro</AssemblyName>
- <TargetFramework>netcoreapp2.0</TargetFramework>
+ <TargetFramework>netcoreapp2.1</TargetFramework>
<SkipSigning>true</SkipSigning>
</PropertyGroup>
<ItemGroup>
diff --git a/src/ILCompiler/reproNative/reproNative.vcxproj b/src/ILCompiler/reproNative/reproNative.vcxproj
index 9d9f6eed2..3b88d1751 100644
--- a/src/ILCompiler/reproNative/reproNative.vcxproj
+++ b/src/ILCompiler/reproNative/reproNative.vcxproj
@@ -62,7 +62,7 @@
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
- <AdditionalDependencies>..\..\..\bin\obj\Windows_NT.x64.Debug\repro\native\repro.obj;kernel32.lib;user32.lib;gdi32.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;bcrypt.lib;%(AdditionalDependencies);..\..\..\bin\Windows_NT.x64.Debug\sdk\Runtime.lib</AdditionalDependencies>
+ <AdditionalDependencies>..\..\..\bin\obj\Windows_NT.x64.Debug\repro\native\repro.obj;kernel32.lib;user32.lib;gdi32.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;bcrypt.lib;%(AdditionalDependencies);..\..\..\bin\Windows_NT.x64.Debug\sdk\Runtime.lib;..\..\..\bin\Windows_NT.x64.Debug\sdk\System.Private.TypeLoader.Native.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -84,7 +84,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <AdditionalDependencies>..\..\..\bin\obj\Windows_NT.x64.Release\repro\native\repro.obj;kernel32.lib;user32.lib;gdi32.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;bcrypt.lib;%(AdditionalDependencies);..\..\..\bin\Windows_NT.x64.Release\sdk\Runtime.lib</AdditionalDependencies>
+ <AdditionalDependencies>..\..\..\bin\obj\Windows_NT.x64.Release\repro\native\repro.obj;kernel32.lib;user32.lib;gdi32.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;bcrypt.lib;%(AdditionalDependencies);..\..\..\bin\Windows_NT.x64.Release\sdk\Runtime.lib;..\..\..\bin\Windows_NT.x64.Release\sdk\System.Private.TypeLoader.Native.lib</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
diff --git a/src/ILCompiler/src/ILCompiler.csproj b/src/ILCompiler/src/ILCompiler.csproj
index 75d6ba4e2..4e437223e 100644
--- a/src/ILCompiler/src/ILCompiler.csproj
+++ b/src/ILCompiler/src/ILCompiler.csproj
@@ -8,7 +8,7 @@
<RootNamespace>ILCompiler</RootNamespace>
<AssemblyName>ilc</AssemblyName>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
- <TargetFramework>netcoreapp2.0</TargetFramework>
+ <TargetFramework>netcoreapp2.1</TargetFramework>
<CopyNugetImplementations>false</CopyNugetImplementations>
<!-- Force .dll extension even if output type is exe. -->
<TargetExt>.dll</TargetExt>
diff --git a/src/ILCompiler/src/Program.cs b/src/ILCompiler/src/Program.cs
index e869f7540..cd75a913e 100644
--- a/src/ILCompiler/src/Program.cs
+++ b/src/ILCompiler/src/Program.cs
@@ -17,6 +17,8 @@ namespace ILCompiler
{
internal class Program
{
+ private const string DefaultSystemModule = "System.Private.CoreLib";
+
private Dictionary<string, string> _inputFilePaths = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
private Dictionary<string, string> _referenceFilePaths = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
@@ -37,7 +39,7 @@ namespace ILCompiler
private OptimizationMode _optimizationMode;
private bool _enableDebugInfo;
private string _ilDump;
- private string _systemModuleName = "System.Private.CoreLib";
+ private string _systemModuleName = DefaultSystemModule;
private bool _multiFile;
private bool _nativeLib;
private string _exportsFile;
@@ -47,6 +49,8 @@ namespace ILCompiler
private bool _emitStackTraceData;
private string _mapFileName;
private string _metadataLogFileName;
+ private bool _noMetadataBlocking;
+ private bool _completeTypesMetadata;
private string _singleMethodTypeName;
private string _singleMethodName;
@@ -56,6 +60,12 @@ namespace ILCompiler
private IReadOnlyList<string> _rdXmlFilePaths = Array.Empty<string>();
+ private IReadOnlyList<string> _initAssemblies = Array.Empty<string>();
+
+ private IReadOnlyList<string> _appContextSwitches = Array.Empty<string>();
+
+ private IReadOnlyList<string> _runtimeOptions = Array.Empty<string>();
+
private bool _help;
private Program()
@@ -88,20 +98,20 @@ namespace ILCompiler
switch (RuntimeInformation.ProcessArchitecture)
{
- case Architecture.X86:
- _targetArchitecture = TargetArchitecture.X86;
- break;
- case Architecture.X64:
- _targetArchitecture = TargetArchitecture.X64;
- break;
- case Architecture.Arm:
- _targetArchitecture = TargetArchitecture.ARM;
- break;
- case Architecture.Arm64:
- _targetArchitecture = TargetArchitecture.ARM64;
- break;
- default:
- throw new NotImplementedException();
+ case Architecture.X86:
+ _targetArchitecture = TargetArchitecture.X86;
+ break;
+ case Architecture.X64:
+ _targetArchitecture = TargetArchitecture.X64;
+ break;
+ case Architecture.Arm:
+ _targetArchitecture = TargetArchitecture.ARM;
+ break;
+ case Architecture.Arm64:
+ _targetArchitecture = TargetArchitecture.ARM64;
+ break;
+ default:
+ throw new NotImplementedException();
}
// Workaround for https://github.com/dotnet/corefx/issues/25267
@@ -149,10 +159,15 @@ namespace ILCompiler
syntax.DefineOptionList("rdxml", ref _rdXmlFilePaths, "RD.XML file(s) for compilation");
syntax.DefineOption("map", ref _mapFileName, "Generate a map file");
syntax.DefineOption("metadatalog", ref _metadataLogFileName, "Generate a metadata log file");
+ syntax.DefineOption("nometadatablocking", ref _noMetadataBlocking, "Ignore metadata blocking for internal implementation details");
+ syntax.DefineOption("completetypemetadata", ref _completeTypesMetadata, "Generate complete metadata for types");
syntax.DefineOption("scan", ref _useScanner, "Use IL scanner to generate optimized code (implied by -O)");
syntax.DefineOption("noscan", ref _noScanner, "Do not use IL scanner to generate optimized code");
syntax.DefineOption("ildump", ref _ilDump, "Dump IL assembly listing for compiler-generated IL");
syntax.DefineOption("stacktracedata", ref _emitStackTraceData, "Emit data to support generating stack trace strings at runtime");
+ syntax.DefineOptionList("initassembly", ref _initAssemblies, "Assembly(ies) with a library initializer");
+ syntax.DefineOptionList("appcontextswitch", ref _appContextSwitches, "System.AppContext switches to set");
+ syntax.DefineOptionList("runtimeopt", ref _runtimeOptions, "Runtime options to set");
syntax.DefineOption("targetarch", ref _targetArchitectureStr, "Target architecture for cross compilation");
syntax.DefineOption("targetos", ref _targetOSStr, "Target OS for cross compilation");
@@ -180,6 +195,33 @@ namespace ILCompiler
return argSyntax;
}
+ private IReadOnlyCollection<MethodDesc> CreateInitializerList(TypeSystemContext context)
+ {
+ List<ModuleDesc> assembliesWithInitalizers = new List<ModuleDesc>();
+
+ // Build a list of assemblies that have an initializer that needs to run before
+ // any user code runs.
+ foreach (string initAssemblyName in _initAssemblies)
+ {
+ ModuleDesc assembly = context.ResolveAssembly(new AssemblyName(initAssemblyName));
+ assembliesWithInitalizers.Add(assembly);
+ }
+
+ var libraryInitializers = new LibraryInitializers(context, assembliesWithInitalizers);
+
+ List<MethodDesc> initializerList = new List<MethodDesc>(libraryInitializers.LibraryInitializerMethods);
+
+ // If there are any AppContext switches the user wishes to enable, generate code that sets them.
+ if (_appContextSwitches.Count > 0)
+ {
+ MethodDesc appContextInitMethod = new Internal.IL.Stubs.StartupCode.AppContextInitializerMethod(
+ context.GeneratedAssembly.GetGlobalModuleType(), _appContextSwitches);
+ initializerList.Add(appContextInitMethod);
+ }
+
+ return initializerList;
+ }
+
private int Run(string[] args)
{
InitializeDefaultOptions();
@@ -190,7 +232,7 @@ namespace ILCompiler
Help(syntax.GetHelpText());
return 1;
}
-
+
if (_outputFilePath == null)
throw new CommandLineException("Output filename must be specified (/out <file>)");
@@ -231,6 +273,7 @@ namespace ILCompiler
if (_isWasmCodegen)
_targetArchitecture = TargetArchitecture.Wasm32;
+
//
// Initialize type system context
//
@@ -239,8 +282,9 @@ namespace ILCompiler
SharedGenericsMode.CanonicalReferenceTypes : SharedGenericsMode.Disabled;
// TODO: compiler switch for SIMD support?
- var simdVectorLength = (_isCppCodegen || _isWasmCodegen) ? SimdVectorLength.None : SimdVectorLength.Vector128Bit;
- var targetDetails = new TargetDetails(_targetArchitecture, _targetOS, TargetAbi.CoreRT, simdVectorLength);
+ var simdVectorLength = (_isCppCodegen || _isWasmCodegen) ? SimdVectorLength.None : SimdVectorLength.Vector128Bit;
+ var targetAbi = _isCppCodegen ? TargetAbi.CppCodegen : TargetAbi.CoreRT;
+ var targetDetails = new TargetDetails(_targetArchitecture, _targetOS, targetAbi, simdVectorLength);
var typeSystemContext = new CompilerTypeSystemContext(targetDetails, genericsMode);
//
@@ -309,15 +353,8 @@ namespace ILCompiler
if (entrypointModule != null)
{
- LibraryInitializers libraryInitializers =
- new LibraryInitializers(typeSystemContext, _isCppCodegen);
- compilationRoots.Add(new MainMethodRootProvider(entrypointModule, libraryInitializers.LibraryInitializerMethods));
- }
- else if (_nativeLib)
- {
- EcmaModule module = (EcmaModule)typeSystemContext.SystemModule;
- LibraryInitializers libraryInitializers = new LibraryInitializers(typeSystemContext, _isCppCodegen);
- compilationRoots.Add(new NativeLibraryInitializerRootProvider(module, libraryInitializers.LibraryInitializerMethods));
+ compilationRoots.Add(new MainMethodRootProvider(entrypointModule, CreateInitializerList(typeSystemContext)));
+ compilationRoots.Add(new RuntimeConfigurationRootProvider(_runtimeOptions));
}
if (_multiFile)
@@ -344,8 +381,15 @@ namespace ILCompiler
throw new Exception("No entrypoint module");
compilationRoots.Add(new ExportedMethodsRootProvider((EcmaModule)typeSystemContext.SystemModule));
+ compilationGroup = new SingleFileCompilationModuleGroup();
+ }
- compilationGroup = new SingleFileCompilationModuleGroup(typeSystemContext);
+ if (_nativeLib)
+ {
+ // Set owning module of generated native library startup method to compiler generated module,
+ // to ensure the startup method is included in the object file during multimodule mode build
+ compilationRoots.Add(new NativeLibraryInitializerRootProvider(typeSystemContext.GeneratedAssembly, CreateInitializerList(typeSystemContext)));
+ compilationRoots.Add(new RuntimeConfigurationRootProvider(_runtimeOptions));
}
if (_rdXmlFilePaths.Count > 0)
@@ -371,12 +415,27 @@ namespace ILCompiler
var stackTracePolicy = _emitStackTraceData ?
(StackTraceEmissionPolicy)new EcmaMethodStackTraceEmissionPolicy() : new NoStackTraceEmissionPolicy();
+ MetadataBlockingPolicy mdBlockingPolicy = _noMetadataBlocking ?
+ (MetadataBlockingPolicy)new NoMetadataBlockingPolicy() : new BlockedInternalsBlockingPolicy();
+
+ ManifestResourceBlockingPolicy resBlockingPolicy = new NoManifestResourceBlockingPolicy();
+
+ UsageBasedMetadataGenerationOptions metadataGenerationOptions = UsageBasedMetadataGenerationOptions.None;
+ if (_completeTypesMetadata)
+ metadataGenerationOptions |= UsageBasedMetadataGenerationOptions.CompleteTypesOnly;
+
+ DynamicInvokeThunkGenerationPolicy invokeThunkGenerationPolicy = new DefaultDynamicInvokeThunkGenerationPolicy();
+
UsageBasedMetadataManager metadataManager = new UsageBasedMetadataManager(
compilationGroup,
typeSystemContext,
- new BlockedInternalsBlockingPolicy(),
+ mdBlockingPolicy,
+ resBlockingPolicy,
_metadataLogFileName,
- stackTracePolicy);
+ stackTracePolicy,
+ invokeThunkGenerationPolicy,
+ metadataGenerationOptions
+ );
// Unless explicitly opted in at the command line, we enable scanner for retail builds by default.
// We don't do this for CppCodegen and Wasm, because those codegens are behind.
@@ -388,7 +447,9 @@ namespace ILCompiler
useScanner &= !_noScanner;
- MetadataManager compilationMetadataManager = _isWasmCodegen ? (MetadataManager)new EmptyMetadataManager(typeSystemContext) : metadataManager;
+ bool supportsReflection = !_isWasmCodegen && !_isCppCodegen && _systemModuleName == DefaultSystemModule;
+
+ MetadataManager compilationMetadataManager = supportsReflection ? metadataManager : (MetadataManager)new EmptyMetadataManager(typeSystemContext);
ILScanResults scanResults = null;
if (useScanner)
{
@@ -494,7 +555,7 @@ namespace ILCompiler
// We additionally skip methods in SIMD module because there's just too many intrisics to handle and IL scanner
// doesn't expand them. They would show up as noisy diffs.
DiffCompilationResults(ref dummy, scanResults.CompiledMethodBodies, compilationResults.CompiledMethodBodies,
- "Methods", "scanned", "compiled", method => !(method.GetTypicalMethodDefinition() is EcmaMethod) || simdHelper.IsInSimdModule(method.OwningType));
+ "Methods", "scanned", "compiled", method => !(method.GetTypicalMethodDefinition() is EcmaMethod) || simdHelper.IsSimdType(method.OwningType));
DiffCompilationResults(ref dummy, scanResults.ConstructedEETypes, compilationResults.ConstructedEETypes,
"EETypes", "scanned", "compiled", type => !(type.GetTypeDefinition() is EcmaType));
}
diff --git a/src/ILVerification/src/ILVerification.csproj b/src/ILVerification/src/ILVerification.csproj
index efa6e5349..8d058dbf6 100644
--- a/src/ILVerification/src/ILVerification.csproj
+++ b/src/ILVerification/src/ILVerification.csproj
@@ -7,8 +7,12 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<TargetFramework>netstandard1.3</TargetFramework>
- <AssemblyKey></AssemblyKey>
<AssemblyOriginatorKeyFile>..\StrongNameKeys\ILVerify.snk</AssemblyOriginatorKeyFile>
+ <SignAssembly>true</SignAssembly>
+ <!-- Suppress signing done by buildtools sign.targets -->
+ <SkipSigning>true</SkipSigning>
+ <!-- Delete once we pick up fix for https://github.com/dotnet/roslyn/issues/8210 -->
+ <DelaySign Condition="'$(OS)' != 'Windows_NT'">true</DelaySign>
</PropertyGroup>
<ItemGroup>
@@ -77,6 +81,9 @@
<Compile Include="..\..\Common\src\TypeSystem\Common\ExceptionStringID.cs">
<Link>TypeSystem\Common\ExceptionStringID.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\src\TypeSystem\Common\Utilities\DebugNameFormatter.cs">
+ <Link>Utilities\DebugNameFormatter.cs</Link>
+ </Compile>
<Compile Include="..\..\Common\src\TypeSystem\Common\FieldForInstantiatedType.cs">
<Link>TypeSystem\Common\FieldForInstantiatedType.cs</Link>
</Compile>
@@ -86,6 +93,9 @@
<Compile Include="..\..\Common\src\TypeSystem\Common\FieldDesc.FieldLayout.cs">
<Link>TypeSystem\Common\FieldDesc.FieldLayout.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\src\TypeSystem\Common\FieldDesc.ToString.cs">
+ <Link>TypeSystem\Common\FieldDesc.ToString.cs</Link>
+ </Compile>
<Compile Include="..\..\Common\src\TypeSystem\Common\FieldLayoutAlgorithm.cs">
<Link>TypeSystem\Common\FieldLayoutAlgorithm.cs</Link>
</Compile>
@@ -167,6 +177,9 @@
<Compile Include="..\..\Common\src\TypeSystem\Common\MethodDesc.cs">
<Link>TypeSystem\Common\MethodDesc.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\src\TypeSystem\Common\MethodDesc.ToString.cs">
+ <Link>TypeSystem\Common\MethodDesc.ToString.cs</Link>
+ </Compile>
<Compile Include="..\..\Common\src\TypeSystem\Common\MetadataVirtualMethodAlgorithm.cs">
<Link>TypeSystem\Common\StandardVirtualMethodAlgorithm.cs</Link>
</Compile>
@@ -176,6 +189,9 @@
<Compile Include="..\..\Common\src\TypeSystem\Common\TypeDesc.Interfaces.cs">
<Link>TypeSystem\Common\TypeDesc.Interfaces.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\src\TypeSystem\Common\TypeDesc.ToString.cs">
+ <Link>TypeSystem\Common\TypeDesc.ToString.cs</Link>
+ </Compile>
<Compile Include="..\..\Common\src\TypeSystem\Common\DefType.cs">
<Link>TypeSystem\Common\DefType.cs</Link>
</Compile>
diff --git a/src/ILVerification/src/ILVerifyTypeSystemContext.cs b/src/ILVerification/src/ILVerifyTypeSystemContext.cs
index 528dc6a90..96aaa3fd9 100644
--- a/src/ILVerification/src/ILVerifyTypeSystemContext.cs
+++ b/src/ILVerification/src/ILVerifyTypeSystemContext.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
@@ -29,18 +30,39 @@ namespace ILVerify
public override ModuleDesc ResolveAssembly(AssemblyName name, bool throwIfNotFound = true)
{
- PEReader peReader = _resolver.Resolve(name);
- if (peReader == null && throwIfNotFound)
+ // Note: we use simple names instead of full names to resolve, because we can't get a full name from an assembly without reading it
+ string simpleName = name.Name;
+ return ResolveAssemblyOrNetmodule(simpleName, simpleName, throwIfNotFound);
+ }
+
+ internal override ModuleDesc ResolveModule(ModuleDesc referencingModule, string fileName, bool throwIfNotFound = true)
+ {
+ // Referenced modules are stored without their extension (see CommandLineHelpers.cs), so we have to drop
+ // the extension here as well to find a match.
+ string simpleName = Path.GetFileNameWithoutExtension(fileName);
+ // The referencing module is not getting verified currently.
+ // However, netmodules are resolved in the context of assembly, not in the global context.
+ EcmaModule module = ResolveAssemblyOrNetmodule(simpleName, fileName, throwIfNotFound);
+ if (module.MetadataReader.IsAssembly)
{
- throw new VerifierException("Assembly or module not found: " + name.Name);
+ throw new VerifierException($"The module '{fileName}' is not expected to be an assembly");
}
+ return module;
+ }
+ private EcmaModule ResolveAssemblyOrNetmodule(string simpleName, string verificationName, bool throwIfNotFound)
+ {
+ PEReader peReader = _resolver.Resolve(simpleName);
+ if (peReader == null && throwIfNotFound)
+ {
+ throw new VerifierException("Assembly or module not found: " + simpleName);
+ }
var module = GetModule(peReader);
- VerifyModuleName(name, module);
+ VerifyModuleName(verificationName, module);
return module;
}
- private static void VerifyModuleName(AssemblyName name, EcmaModule module)
+ private static void VerifyModuleName(string simpleName, EcmaModule module)
{
MetadataReader metadataReader = module.MetadataReader;
StringHandle nameHandle = metadataReader.IsAssembly
@@ -48,9 +70,9 @@ namespace ILVerify
: metadataReader.GetModuleDefinition().Name;
string actualSimpleName = metadataReader.GetString(nameHandle);
- if (!actualSimpleName.Equals(name.Name, StringComparison.OrdinalIgnoreCase))
+ if (!actualSimpleName.Equals(simpleName, StringComparison.OrdinalIgnoreCase))
{
- throw new VerifierException($"Actual PE name '{actualSimpleName}' does not match provided name '{name}'");
+ throw new VerifierException($"Actual PE name '{actualSimpleName}' does not match provided name '{simpleName}'");
}
}
diff --git a/src/ILVerification/src/IResolver.cs b/src/ILVerification/src/IResolver.cs
index f3706cf3b..aec09c82a 100644
--- a/src/ILVerification/src/IResolver.cs
+++ b/src/ILVerification/src/IResolver.cs
@@ -13,7 +13,7 @@ namespace ILVerify
/// <summary>
/// This method should return the same instance when queried multiple times.
/// </summary>
- PEReader Resolve(AssemblyName name);
+ PEReader Resolve(string simpleName);
}
/// <summary>
@@ -23,16 +23,14 @@ namespace ILVerify
{
private readonly Dictionary<string, PEReader> _resolverCache = new Dictionary<string, PEReader>();
- public PEReader Resolve(AssemblyName name)
+ public PEReader Resolve(string simpleName)
{
- // Note: we use simple names instead of full names to resolve, because we can't get a full name from an assembly without reading it
- string simpleName = name.Name;
if (_resolverCache.TryGetValue(simpleName, out PEReader peReader))
{
return peReader;
}
- PEReader result = ResolveCore(name);
+ PEReader result = ResolveCore(simpleName);
if (result != null)
{
_resolverCache.Add(simpleName, result);
@@ -42,6 +40,6 @@ namespace ILVerify
return null;
}
- protected abstract PEReader ResolveCore(AssemblyName name);
+ protected abstract PEReader ResolveCore(string simpleName);
}
}
diff --git a/src/ILVerification/src/Verifier.cs b/src/ILVerification/src/Verifier.cs
index 9341ef395..ef9374f14 100644
--- a/src/ILVerification/src/Verifier.cs
+++ b/src/ILVerification/src/Verifier.cs
@@ -34,7 +34,12 @@ namespace ILVerify
public void SetSystemModuleName(AssemblyName name)
{
- _typeSystemContext.SetSystemModule(_typeSystemContext.GetModule(_typeSystemContext._resolver.Resolve(name)));
+ PEReader peReader = _typeSystemContext._resolver.Resolve(name.Name);
+ if (peReader is null)
+ {
+ throw new VerifierException("Assembly or module not found: " + name.FullName);
+ }
+ _typeSystemContext.SetSystemModule(_typeSystemContext.GetModule(peReader));
}
internal EcmaModule GetModule(PEReader peReader)
@@ -161,7 +166,7 @@ namespace ILVerify
private IEnumerable<VerificationResult> VerifyMethod(EcmaModule module, MethodIL methodIL, MethodDefinitionHandle methodHandle)
{
var builder = new ArrayBuilder<VerificationResult>();
- MethodDesc method = methodIL.OwningMethod;
+ MethodDesc method = methodIL.OwningMethod;
try
{
diff --git a/src/ILVerification/tests/ILMethodTester.cs b/src/ILVerification/tests/ILMethodTester.cs
index eb92c3dcb..871045ed0 100644
--- a/src/ILVerification/tests/ILMethodTester.cs
+++ b/src/ILVerification/tests/ILMethodTester.cs
@@ -20,7 +20,7 @@ namespace ILVerification.Tests
void TestMethodsWithValidIL(ValidILTestCase validIL)
{
var results = Verify(validIL);
- Assert.Equal(0, results.Count());
+ Assert.Empty(results);
}
[Theory(DisplayName = "")]
diff --git a/src/ILVerification/tests/ILTests/AccessTests.ilproj b/src/ILVerification/tests/ILTests/AccessTests.ilproj
new file mode 100644
index 000000000..8e8765d14
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/AccessTests.ilproj
@@ -0,0 +1,3 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILTests/AccessTestsExtern.ilproj b/src/ILVerification/tests/ILTests/AccessTestsExtern.ilproj
new file mode 100644
index 000000000..8e8765d14
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/AccessTestsExtern.ilproj
@@ -0,0 +1,3 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILTests/AccessTestsFriend.ilproj b/src/ILVerification/tests/ILTests/AccessTestsFriend.ilproj
new file mode 100644
index 000000000..8e8765d14
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/AccessTestsFriend.ilproj
@@ -0,0 +1,3 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILTests/ArrayTests.ilproj b/src/ILVerification/tests/ILTests/ArrayTests.ilproj
new file mode 100644
index 000000000..8e8765d14
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/ArrayTests.ilproj
@@ -0,0 +1,3 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILTests/BasicArithmeticTests.ilproj b/src/ILVerification/tests/ILTests/BasicArithmeticTests.ilproj
new file mode 100644
index 000000000..8e8765d14
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/BasicArithmeticTests.ilproj
@@ -0,0 +1,3 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILTests/BranchingTests.ilproj b/src/ILVerification/tests/ILTests/BranchingTests.ilproj
new file mode 100644
index 000000000..8e8765d14
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/BranchingTests.ilproj
@@ -0,0 +1,3 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILTests/CallTests.ilproj b/src/ILVerification/tests/ILTests/CallTests.ilproj
new file mode 100644
index 000000000..8e8765d14
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/CallTests.ilproj
@@ -0,0 +1,3 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILTests/CastingTests.ilproj b/src/ILVerification/tests/ILTests/CastingTests.ilproj
new file mode 100644
index 000000000..8e8765d14
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/CastingTests.ilproj
@@ -0,0 +1,3 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILTests/ComparisonTests.ilproj b/src/ILVerification/tests/ILTests/ComparisonTests.ilproj
new file mode 100644
index 000000000..8e8765d14
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/ComparisonTests.ilproj
@@ -0,0 +1,3 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILTests/DelegateTests.ilproj b/src/ILVerification/tests/ILTests/DelegateTests.ilproj
new file mode 100644
index 000000000..8e8765d14
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/DelegateTests.ilproj
@@ -0,0 +1,3 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILTests/ExceptionRegionTests.ilproj b/src/ILVerification/tests/ILTests/ExceptionRegionTests.ilproj
new file mode 100644
index 000000000..8e8765d14
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/ExceptionRegionTests.ilproj
@@ -0,0 +1,3 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILTests/FieldTests.ilproj b/src/ILVerification/tests/ILTests/FieldTests.ilproj
new file mode 100644
index 000000000..8e8765d14
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/FieldTests.ilproj
@@ -0,0 +1,3 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILTests/FtnTests.ilproj b/src/ILVerification/tests/ILTests/FtnTests.ilproj
new file mode 100644
index 000000000..8e8765d14
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/FtnTests.ilproj
@@ -0,0 +1,3 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILTests/ILTests.targets b/src/ILVerification/tests/ILTests/ILTests.targets
new file mode 100644
index 000000000..22983bd3a
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/ILTests.targets
@@ -0,0 +1,17 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+
+ <PropertyGroup>
+ <OutputType>Library</OutputType>
+ <AssemblyName>$(MSBuildProjectName)</AssemblyName>
+ <OutputPath>$(BaseOutputPath)$(OSPlatformConfig)/ILVerification.Tests/Tests</OutputPath>
+ <SkipTestRun>true</SkipTestRun>
+ <SkipSigning>true</SkipSigning>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Compile Include="$(MSBuildProjectName).il" />
+ </ItemGroup>
+
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILTests/LoadStoreIndirectTests.ilproj b/src/ILVerification/tests/ILTests/LoadStoreIndirectTests.ilproj
new file mode 100644
index 000000000..8e8765d14
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/LoadStoreIndirectTests.ilproj
@@ -0,0 +1,3 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILTests/NewobjTests.ilproj b/src/ILVerification/tests/ILTests/NewobjTests.ilproj
new file mode 100644
index 000000000..8e8765d14
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/NewobjTests.ilproj
@@ -0,0 +1,3 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILTests/PrefixTests.ilproj b/src/ILVerification/tests/ILTests/PrefixTests.ilproj
new file mode 100644
index 000000000..8e8765d14
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/PrefixTests.ilproj
@@ -0,0 +1,3 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILTests/ReturnTests.ilproj b/src/ILVerification/tests/ILTests/ReturnTests.ilproj
new file mode 100644
index 000000000..8e8765d14
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/ReturnTests.ilproj
@@ -0,0 +1,3 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILTests/ShiftTests.ilproj b/src/ILVerification/tests/ILTests/ShiftTests.ilproj
new file mode 100644
index 000000000..8e8765d14
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/ShiftTests.ilproj
@@ -0,0 +1,3 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILTests/ThisStateTests.ilproj b/src/ILVerification/tests/ILTests/ThisStateTests.ilproj
new file mode 100644
index 000000000..8e8765d14
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/ThisStateTests.ilproj
@@ -0,0 +1,3 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILTests/ValueTypeTests.ilproj b/src/ILVerification/tests/ILTests/ValueTypeTests.ilproj
new file mode 100644
index 000000000..8e8765d14
--- /dev/null
+++ b/src/ILVerification/tests/ILTests/ValueTypeTests.ilproj
@@ -0,0 +1,3 @@
+<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="ILTests.targets" />
+</Project>
diff --git a/src/ILVerification/tests/ILVerification.Tests.csproj b/src/ILVerification/tests/ILVerification.Tests.csproj
index 4d5f17abf..237655ccc 100644
--- a/src/ILVerification/tests/ILVerification.Tests.csproj
+++ b/src/ILVerification/tests/ILVerification.Tests.csproj
@@ -3,7 +3,7 @@
<PropertyGroup>
<OutputType>Library</OutputType>
- <TargetFramework>netstandard1.5</TargetFramework>
+ <TargetFramework>netstandard2.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
@@ -14,10 +14,8 @@
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0-preview-20170427-09" />
- <PackageReference Include="xunit" Version="2.2.0" />
- <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
- <PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
+ <PackageReference Include="xunit" Version="$(XUnitPackageVersion)" />
+ <PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
</ItemGroup>
<ItemGroup>
@@ -25,15 +23,19 @@
</ItemGroup>
<ItemGroup>
- <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
+ <ProjectReference Include="ILTests\*.ilproj">
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <OutputItemType>Content</OutputItemType>
+ </ProjectReference>
</ItemGroup>
<ItemGroup>
- <Folder Include="ILTests\" />
+ <Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
<ItemGroup>
- <None Include="..\..\ILVerification\StrongNameKeys\ILVerify.snk" Link="ILVerify.snk" />
+ <Folder Include="ILTests\" />
</ItemGroup>
+
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>
diff --git a/src/ILVerification/tests/TestDataLoader.cs b/src/ILVerification/tests/TestDataLoader.cs
index 91a1195f8..4184a5f6f 100644
--- a/src/ILVerification/tests/TestDataLoader.cs
+++ b/src/ILVerification/tests/TestDataLoader.cs
@@ -20,19 +20,17 @@ namespace ILVerification.Tests
{
/// <summary>
/// Parses the methods in the test assemblies.
- /// It loads all assemblies from the test folder defined in <code>TestDataLoader.TESTASSEMBLYPATH</code>
+ /// It loads all assemblies from the test folder defined in <code>TestDataLoader.TestAssemblyPath</code>
/// This class feeds the xunit Theories
/// </summary>
class TestDataLoader
{
/// <summary>
- /// The folder with the binaries which are compiled from the test driver IL Code
- /// Currently the test .il code is built manually, but the plan is to have a ProjectReference and automatically build the .il files.
- /// See: https://github.com/dotnet/corert/pull/3725#discussion_r118820770
+ /// The folder with the test binaries
/// </summary>
- public static string TESTASSEMBLYPATH = @"..\..\..\ILTests\";
+ private const string TestAssemblyPath = @"Tests\";
- private const string SPECIALTEST_PREFIX = "special.";
+ private const string SpecialTestPrefix = "special.";
/// <summary>
/// Returns all methods that contain valid IL code based on the following naming convention:
@@ -129,11 +127,11 @@ namespace ILVerification.Tests
private static MethodDefinitionHandle HandleSpecialTests(string[] methodParams, EcmaMethod method)
{
- if (!methodParams[0].StartsWith(SPECIALTEST_PREFIX))
+ if (!methodParams[0].StartsWith(SpecialTestPrefix))
return method.Handle;
// Cut off special prefix
- var specialParams = methodParams[0].Substring(SPECIALTEST_PREFIX.Length);
+ var specialParams = methodParams[0].Substring(SpecialTestPrefix.Length);
// Get friendly name / special name
int delimiter = specialParams.IndexOf('.');
@@ -152,7 +150,7 @@ namespace ILVerification.Tests
private static IEnumerable<string> GetAllTestDlls()
{
- foreach (var item in Directory.GetFiles(TESTASSEMBLYPATH))
+ foreach (var item in Directory.GetFiles(TestAssemblyPath))
{
if (item.ToLower().EndsWith(".dll"))
{
@@ -167,7 +165,7 @@ namespace ILVerification.Tests
foreach (var fileName in GetAllTestDlls())
{
- simpleNameToPathMap.Add(Path.GetFileNameWithoutExtension(fileName), TESTASSEMBLYPATH + fileName);
+ simpleNameToPathMap.Add(Path.GetFileNameWithoutExtension(fileName), TestAssemblyPath + fileName);
}
Assembly coreAssembly = typeof(object).GetTypeInfo().Assembly;
@@ -178,9 +176,9 @@ namespace ILVerification.Tests
var resolver = new TestResolver(simpleNameToPathMap);
var typeSystemContext = new ILVerifyTypeSystemContext(resolver);
- typeSystemContext.SetSystemModule(typeSystemContext.GetModule(resolver.Resolve(coreAssembly.GetName())));
+ typeSystemContext.SetSystemModule(typeSystemContext.GetModule(resolver.Resolve(coreAssembly.GetName().Name)));
- return typeSystemContext.GetModule(resolver.Resolve(new AssemblyName(Path.GetFileNameWithoutExtension(assemblyName))));
+ return typeSystemContext.GetModule(resolver.Resolve(new AssemblyName(Path.GetFileNameWithoutExtension(assemblyName)).Name));
}
private sealed class TestResolver : ResolverBase
@@ -191,9 +189,9 @@ namespace ILVerification.Tests
_simpleNameToPathMap = simpleNameToPathMap;
}
- protected override PEReader ResolveCore(AssemblyName name)
+ protected override PEReader ResolveCore(string simpleName)
{
- if (_simpleNameToPathMap.TryGetValue(name.Name, out string path))
+ if (_simpleNameToPathMap.TryGetValue(simpleName, out string path))
{
return new PEReader(File.OpenRead(path));
}
diff --git a/src/ILVerify/README.md b/src/ILVerify/README.md
index ef4d0d81f..286c70d50 100644
--- a/src/ILVerify/README.md
+++ b/src/ILVerify/README.md
@@ -17,7 +17,7 @@ Historically on Full Framework IL generators used PEVerify to make sure that the
- Fast spin up/tear down.
## The codebase
-The project targets netcoreapp2.0 and uses the new .csproj based project format. If you want to open and compile it with Visual Studio then you need a version, which supports .NET Core 2.0 tooling. This is supported in Visual Studio 2017 Update 3 (Version 15.3) or later. The other option is to use command (with .NET Core 2.0 tooling).
+The project targets netcoreapp2.1 and uses the new .csproj based project format. If you want to open and compile it with Visual Studio then you need a version, which supports .NET Core 2.1 tooling. This is supported in Visual Studio 2017 Version 15.8 or later. The other option is to use command (with .NET Core 2.1 tooling).
The code is split into three projects:
- ILVerification is the library with the core verification logic,
- ILVerification.Tests contains the tests for ILVerification,
@@ -27,18 +27,6 @@ The code is split into three projects:
To test the ILVerification library we have small methods checked in as .il files testing specific verification scenarios. These tests live under [src/ILVerification/tests/ILTests](../ILVerification/tests/ILTests). Tests are grouped into .il files based on functionalities they test. There is no strict policy here, the goal is to have a few dozen .il files instead of thousands containing each only a single method.
-Currently the IL files are NOT compiled automatically. You have to compile manually (We want to automate this step later):
-
-```
-ilasm [filename.il] /dll /ERROR
-```
-
-Note: if you run the tests and get an error similar to this then it means that the .il files were not compiled, or none of them contained methods that follow the naming convention described below:
-
-```
-Result Message: System.InvalidOperationException : No data found for ILVerify.Tests.ILMethodTester.TestMethodsWithInvalidIL
-```
-
The test project itself is under [src/ILVerification/tests](../ILVerification/tests)
Method names in the .il files must follow the following naming convention:
diff --git a/src/ILVerify/netcoreapp/ILVerify.csproj b/src/ILVerify/netcoreapp/ILVerify.csproj
index 47b7d3145..302e01f7d 100644
--- a/src/ILVerify/netcoreapp/ILVerify.csproj
+++ b/src/ILVerify/netcoreapp/ILVerify.csproj
@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
- <TargetFramework>netcoreapp2.0</TargetFramework>
+ <TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
diff --git a/src/ILVerify/src/ILVerify.csproj b/src/ILVerify/src/ILVerify.csproj
index 0f5d1e990..9042c8a85 100644
--- a/src/ILVerify/src/ILVerify.csproj
+++ b/src/ILVerify/src/ILVerify.csproj
@@ -4,9 +4,13 @@
<OutputType>Exe</OutputType>
<RootNamespace>ILVerify</RootNamespace>
<AssemblyName>ILVerify</AssemblyName>
- <AssemblyKey></AssemblyKey>
<AssemblyOriginatorKeyFile>..\..\ILVerification\StrongNameKeys\ILVerify.snk</AssemblyOriginatorKeyFile>
- <TargetFramework>netcoreapp2.0</TargetFramework>
+ <SignAssembly>true</SignAssembly>
+ <!-- Suppress signing done by buildtools sign.targets -->
+ <SkipSigning>true</SkipSigning>
+ <!-- Delete once we pick up fix for https://github.com/dotnet/roslyn/issues/8210 -->
+ <DelaySign Condition="'$(OS)' != 'Windows_NT'">true</DelaySign>
+ <TargetFramework>netcoreapp2.1</TargetFramework>
<CopyNugetImplementations>false</CopyNugetImplementations>
<!-- Force .dll extension even if output type is exe. -->
<TargetExt>.dll</TargetExt>
diff --git a/src/ILVerify/src/Program.cs b/src/ILVerify/src/Program.cs
index d748084b8..36e978512 100644
--- a/src/ILVerify/src/Program.cs
+++ b/src/ILVerify/src/Program.cs
@@ -10,6 +10,7 @@ using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
+using System.Text;
using System.Text.RegularExpressions;
using Internal.CommandLine;
using Internal.TypeSystem.Ecma;
@@ -20,6 +21,8 @@ namespace ILVerify
class Program : ResolverBase
{
private bool _help;
+ private bool _verbose;
+ private bool _printStatistics;
private AssemblyName _systemModule = new AssemblyName("mscorlib");
private Dictionary<string, string> _inputFilePaths = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); // map of simple name to file path
@@ -73,6 +76,8 @@ namespace ILVerify
syntax.DefineOption("include-file", ref includeFile, "Same as --include, but the regular expression(s) are declared line by line in the specified file.");
syntax.DefineOptionList("e|exclude", ref excludePatterns, "Skip methods/types/namespaces, which match the given regular expression(s)");
syntax.DefineOption("exclude-file", ref excludeFile, "Same as --exclude, but the regular expression(s) are declared line by line in the specified file.");
+ syntax.DefineOption("statistics", ref _printStatistics, "Print verification statistics");
+ syntax.DefineOption("v|verbose", ref _verbose, "Verbose output");
syntax.DefineParameterList("in", ref inputFiles, "Input file(s)");
});
@@ -99,6 +104,25 @@ namespace ILVerify
}
_excludePatterns = StringPatternsToRegexList(excludePatterns);
+ if (_verbose)
+ {
+ WriteLine();
+ foreach (var path in _inputFilePaths)
+ WriteLine($"Using input file '{path.Value}'");
+
+ WriteLine();
+ foreach (var path in _referenceFilePaths)
+ WriteLine($"Using reference file '{path.Value}'");
+
+ WriteLine();
+ foreach (var pattern in _includePatterns)
+ WriteLine($"Using include pattern '{pattern}'");
+
+ WriteLine();
+ foreach (var pattern in _excludePatterns)
+ WriteLine($"Using exclude pattern '{pattern}'");
+ }
+
return argSyntax;
}
@@ -119,19 +143,7 @@ namespace ILVerify
foreach (var kvp in _inputFilePaths)
{
- var results = VerifyAssembly(new AssemblyName(kvp.Key), out EcmaModule module);
- int numErrors = 0;
-
- foreach (var result in results)
- {
- numErrors++;
- PrintResult(result, module, kvp.Value);
- }
-
- if (numErrors > 0)
- WriteLine(numErrors + " Error(s) Verifying " + kvp.Value);
- else
- WriteLine("All Classes and Methods in " + kvp.Value + " Verified.");
+ VerifyAssembly(new AssemblyName(kvp.Key), kvp.Value);
}
return 0;
@@ -216,31 +228,84 @@ namespace ILVerify
Write(")");
}
- private IEnumerable<VerificationResult> VerifyAssembly(AssemblyName name, out EcmaModule module)
+ private void VerifyAssembly(AssemblyName name, string path)
{
- PEReader peReader = Resolve(name);
- module = _verifier.GetModule(peReader);
+ PEReader peReader = Resolve(name.Name);
+ EcmaModule module = _verifier.GetModule(peReader);
- return VerifyAssembly(peReader);
+ VerifyAssembly(peReader, module, path);
}
- private IEnumerable<VerificationResult> VerifyAssembly(PEReader peReader)
+ private void VerifyAssembly(PEReader peReader, EcmaModule module, string path)
{
+ int numErrors = 0;
+ int verifiedMethodCounter = 0;
+ int methodCounter = 0;
+
MetadataReader metadataReader = peReader.GetMetadataReader();
foreach (var methodHandle in metadataReader.MethodDefinitions)
{
- var methodName = metadataReader.GetString(metadataReader.GetMethodDefinition(methodHandle).Name);
- if (ShouldVerifyMethod(methodName))
+ // get fully qualified method name
+ var methodName = GetQualifiedMethodName(metadataReader, methodHandle);
+
+ bool verifying = ShouldVerifyMethod(methodName);
+ if (_verbose)
+ {
+ Write(verifying ? "Verifying " : "Skipping ");
+ WriteLine(methodName);
+ }
+
+ if (verifying)
{
var results = _verifier.Verify(peReader, methodHandle);
foreach (var result in results)
{
- yield return result;
+ PrintResult(result, module, path);
+ numErrors++;
}
+
+ verifiedMethodCounter++;
}
+
+ methodCounter++;
+ }
+
+ if (numErrors > 0)
+ WriteLine(numErrors + " Error(s) Verifying " + path);
+ else
+ WriteLine("All Classes and Methods in " + path + " Verified.");
+
+ if (_printStatistics)
+ {
+ WriteLine($"Methods found: {methodCounter}");
+ WriteLine($"Methods verified: {verifiedMethodCounter}");
}
}
+ /// <summary>
+ /// This method returns the fully qualified method name by concatenating assembly, type and method name.
+ /// This method exists to avoid additional assembly resolving, which might be triggered by calling
+ /// MethodDesc.ToString().
+ /// </summary>
+ private string GetQualifiedMethodName(MetadataReader metadataReader, MethodDefinitionHandle methodHandle)
+ {
+ var methodDef = metadataReader.GetMethodDefinition(methodHandle);
+ var typeDef = metadataReader.GetTypeDefinition(methodDef.GetDeclaringType());
+
+ var methodName = metadataReader.GetString(metadataReader.GetMethodDefinition(methodHandle).Name);
+ var typeName = metadataReader.GetString(typeDef.Name);
+ var namespaceName = metadataReader.GetString(typeDef.Namespace);
+ var assemblyName = metadataReader.GetString(metadataReader.IsAssembly ? metadataReader.GetAssemblyDefinition().Name : metadataReader.GetModuleDefinition().Name);
+
+ StringBuilder builder = new StringBuilder();
+ builder.Append($"[{assemblyName}]");
+ if (!string.IsNullOrEmpty(namespaceName))
+ builder.Append($"{namespaceName}.");
+ builder.Append($"{typeName}.{methodName}");
+
+ return builder.ToString();
+ }
+
private bool ShouldVerifyMethod(string methodName)
{
if (_includePatterns.Count > 0 && !_includePatterns.Any(p => p.IsMatch(methodName)))
@@ -256,11 +321,8 @@ namespace ILVerify
return true;
}
- protected override PEReader ResolveCore(AssemblyName name)
+ protected override PEReader ResolveCore(string simpleName)
{
- // Note: we use simple names instead of full names to resolve, because we can't get a full name from an assembly without reading it
- string simpleName = name.Name;
-
string path = null;
if (_inputFilePaths.TryGetValue(simpleName, out path) || _referenceFilePaths.TryGetValue(simpleName, out path))
{
diff --git a/src/JitInterface/src/CorInfoBase.cs b/src/JitInterface/src/CorInfoBase.cs
index 8ce1de300..f9f78d97a 100644
--- a/src/JitInterface/src/CorInfoBase.cs
+++ b/src/JitInterface/src/CorInfoBase.cs
@@ -320,6 +320,8 @@ namespace Internal.JitInterface
[UnmanagedFunctionPointerAttribute(default(CallingConvention))]
delegate void* __getTailCallCopyArgsThunk(IntPtr _this, IntPtr* ppException, CORINFO_SIG_INFO* pSig, CorInfoHelperTailCallSpecialHandling flags);
[UnmanagedFunctionPointerAttribute(default(CallingConvention))]
+ [return: MarshalAs(UnmanagedType.I1)]delegate bool __convertPInvokeCalliToCall(IntPtr _this, IntPtr* ppException, ref CORINFO_RESOLVED_TOKEN pResolvedToken, [MarshalAs(UnmanagedType.I1)]bool mustConvert);
+ [UnmanagedFunctionPointerAttribute(default(CallingConvention))]
delegate void* __getMemoryManager(IntPtr _this, IntPtr* ppException);
[UnmanagedFunctionPointerAttribute(default(CallingConvention))]
delegate void __allocMem(IntPtr _this, IntPtr* ppException, uint hotCodeSize, uint coldCodeSize, uint roDataSize, uint xcptnsCount, CorJitAllocMemFlag flag, ref void* hotCodeBlock, ref void* coldCodeBlock, ref void* roDataBlock);
@@ -2478,6 +2480,20 @@ namespace Internal.JitInterface
}
}
+ [return: MarshalAs(UnmanagedType.I1)]static bool _convertPInvokeCalliToCall(IntPtr thisHandle, IntPtr* ppException, ref CORINFO_RESOLVED_TOKEN pResolvedToken, [MarshalAs(UnmanagedType.I1)]bool mustConvert)
+ {
+ var _this = GetThis(thisHandle);
+ try
+ {
+ return _this.convertPInvokeCalliToCall(ref pResolvedToken, mustConvert);
+ }
+ catch (Exception ex)
+ {
+ *ppException = _this.AllocException(ex);
+ return default(bool);
+ }
+ }
+
static void* _getMemoryManager(IntPtr thisHandle, IntPtr* ppException)
{
var _this = GetThis(thisHandle);
@@ -2737,8 +2753,8 @@ namespace Internal.JitInterface
static IntPtr GetUnmanagedCallbacks(out Object keepAlive)
{
- IntPtr * callbacks = (IntPtr *)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 173);
- Object[] delegates = new Object[173];
+ IntPtr * callbacks = (IntPtr *)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 174);
+ Object[] delegates = new Object[174];
var d0 = new __getMethodAttribs(_getMethodAttribs);
callbacks[0] = Marshal.GetFunctionPointerForDelegate(d0);
@@ -3202,63 +3218,66 @@ namespace Internal.JitInterface
var d153 = new __getTailCallCopyArgsThunk(_getTailCallCopyArgsThunk);
callbacks[153] = Marshal.GetFunctionPointerForDelegate(d153);
delegates[153] = d153;
- var d154 = new __getMemoryManager(_getMemoryManager);
+ var d154 = new __convertPInvokeCalliToCall(_convertPInvokeCalliToCall);
callbacks[154] = Marshal.GetFunctionPointerForDelegate(d154);
delegates[154] = d154;
- var d155 = new __allocMem(_allocMem);
+ var d155 = new __getMemoryManager(_getMemoryManager);
callbacks[155] = Marshal.GetFunctionPointerForDelegate(d155);
delegates[155] = d155;
- var d156 = new __reserveUnwindInfo(_reserveUnwindInfo);
+ var d156 = new __allocMem(_allocMem);
callbacks[156] = Marshal.GetFunctionPointerForDelegate(d156);
delegates[156] = d156;
- var d157 = new __allocUnwindInfo(_allocUnwindInfo);
+ var d157 = new __reserveUnwindInfo(_reserveUnwindInfo);
callbacks[157] = Marshal.GetFunctionPointerForDelegate(d157);
delegates[157] = d157;
- var d158 = new __allocGCInfo(_allocGCInfo);
+ var d158 = new __allocUnwindInfo(_allocUnwindInfo);
callbacks[158] = Marshal.GetFunctionPointerForDelegate(d158);
delegates[158] = d158;
- var d159 = new __yieldExecution(_yieldExecution);
+ var d159 = new __allocGCInfo(_allocGCInfo);
callbacks[159] = Marshal.GetFunctionPointerForDelegate(d159);
delegates[159] = d159;
- var d160 = new __setEHcount(_setEHcount);
+ var d160 = new __yieldExecution(_yieldExecution);
callbacks[160] = Marshal.GetFunctionPointerForDelegate(d160);
delegates[160] = d160;
- var d161 = new __setEHinfo(_setEHinfo);
+ var d161 = new __setEHcount(_setEHcount);
callbacks[161] = Marshal.GetFunctionPointerForDelegate(d161);
delegates[161] = d161;
- var d162 = new __logMsg(_logMsg);
+ var d162 = new __setEHinfo(_setEHinfo);
callbacks[162] = Marshal.GetFunctionPointerForDelegate(d162);
delegates[162] = d162;
- var d163 = new __doAssert(_doAssert);
+ var d163 = new __logMsg(_logMsg);
callbacks[163] = Marshal.GetFunctionPointerForDelegate(d163);
delegates[163] = d163;
- var d164 = new __reportFatalError(_reportFatalError);
+ var d164 = new __doAssert(_doAssert);
callbacks[164] = Marshal.GetFunctionPointerForDelegate(d164);
delegates[164] = d164;
- var d165 = new __allocBBProfileBuffer(_allocBBProfileBuffer);
+ var d165 = new __reportFatalError(_reportFatalError);
callbacks[165] = Marshal.GetFunctionPointerForDelegate(d165);
delegates[165] = d165;
- var d166 = new __getBBProfileData(_getBBProfileData);
+ var d166 = new __allocBBProfileBuffer(_allocBBProfileBuffer);
callbacks[166] = Marshal.GetFunctionPointerForDelegate(d166);
delegates[166] = d166;
- var d167 = new __recordCallSite(_recordCallSite);
+ var d167 = new __getBBProfileData(_getBBProfileData);
callbacks[167] = Marshal.GetFunctionPointerForDelegate(d167);
delegates[167] = d167;
- var d168 = new __recordRelocation(_recordRelocation);
+ var d168 = new __recordCallSite(_recordCallSite);
callbacks[168] = Marshal.GetFunctionPointerForDelegate(d168);
delegates[168] = d168;
- var d169 = new __getRelocTypeHint(_getRelocTypeHint);
+ var d169 = new __recordRelocation(_recordRelocation);
callbacks[169] = Marshal.GetFunctionPointerForDelegate(d169);
delegates[169] = d169;
- var d170 = new __getModuleNativeEntryPointRange(_getModuleNativeEntryPointRange);
+ var d170 = new __getRelocTypeHint(_getRelocTypeHint);
callbacks[170] = Marshal.GetFunctionPointerForDelegate(d170);
delegates[170] = d170;
- var d171 = new __getExpectedTargetArchitecture(_getExpectedTargetArchitecture);
+ var d171 = new __getModuleNativeEntryPointRange(_getModuleNativeEntryPointRange);
callbacks[171] = Marshal.GetFunctionPointerForDelegate(d171);
delegates[171] = d171;
- var d172 = new __getJitFlags(_getJitFlags);
+ var d172 = new __getExpectedTargetArchitecture(_getExpectedTargetArchitecture);
callbacks[172] = Marshal.GetFunctionPointerForDelegate(d172);
delegates[172] = d172;
+ var d173 = new __getJitFlags(_getJitFlags);
+ callbacks[173] = Marshal.GetFunctionPointerForDelegate(d173);
+ delegates[173] = d173;
keepAlive = delegates;
return (IntPtr)callbacks;
diff --git a/src/JitInterface/src/CorInfoImpl.Intrinsics.cs b/src/JitInterface/src/CorInfoImpl.Intrinsics.cs
index 888957b32..903ba093c 100644
--- a/src/JitInterface/src/CorInfoImpl.Intrinsics.cs
+++ b/src/JitInterface/src/CorInfoImpl.Intrinsics.cs
@@ -131,9 +131,9 @@ namespace Internal.JitInterface
table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_InitializeArray, "InitializeArray", "System.Runtime.CompilerServices", "RuntimeHelpers");
//table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_GetTypeFromHandle, "GetTypeFromHandle", "System", "Type"); // RuntimeTypeHandle has to be RuntimeType
table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_RTH_GetValueInternal, "GetValueInternal", "System", "RuntimeTypeHandle");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_TypeEQ, "op_Equality", "System", "Type");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_TypeNEQ, "op_Inequality", "System", "Type");
- table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Object_GetType, "GetType", "System", "Object");
+ //table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_TypeEQ, "op_Equality", "System", "Type"); // https://github.com/dotnet/corert/issues/5180
+ //table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_TypeNEQ, "op_Inequality", "System", "Type"); // https://github.com/dotnet/corert/issues/5180
+ //table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_Object_GetType, "GetType", "System", "Object"); // https://github.com/dotnet/corert/issues/5180
// table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_StubHelpers_GetStubContext, "GetStubContext", "System.StubHelpers", "StubHelpers"); // interop-specific
// table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_StubHelpers_GetStubContextAddr, "GetStubContextAddr", "System.StubHelpers", "StubHelpers"); // interop-specific
// table.Add(CorInfoIntrinsics.CORINFO_INTRINSIC_StubHelpers_GetNDirectTarget, "GetNDirectTarget", "System.StubHelpers", "StubHelpers"); // interop-specific
diff --git a/src/JitInterface/src/CorInfoImpl.cs b/src/JitInterface/src/CorInfoImpl.cs
index a9eaceaab..b02092b30 100644
--- a/src/JitInterface/src/CorInfoImpl.cs
+++ b/src/JitInterface/src/CorInfoImpl.cs
@@ -42,6 +42,12 @@ namespace Internal.JitInterface
ARM = 0x01c4,
}
+#if SUPPORT_JIT
+ private const string JitSupportLibrary = "*";
+#else
+ private const string JitSupportLibrary = "jitinterface";
+#endif
+
private IntPtr _jit;
private IntPtr _unmanagedCallbacks; // array of pointers to JIT-EE interface callbacks
@@ -49,13 +55,13 @@ namespace Internal.JitInterface
private ExceptionDispatchInfo _lastException;
- [DllImport("clrjitilc")]
+ [DllImport("clrjitilc", CallingConvention=CallingConvention.StdCall)] // stdcall in CoreCLR!
private extern static IntPtr jitStartup(IntPtr host);
- [DllImport("clrjitilc")]
+ [DllImport("clrjitilc", CallingConvention=CallingConvention.StdCall)]
private extern static IntPtr getJit();
- [DllImport("jitinterface")]
+ [DllImport(JitSupportLibrary)]
private extern static IntPtr GetJitHost(IntPtr configProvider);
//
@@ -68,15 +74,15 @@ namespace Internal.JitInterface
return _this;
}
- [DllImport("jitinterface")]
+ [DllImport(JitSupportLibrary)]
private extern static CorJitResult JitCompileMethod(out IntPtr exception,
IntPtr jit, IntPtr thisHandle, IntPtr callbacks,
ref CORINFO_METHOD_INFO info, uint flags, out IntPtr nativeEntry, out uint codeSize);
- [DllImport("jitinterface")]
+ [DllImport(JitSupportLibrary)]
private extern static uint GetMaxIntrinsicSIMDVectorLength(IntPtr jit, CORJIT_FLAGS* flags);
- [DllImport("jitinterface")]
+ [DllImport(JitSupportLibrary)]
private extern static IntPtr AllocException([MarshalAs(UnmanagedType.LPWStr)]string message, int messageLength);
private IntPtr AllocException(Exception ex)
@@ -93,10 +99,10 @@ namespace Internal.JitInterface
return nativeException;
}
- [DllImport("jitinterface")]
+ [DllImport(JitSupportLibrary)]
private extern static void FreeException(IntPtr obj);
- [DllImport("jitinterface")]
+ [DllImport(JitSupportLibrary)]
private extern static char* GetExceptionMessage(IntPtr obj);
private Compilation _compilation;
@@ -407,10 +413,22 @@ namespace Internal.JitInterface
_compilation.NodeFactory.Target.MinimumFunctionAlignment,
new ISymbolDefinitionNode[] { _methodCodeNode });
ObjectNode.ObjectData ehInfo = _ehClauses != null ? EncodeEHInfo() : null;
+ DebugEHClauseInfo[] debugEHClauseInfos = null;
+ if (_ehClauses != null)
+ {
+ debugEHClauseInfos = new DebugEHClauseInfo[_ehClauses.Length];
+ for (int i = 0; i < _ehClauses.Length; i++)
+ {
+ var clause = _ehClauses[i];
+ debugEHClauseInfos[i] = new DebugEHClauseInfo(clause.TryOffset, clause.TryLength,
+ clause.HandlerOffset, clause.HandlerLength);
+ }
+ }
_methodCodeNode.SetCode(objectData);
_methodCodeNode.InitializeFrameInfos(_frameInfos);
+ _methodCodeNode.InitializeDebugEHClauseInfos(debugEHClauseInfos);
_methodCodeNode.InitializeGCInfo(_gcInfo);
_methodCodeNode.InitializeEHInfo(ehInfo);
@@ -751,7 +769,8 @@ namespace Internal.JitInterface
{
result |= CorInfoFlag.CORINFO_FLG_PINVOKE;
- // See comment in pInvokeMarshalingRequired
+ // TODO: Enable PInvoke inlining
+ // https://github.com/dotnet/corert/issues/6063
result |= CorInfoFlag.CORINFO_FLG_DONT_INLINE;
}
@@ -859,8 +878,9 @@ namespace Internal.JitInterface
// Normalize to the slot defining method. We don't have slot information for the overrides.
methodDesc = MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(methodDesc);
+ Debug.Assert(!methodDesc.CanMethodBeInSealedVTable());
- int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(_compilation.NodeFactory, methodDesc);
+ int slot = VirtualMethodSlotHelper.GetVirtualMethodSlot(_compilation.NodeFactory, methodDesc, methodDesc.OwningType);
Debug.Assert(slot != -1);
offsetAfterIndirection = (uint)(EETypeNode.GetVTableOffset(pointerSize) + slot * pointerSize);
@@ -993,7 +1013,7 @@ namespace Internal.JitInterface
{
TypeDesc type = HandleToObject(classHnd);
- if (_simdHelper.IsInSimdModule(type))
+ if (_simdHelper.IsSimdType(type))
{
#if DEBUG
// If this is Vector<T>, make sure the codegen and the type system agree on what instructions/registers
@@ -1024,23 +1044,34 @@ namespace Internal.JitInterface
return (CorInfoUnmanagedCallConv)unmanagedCallConv;
}
+ private bool IsPInvokeStubRequired(MethodDesc method)
+ {
+ return ((Internal.IL.Stubs.PInvokeILStubMethodIL)_compilation.GetMethodIL(method)).IsStubRequired;
+ }
+
private bool pInvokeMarshalingRequired(CORINFO_METHOD_STRUCT_* handle, CORINFO_SIG_INFO* callSiteSig)
{
- // TODO: Support for PInvoke calli with marshalling. For now, assume there is no marshalling required.
+ // calli is covered by convertPInvokeCalliToCall
if (handle == null)
+ {
+#if DEBUG
+ MethodSignature methodSignature = (MethodSignature)HandleToObject((IntPtr)callSiteSig->pSig);
+
+ MethodDesc stub = _compilation.PInvokeILProvider.GetCalliStub(methodSignature);
+ Debug.Assert(!IsPInvokeStubRequired(stub));
+#endif
+
return false;
+ }
MethodDesc method = HandleToObject(handle);
if (method.IsRawPInvoke())
return false;
- // TODO: Ideally, we would just give back the PInvoke stub IL to the JIT and let it inline it, without
- // checking whether it is required upfront. Unfortunatelly, RyuJIT is not able to generate PInvoke
- // transitions in inlined methods today (impCheckForPInvokeCall is not called for inlinees and number of other places
- // depend on it). To get a decent code with this limitation, we mirror CoreCLR behavior: Check
- // whether PInvoke stub is required here, and disable inlining of PInvoke methods in getMethodAttribsInternal.
- return ((Internal.IL.Stubs.PInvokeILStubMethodIL)_compilation.GetMethodIL(method)).IsStubRequired;
+ // We could have given back the PInvoke stub IL to the JIT and let it inline it, without
+ // checking whether there is any stub required. Save the JIT from doing the inlining by checking upfront.
+ return IsPInvokeStubRequired(method);
}
private bool satisfiesMethodConstraints(CORINFO_CLASS_STRUCT_* parent, CORINFO_METHOD_STRUCT_* method)
@@ -1399,7 +1430,7 @@ namespace Internal.JitInterface
private uint getClassAlignmentRequirement(CORINFO_CLASS_STRUCT_* cls, bool fDoubleAlignHint)
{
DefType type = (DefType)HandleToObject(cls);
- return (uint)type.InstanceByteAlignment.AsInt;
+ return (uint)type.InstanceFieldAlignment.AsInt;
}
private int GatherClassGCLayout(TypeDesc type, byte* gcPtrs)
@@ -1477,7 +1508,7 @@ namespace Internal.JitInterface
int pointerSize = PointerSize;
- int ptrsCount = AlignmentHelper.AlignUp(type.InstanceByteCount.AsInt, pointerSize) / pointerSize;
+ int ptrsCount = AlignmentHelper.AlignUp(type.InstanceFieldSize.AsInt, pointerSize) / pointerSize;
// Assume no GC pointers at first
for (int i = 0; i < ptrsCount; i++)
@@ -3342,6 +3373,7 @@ namespace Internal.JitInterface
else
{
pResult.exactContextNeedsRuntimeLookup = false;
+ targetMethod = targetMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
// Get the slot defining method to make sure our virtual method use tracking gets this right.
// For normal C# code the targetMethod will always be newslot.
@@ -3426,8 +3458,41 @@ namespace Internal.JitInterface
{ throw new NotImplementedException("GetDelegateCtor"); }
private void MethodCompileComplete(CORINFO_METHOD_STRUCT_* methHnd)
{ throw new NotImplementedException("MethodCompileComplete"); }
+
private void* getTailCallCopyArgsThunk(CORINFO_SIG_INFO* pSig, CorInfoHelperTailCallSpecialHandling flags)
- { throw new NotImplementedException("getTailCallCopyArgsThunk"); }
+ {
+ // Slow tailcalls are not supported yet
+ // https://github.com/dotnet/corert/issues/1683
+ return null;
+ }
+
+ private bool convertPInvokeCalliToCall(ref CORINFO_RESOLVED_TOKEN pResolvedToken, bool mustConvert)
+ {
+ var methodIL = (MethodIL)HandleToObject((IntPtr)pResolvedToken.tokenScope);
+ if (methodIL.OwningMethod.IsPInvoke)
+ {
+ return false;
+ }
+
+ MethodSignature signature = (MethodSignature)methodIL.GetObject((int)pResolvedToken.token);
+
+ CorInfoCallConv callConv = (CorInfoCallConv)(signature.Flags & MethodSignatureFlags.UnmanagedCallingConventionMask);
+ if (callConv != CorInfoCallConv.CORINFO_CALLCONV_C &&
+ callConv != CorInfoCallConv.CORINFO_CALLCONV_STDCALL &&
+ callConv != CorInfoCallConv.CORINFO_CALLCONV_THISCALL &&
+ callConv != CorInfoCallConv.CORINFO_CALLCONV_FASTCALL)
+ {
+ return false;
+ }
+
+ MethodDesc stub = _compilation.PInvokeILProvider.GetCalliStub(signature);
+ if (!mustConvert && !IsPInvokeStubRequired(stub))
+ return false;
+
+ pResolvedToken.hMethod = ObjectToHandle(stub);
+ pResolvedToken.hClass = ObjectToHandle(stub.OwningType);
+ return true;
+ }
private void* getMemoryManager()
{
diff --git a/src/JitInterface/src/CorInfoTypes.cs b/src/JitInterface/src/CorInfoTypes.cs
index b0ceda613..6d0662be5 100644
--- a/src/JitInterface/src/CorInfoTypes.cs
+++ b/src/JitInterface/src/CorInfoTypes.cs
@@ -193,6 +193,7 @@ namespace Internal.JitInterface
// Constant Lookups are either:
// IAT_VALUE: immediate (relocatable) values,
// IAT_PVALUE: immediate values access via an indirection through an immediate (relocatable) address
+ // IAT_RELPVALUE: immediate values access via a relative indirection through an immediate offset
// IAT_PPVALUE: immediate values access via a double indirection through an immediate (relocatable) address
//
// Runtime Lookups
@@ -220,6 +221,7 @@ namespace Internal.JitInterface
// If accessType is
// IAT_VALUE --> "handle" stores the real handle or "addr " stores the computed address
// IAT_PVALUE --> "addr" stores a pointer to a location which will hold the real handle
+ // IAT_RELPVALUE --> "addr" stores a relative pointer to a location which will hold the real handle
// IAT_PPVALUE --> "addr" stores a double indirection to a location which will hold the real handle
public InfoAccessType accessType;
@@ -301,6 +303,7 @@ namespace Internal.JitInterface
// Otherwise, it's a representative... If accessType is
// IAT_VALUE --> "handle" stores the real handle or "addr " stores the computed address
// IAT_PVALUE --> "addr" stores a pointer to a location which will hold the real handle
+ // IAT_RELPVALUE --> "addr" stores a relative pointer to a location which will hold the real handle
// IAT_PPVALUE --> "addr" stores a double indirection to a location which will hold the real handle
public ref CORINFO_CONST_LOOKUP constLookup
{
@@ -495,7 +498,8 @@ namespace Internal.JitInterface
{
IAT_VALUE, // The info value is directly available
IAT_PVALUE, // The value needs to be accessed via an indirection
- IAT_PPVALUE // The value needs to be accessed via a double indirection
+ IAT_PPVALUE, // The value needs to be accessed via a double indirection
+ IAT_RELPVALUE // The value needs to be accessed via a relative indirection
}
public enum CorInfoGCType
@@ -1508,7 +1512,7 @@ namespace Internal.JitInterface
CORJIT_FLAG_HAS_ARM64_LRCPC = 52, // ID_AA64ISAR1_EL1.LRCPC is 1 or better
CORJIT_FLAG_HAS_ARM64_PMULL = 53, // ID_AA64ISAR0_EL1.AES is 2 or better
CORJIT_FLAG_HAS_ARM64_SHA1 = 54, // ID_AA64ISAR0_EL1.SHA1 is 1 or better
- CORJIT_FLAG_HAS_ARM64_SHA2 = 55, // ID_AA64ISAR0_EL1.SHA2 is 1 or better
+ CORJIT_FLAG_HAS_ARM64_SHA256 = 55, // ID_AA64ISAR0_EL1.SHA2 is 1 or better
CORJIT_FLAG_HAS_ARM64_SHA512 = 56, // ID_AA64ISAR0_EL1.SHA2 is 2 or better
CORJIT_FLAG_HAS_ARM64_SHA3 = 57, // ID_AA64ISAR0_EL1.SHA3 is 1 or better
CORJIT_FLAG_HAS_ARM64_SIMD = 58, // ID_AA64PFR0_EL1.AdvSIMD is 0 or better
diff --git a/src/JitInterface/src/ThunkGenerator/ThunkInput.txt b/src/JitInterface/src/ThunkGenerator/ThunkInput.txt
index 4792e13d1..056daa6db 100644
--- a/src/JitInterface/src/ThunkGenerator/ThunkInput.txt
+++ b/src/JitInterface/src/ThunkGenerator/ThunkInput.txt
@@ -314,6 +314,7 @@ FUNCTIONS
CORINFO_METHOD_HANDLE GetDelegateCtor(CORINFO_METHOD_HANDLE methHnd, CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE targetMethodHnd, DelegateCtorArgs * pCtorData);
void MethodCompileComplete(CORINFO_METHOD_HANDLE methHnd);
void* getTailCallCopyArgsThunk (CORINFO_SIG_INFO *pSig, CorInfoHelperTailCallSpecialHandling flags);
+ bool convertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN * pResolvedToken, bool mustConvert);
[ManualNativeWrapper] IEEMemoryManager* getMemoryManager();
void allocMem( ULONG hotCodeSize, ULONG coldCodeSize, ULONG roDataSize, ULONG xcptnsCount, CorJitAllocMemFlag flag, void** hotCodeBlock, void** coldCodeBlock, void** roDataBlock );
void reserveUnwindInfo(BOOL isFunclet, BOOL isColdCode, ULONG unwindSize)
diff --git a/src/JitInterface/src/ThunkGenerator/cordebuginfo.h b/src/JitInterface/src/ThunkGenerator/cordebuginfo.h
index b065c5fc0..8c076e8b6 100644
--- a/src/JitInterface/src/ThunkGenerator/cordebuginfo.h
+++ b/src/JitInterface/src/ThunkGenerator/cordebuginfo.h
@@ -2,6 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+//
+// Keep in sync with https://github.com/dotnet/corert/blob/master/src/Native/ObjWriter/cordebuginfo.h
+//
+
/**********************************************************************************/
// DebugInfo types shared by JIT-EE interface and EE-Debugger interface
@@ -191,104 +195,114 @@ public:
VLT_INVALID,
};
+ // VLT_REG/VLT_REG_FP -- Any pointer-sized enregistered value (TYP_INT, TYP_REF, etc)
+ // eg. EAX
+ // VLT_REG_BYREF -- the specified register contains the address of the variable
+ // eg. [EAX]
+
+ struct vlReg
+ {
+ RegNum vlrReg;
+ };
+
+ // VLT_STK -- Any 32 bit value which is on the stack
+ // eg. [ESP+0x20], or [EBP-0x28]
+ // VLT_STK_BYREF -- the specified stack location contains the address of the variable
+ // eg. mov EAX, [ESP+0x20]; [EAX]
+
+ struct vlStk
+ {
+ RegNum vlsBaseReg;
+ signed vlsOffset;
+ };
+
+ // VLT_REG_REG -- TYP_LONG with both DWords enregistred
+ // eg. RBM_EAXEDX
+
+ struct vlRegReg
+ {
+ RegNum vlrrReg1;
+ RegNum vlrrReg2;
+ };
+
+ // VLT_REG_STK -- Partly enregistered TYP_LONG
+ // eg { LowerDWord=EAX UpperDWord=[ESP+0x8] }
+
+ struct vlRegStk
+ {
+ RegNum vlrsReg;
+ struct
+ {
+ RegNum vlrssBaseReg;
+ signed vlrssOffset;
+ } vlrsStk;
+ };
+
+ // VLT_STK_REG -- Partly enregistered TYP_LONG
+ // eg { LowerDWord=[ESP+0x8] UpperDWord=EAX }
+
+ struct vlStkReg
+ {
+ struct
+ {
+ RegNum vlsrsBaseReg;
+ signed vlsrsOffset;
+ } vlsrStk;
+ RegNum vlsrReg;
+ };
+
+ // VLT_STK2 -- Any 64 bit value which is on the stack,
+ // in 2 successsive DWords.
+ // eg 2 DWords at [ESP+0x10]
+
+ struct vlStk2
+ {
+ RegNum vls2BaseReg;
+ signed vls2Offset;
+ };
+
+ // VLT_FPSTK -- enregisterd TYP_DOUBLE (on the FP stack)
+ // eg. ST(3). Actually it is ST("FPstkHeigth - vpFpStk")
+
+ struct vlFPstk
+ {
+ unsigned vlfReg;
+ };
+
+ // VLT_FIXED_VA -- fixed argument of a varargs function.
+ // The argument location depends on the size of the variable
+ // arguments (...). Inspecting the VARARGS_HANDLE indicates the
+ // location of the first arg. This argument can then be accessed
+ // relative to the position of the first arg
+
+ struct vlFixedVarArg
+ {
+ unsigned vlfvOffset;
+ };
+
+ // VLT_MEMORY
+
+ struct vlMemory
+ {
+ void *rpValue; // pointer to the in-process
+ // location of the value.
+ };
+
struct VarLoc
{
VarLocType vlType;
union
{
- // VLT_REG/VLT_REG_FP -- Any pointer-sized enregistered value (TYP_INT, TYP_REF, etc)
- // eg. EAX
- // VLT_REG_BYREF -- the specified register contains the address of the variable
- // eg. [EAX]
-
- struct
- {
- RegNum vlrReg;
- } vlReg;
-
- // VLT_STK -- Any 32 bit value which is on the stack
- // eg. [ESP+0x20], or [EBP-0x28]
- // VLT_STK_BYREF -- the specified stack location contains the address of the variable
- // eg. mov EAX, [ESP+0x20]; [EAX]
-
- struct
- {
- RegNum vlsBaseReg;
- signed vlsOffset;
- } vlStk;
-
- // VLT_REG_REG -- TYP_LONG with both DWords enregistred
- // eg. RBM_EAXEDX
-
- struct
- {
- RegNum vlrrReg1;
- RegNum vlrrReg2;
- } vlRegReg;
-
- // VLT_REG_STK -- Partly enregistered TYP_LONG
- // eg { LowerDWord=EAX UpperDWord=[ESP+0x8] }
-
- struct
- {
- RegNum vlrsReg;
- struct
- {
- RegNum vlrssBaseReg;
- signed vlrssOffset;
- } vlrsStk;
- } vlRegStk;
-
- // VLT_STK_REG -- Partly enregistered TYP_LONG
- // eg { LowerDWord=[ESP+0x8] UpperDWord=EAX }
-
- struct
- {
- struct
- {
- RegNum vlsrsBaseReg;
- signed vlsrsOffset;
- } vlsrStk;
- RegNum vlsrReg;
- } vlStkReg;
-
- // VLT_STK2 -- Any 64 bit value which is on the stack,
- // in 2 successsive DWords.
- // eg 2 DWords at [ESP+0x10]
-
- struct
- {
- RegNum vls2BaseReg;
- signed vls2Offset;
- } vlStk2;
-
- // VLT_FPSTK -- enregisterd TYP_DOUBLE (on the FP stack)
- // eg. ST(3). Actually it is ST("FPstkHeigth - vpFpStk")
-
- struct
- {
- unsigned vlfReg;
- } vlFPstk;
-
- // VLT_FIXED_VA -- fixed argument of a varargs function.
- // The argument location depends on the size of the variable
- // arguments (...). Inspecting the VARARGS_HANDLE indicates the
- // location of the first arg. This argument can then be accessed
- // relative to the position of the first arg
-
- struct
- {
- unsigned vlfvOffset;
- } vlFixedVarArg;
-
- // VLT_MEMORY
-
- struct
- {
- void *rpValue; // pointer to the in-process
- // location of the value.
- } vlMemory;
+ vlReg vlReg;
+ vlStk vlStk;
+ vlRegReg vlRegReg;
+ vlRegStk vlRegStk;
+ vlStkReg vlStkReg;
+ vlStk2 vlStk2;
+ vlFPstk vlFPstk;
+ vlFixedVarArg vlFixedVarArg;
+ vlMemory vlMemory;
};
};
diff --git a/src/JitInterface/src/ThunkGenerator/corinfo.h b/src/JitInterface/src/ThunkGenerator/corinfo.h
index f3b509c5a..89cd95f75 100644
--- a/src/JitInterface/src/ThunkGenerator/corinfo.h
+++ b/src/JitInterface/src/ThunkGenerator/corinfo.h
@@ -213,11 +213,11 @@ TODO: Talk about initializing strutures before use
#define SELECTANY extern __declspec(selectany)
#endif
-SELECTANY const GUID JITEEVersionIdentifier = { /* 0ba106c8-81a0-407f-99a1-928448c1eb62 */
- 0x0ba106c8,
- 0x81a0,
- 0x407f,
- {0x99, 0xa1, 0x92, 0x84, 0x48, 0xc1, 0xeb, 0x62}
+SELECTANY const GUID JITEEVersionIdentifier = { /* 45aafd4d-1d23-4647-9ce1-cf09a2677ca0 */
+ 0x45aafd4d,
+ 0x1d23,
+ 0x4647,
+ {0x9c, 0xe1, 0xcf, 0x09, 0xa2, 0x67, 0x7c, 0xa0}
};
//////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -977,8 +977,9 @@ enum CorInfoIntrinsics
enum InfoAccessType
{
IAT_VALUE, // The info value is directly available
- IAT_PVALUE, // The value needs to be accessed via an indirection
- IAT_PPVALUE // The value needs to be accessed via a double indirection
+ IAT_PVALUE, // The value needs to be accessed via an indirection
+ IAT_PPVALUE, // The value needs to be accessed via a double indirection
+ IAT_RELPVALUE // The value needs to be accessed via a relative indirection
};
enum CorInfoGCType
@@ -1243,6 +1244,7 @@ struct CORINFO_METHOD_INFO
// Constant Lookups are either:
// IAT_VALUE: immediate (relocatable) values,
// IAT_PVALUE: immediate values access via an indirection through an immediate (relocatable) address
+// IAT_RELPVALUE: immediate values access via a relative indirection through an immediate offset
// IAT_PPVALUE: immediate values access via a double indirection through an immediate (relocatable) address
//
// Runtime Lookups
@@ -1268,9 +1270,10 @@ struct CORINFO_CONST_LOOKUP
// If the handle is obtained at compile-time, then this handle is the "exact" handle (class, method, or field)
// Otherwise, it's a representative...
// If accessType is
- // IAT_VALUE --> "handle" stores the real handle or "addr " stores the computed address
- // IAT_PVALUE --> "addr" stores a pointer to a location which will hold the real handle
- // IAT_PPVALUE --> "addr" stores a double indirection to a location which will hold the real handle
+ // IAT_VALUE --> "handle" stores the real handle or "addr " stores the computed address
+ // IAT_PVALUE --> "addr" stores a pointer to a location which will hold the real handle
+ // IAT_RELPVALUE --> "addr" stores a relative pointer to a location which will hold the real handle
+ // IAT_PPVALUE --> "addr" stores a double indirection to a location which will hold the real handle
InfoAccessType accessType;
union
@@ -1361,6 +1364,7 @@ struct CORINFO_LOOKUP
// Otherwise, it's a representative... If accessType is
// IAT_VALUE --> "handle" stores the real handle or "addr " stores the computed address
// IAT_PVALUE --> "addr" stores a pointer to a location which will hold the real handle
+ // IAT_RELPVALUE --> "addr" stores a relative pointer to a location which will hold the real handle
// IAT_PPVALUE --> "addr" stores a double indirection to a location which will hold the real handle
CORINFO_CONST_LOOKUP constLookup;
};
@@ -1926,6 +1930,21 @@ struct CORINFO_VarArgInfo
#include <poppack.h>
+#define SIZEOF__CORINFO_Object TARGET_POINTER_SIZE /* methTable */
+
+#define OFFSETOF__CORINFO_Array__length SIZEOF__CORINFO_Object
+#ifdef _TARGET_64BIT_
+#define OFFSETOF__CORINFO_Array__data (OFFSETOF__CORINFO_Array__length + sizeof(unsigned __int32) /* length */ + sizeof(unsigned __int32) /* alignpad */)
+#else
+#define OFFSETOF__CORINFO_Array__data (OFFSETOF__CORINFO_Array__length + sizeof(unsigned __int32) /* length */)
+#endif
+
+#define OFFSETOF__CORINFO_TypedReference__dataPtr 0
+#define OFFSETOF__CORINFO_TypedReference__type (OFFSETOF__CORINFO_TypedReference__dataPtr + TARGET_POINTER_SIZE /* dataPtr */)
+
+#define OFFSETOF__CORINFO_String__stringLen SIZEOF__CORINFO_Object
+#define OFFSETOF__CORINFO_String__chars (OFFSETOF__CORINFO_String__stringLen + sizeof(unsigned __int32) /* stringLen */)
+
enum CorInfoSecurityRuntimeChecks
{
CORINFO_ACCESS_SECURITY_NONE = 0,
@@ -1944,9 +1963,6 @@ struct DelegateCtorArgs
// use offsetof to get the offset of the fields above
#include <stddef.h> // offsetof
-#ifndef offsetof
-#define offsetof(s,m) ((size_t)&(((s *)0)->m))
-#endif
// Guard-stack cookie for preventing against stack buffer overruns
typedef SIZE_T GSCookie;
@@ -2375,7 +2391,7 @@ public:
// This is only called for Value classes. It returns a boolean array
// in representing of 'cls' from a GC perspective. The class is
// assumed to be an array of machine words
- // (of length // getClassSize(cls) / sizeof(void*)),
+ // (of length // getClassSize(cls) / TARGET_POINTER_SIZE),
// 'gcPtrs' is a pointer to an array of BYTEs of this length.
// getClassGClayout fills in this array so that gcPtrs[i] is set
// to one of the CorInfoGCType values which is the GC type of
@@ -3153,6 +3169,12 @@ public:
CORINFO_SIG_INFO *pSig,
CorInfoHelperTailCallSpecialHandling flags
) = 0;
+
+ // Optionally, convert calli to regular method call. This is for PInvoke argument marshalling.
+ virtual bool convertPInvokeCalliToCall(
+ CORINFO_RESOLVED_TOKEN * pResolvedToken,
+ bool fMustConvert
+ ) = 0;
};
/**********************************************************************************/
diff --git a/src/JitInterface/src/ThunkGenerator/corjitflags.h b/src/JitInterface/src/ThunkGenerator/corjitflags.h
index da303b6a0..84fb42f08 100644
--- a/src/JitInterface/src/ThunkGenerator/corjitflags.h
+++ b/src/JitInterface/src/ThunkGenerator/corjitflags.h
@@ -120,7 +120,7 @@ public:
CORJIT_FLAG_HAS_ARM64_LRCPC = 52, // ID_AA64ISAR1_EL1.LRCPC is 1 or better
CORJIT_FLAG_HAS_ARM64_PMULL = 53, // ID_AA64ISAR0_EL1.AES is 2 or better
CORJIT_FLAG_HAS_ARM64_SHA1 = 54, // ID_AA64ISAR0_EL1.SHA1 is 1 or better
- CORJIT_FLAG_HAS_ARM64_SHA2 = 55, // ID_AA64ISAR0_EL1.SHA2 is 1 or better
+ CORJIT_FLAG_HAS_ARM64_SHA256 = 55, // ID_AA64ISAR0_EL1.SHA2 is 1 or better
CORJIT_FLAG_HAS_ARM64_SHA512 = 56, // ID_AA64ISAR0_EL1.SHA2 is 2 or better
CORJIT_FLAG_HAS_ARM64_SHA3 = 57, // ID_AA64ISAR0_EL1.SHA3 is 1 or better
CORJIT_FLAG_HAS_ARM64_SIMD = 58, // ID_AA64PFR0_EL1.AdvSIMD is 0 or better
diff --git a/src/JitInterface/src/ThunkGenerator/corjithost.h b/src/JitInterface/src/ThunkGenerator/corjithost.h
index 8242fab2b..b2ab80646 100644
--- a/src/JitInterface/src/ThunkGenerator/corjithost.h
+++ b/src/JitInterface/src/ThunkGenerator/corjithost.h
@@ -15,15 +15,11 @@
class ICorJitHost
{
public:
- // Allocate memory of the given size in bytes. All bytes of the returned block
- // must be initialized to zero. If `usePageAllocator` is true, the implementation
- // should use an allocator that deals in OS pages if one exists.
- virtual void* allocateMemory(size_t size, bool usePageAllocator = false) = 0;
+ // Allocate memory of the given size in bytes.
+ virtual void* allocateMemory(size_t size) = 0;
- // Frees memory previous obtained by a call to `ICorJitHost::allocateMemory`. The
- // value of the `usePageAllocator` parameter must match the value that was
- // provided to the call to used to allocate the memory.
- virtual void freeMemory(void* block, bool usePageAllocator = false) = 0;
+ // Frees memory previous obtained by a call to `ICorJitHost::allocateMemory`.
+ virtual void freeMemory(void* block) = 0;
// Return an integer config value for the given key, if any exists.
virtual int getIntConfigValue(
@@ -43,6 +39,20 @@ public:
virtual void freeStringConfigValue(
const wchar_t* value
) = 0;
+
+ // Allocate memory slab of the given size in bytes. The host is expected to pool
+ // these for a good performance.
+ virtual void* allocateSlab(size_t size, size_t* pActualSize)
+ {
+ *pActualSize = size;
+ return allocateMemory(size);
+ }
+
+ // Free memory slab of the given size in bytes.
+ virtual void freeSlab(void* slab, size_t actualSize)
+ {
+ freeMemory(slab);
+ }
};
#endif
diff --git a/src/Native/Bootstrap/main.cpp b/src/Native/Bootstrap/main.cpp
index 43860640d..f327d28c6 100644
--- a/src/Native/Bootstrap/main.cpp
+++ b/src/Native/Bootstrap/main.cpp
@@ -245,9 +245,12 @@ extern "C" void RhpUniversalTransition_DebugStepTailCall()
{
throw "RhpUniversalTransition_DebugStepTailCall";
}
+extern "C" void ConstrainedCallSupport_GetStubs()
+{
+ throw "ConstrainedCallSupport_GetStubs";
+}
-void* RtRHeaderWrapper();
-
+extern "C" void* RtRHeaderWrapper();
#endif // CPPCODEGEN
// This works around System.Private.Interop's references to Interop.Native.
@@ -279,6 +282,8 @@ extern "C" bool RhRegisterOSModule(void * pModule,
extern "C" void* PalGetModuleHandleFromPointer(void* pointer);
+#endif // !CPPCODEGEN
+
extern "C" void GetRuntimeException();
extern "C" void FailFast();
extern "C" void AppendExceptionStackFrame();
@@ -299,8 +304,6 @@ static const pfn c_classlibFunctions[] = {
nullptr, // &DebugFuncEvalAbortHelper,
};
-#endif // !CPPCODEGEN
-
extern "C" void InitializeModules(void* osModule, void ** modules, int count, void ** pClasslibFunctions, int nClasslibFunctions);
#ifndef CORERT_DLL
@@ -341,10 +344,9 @@ static int InitializeRuntime()
#ifndef CPPCODEGEN
InitializeModules(osModule, __modules_a, (int)((__modules_z - __modules_a)), (void **)&c_classlibFunctions, _countof(c_classlibFunctions));
#elif defined _WASM_
- // WASMTODO: Figure out what to do here. This is a NativeCallable method in the runtime
- // and we also would have to figure out what to pass for pModuleHeaders
+ InitializeModules(nullptr, (void**)RtRHeaderWrapper(), 1, nullptr, 0);
#else // !CPPCODEGEN
- InitializeModules(nullptr, (void**)RtRHeaderWrapper(), 2, nullptr, 0);
+ InitializeModules(nullptr, (void**)RtRHeaderWrapper(), 2, (void **)&c_classlibFunctions, _countof(c_classlibFunctions));
#endif // !CPPCODEGEN
#ifdef CORERT_DLL
diff --git a/src/Native/CMakeLists.txt b/src/Native/CMakeLists.txt
index 219d68936..1a3622a0d 100644
--- a/src/Native/CMakeLists.txt
+++ b/src/Native/CMakeLists.txt
@@ -95,33 +95,26 @@ if (CLR_CMAKE_PLATFORM_UNIX)
add_compile_options(-Wno-null-arithmetic)
add_compile_options(-Wno-null-conversion)
- if (CLR_CMAKE_PLATFORM_ARCH_AMD64 OR CLR_CMAKE_PLATFORM_ARCH_I386)
+ # Since 6 version, clang generates pragma-pack warnings, so disable it because we use pshpack[1..8].h/poppack.h
+ add_compile_options(-Wno-pragmas)
+
+ if(CLR_CMAKE_PLATFORM_ARCH_AMD64 OR CLR_CMAKE_PLATFORM_ARCH_I386)
# Allow 16 byte compare-exchange
add_compile_options(-mcx16)
endif()
- if (CLR_CMAKE_PLATFORM_ARCH_ARM)
- # Because we don't use CMAKE_C_COMPILER/CMAKE_CXX_COMPILER to use clang
- # we have to set the triple by adding a compiler argument
+ if(CLR_CMAKE_PLATFORM_ARCH_ARM)
+ add_compile_options(-march=armv7-a)
if(TOOLCHAIN STREQUAL arm-linux-gnueabi)
- add_compile_options(-target armv7-linux-gnueabi)
add_compile_options(-mfloat-abi=softfp)
- else ()
- add_compile_options(-target armv7-linux-gnueabihf)
- endif ()
+ endif()
add_compile_options(-mthumb)
add_compile_options(-mfpu=vfpv3)
endif()
- if (CLR_CMAKE_PLATFORM_ARCH_ARM64)
- # Because we don't use CMAKE_C_COMPILER/CMAKE_CXX_COMPILER to use clang
- # we have to set the triple by adding a compiler argument
- add_compile_options(-target aarch64-linux-gnu)
- endif ()
-
- if (CLR_CMAKE_PLATFORM_ARCH_AMD64)
+ if(CLR_CMAKE_PLATFORM_ARCH_AMD64)
add_definitions(-DUNIX_AMD64_ABI)
- elseif (CLR_CMAKE_PLATFORM_ARCH_I386)
+ elseif(CLR_CMAKE_PLATFORM_ARCH_I386)
add_definitions(-DUNIX_X86_ABI)
endif()
@@ -228,7 +221,10 @@ if(NOT WIN32)
add_subdirectory(System.Private.CoreLib.Native)
endif(NOT WIN32)
-# Build ObjWriter on Linux only
-if(CMAKE_SYSTEM_NAME STREQUAL Linux AND OBJWRITER_BUILD)
+if(NOT CLR_CMAKE_PLATFORM_WASM)
+ add_subdirectory(System.Private.TypeLoader.Native)
+endif(NOT CLR_CMAKE_PLATFORM_WASM)
+
+if(OBJWRITER_BUILD)
add_subdirectory(ObjWriter/llvmCap)
endif()
diff --git a/src/Native/ObjWriter/.nuget/Microsoft.DotNet.ObjectWriter.nuspec b/src/Native/ObjWriter/.nuget/Microsoft.DotNet.ObjectWriter.nuspec
deleted file mode 100644
index f3421bb32..000000000
--- a/src/Native/ObjWriter/.nuget/Microsoft.DotNet.ObjectWriter.nuspec
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0"?>
-<package >
- <metadata>
- <id>Microsoft.DotNet.ObjectWriter</id>
- <version>1.0.19-prerelease-00001</version>
- <title>Microsoft .NET Object File Generator</title>
- <authors>Microsoft</authors>
- <owners>Microsoft</owners>
- <licenseUrl>http://go.microsoft.com/fwlink/?LinkId=329770</licenseUrl>
- <projectUrl>https://github.com/dotnet/corert</projectUrl>
- <iconUrl>http://go.microsoft.com/fwlink/?LinkID=288859</iconUrl>
- <requireLicenseAcceptance>true</requireLicenseAcceptance>
- <description>Provides object writer to the managed to native code-generator.</description>
- <releaseNotes>Initial release</releaseNotes>
- <copyright>Copyright &#169; Microsoft Corporation</copyright>
- </metadata>
- <files>
- <file src="runtime.json" />
- </files>
-</package>
diff --git a/src/Native/ObjWriter/.nuget/runtime.json b/src/Native/ObjWriter/.nuget/runtime.json
deleted file mode 100644
index c9c5b8e6b..000000000
--- a/src/Native/ObjWriter/.nuget/runtime.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "runtimes": {
- "win7-x64": {
- "Microsoft.DotNet.ObjectWriter": {
- "toolchain.win7-x64.Microsoft.DotNet.ObjectWriter": "1.0.19-prerelease-00001"
- }
- },
- "ubuntu.14.04-x64": {
- "Microsoft.DotNet.ObjectWriter": {
- "toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter": "1.0.19-prerelease-00001"
- }
- },
- "osx.10.10-x64": {
- "Microsoft.DotNet.ObjectWriter": {
- "toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter": "1.0.19-prerelease-00001"
- }
- }
- }
-}
diff --git a/src/Native/ObjWriter/.nuget/toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter.nuspec b/src/Native/ObjWriter/.nuget/toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter.nuspec
deleted file mode 100644
index 7a571beaf..000000000
--- a/src/Native/ObjWriter/.nuget/toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter.nuspec
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0"?>
-<package >
- <metadata>
- <id>toolchain.osx.10.10-x64.Microsoft.DotNet.ObjectWriter</id>
- <version>1.0.19-prerelease-00001</version>
- <title>Microsoft .NET Object File Generator</title>
- <authors>Microsoft</authors>
- <owners>Microsoft</owners>
- <licenseUrl>http://go.microsoft.com/fwlink/?LinkId=329770</licenseUrl>
- <projectUrl>https://github.com/dotnet/corert</projectUrl>
- <iconUrl>http://go.microsoft.com/fwlink/?LinkID=288859</iconUrl>
- <requireLicenseAcceptance>true</requireLicenseAcceptance>
- <description>Provides object writer to the managed to native code-generator.</description>
- <releaseNotes>Initial release</releaseNotes>
- <copyright>Copyright &#169; Microsoft Corporation</copyright>
- </metadata>
- <files>
- <file src="../libobjwriter.dylib" target="runtimes/osx.10.10-x64/native/libobjwriter.dylib" />
- </files>
-</package>
diff --git a/src/Native/ObjWriter/.nuget/toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter.nuspec b/src/Native/ObjWriter/.nuget/toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter.nuspec
deleted file mode 100644
index fd9c514c6..000000000
--- a/src/Native/ObjWriter/.nuget/toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter.nuspec
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0"?>
-<package >
- <metadata>
- <id>toolchain.ubuntu.14.04-x64.Microsoft.DotNet.ObjectWriter</id>
- <version>1.0.19-prerelease-00001</version>
- <title>Microsoft .NET Object File Generator</title>
- <authors>Microsoft</authors>
- <owners>Microsoft</owners>
- <licenseUrl>http://go.microsoft.com/fwlink/?LinkId=329770</licenseUrl>
- <projectUrl>https://github.com/dotnet/corert</projectUrl>
- <iconUrl>http://go.microsoft.com/fwlink/?LinkID=288859</iconUrl>
- <requireLicenseAcceptance>true</requireLicenseAcceptance>
- <description>Provides object writer to the managed to native code-generator.</description>
- <releaseNotes>Initial release</releaseNotes>
- <copyright>Copyright &#169; Microsoft Corporation</copyright>
- </metadata>
- <files>
- <file src="../libobjwriter.so" target="runtimes/ubuntu.14.04-x64/native/libobjwriter.so" />
- </files>
-</package>
diff --git a/src/Native/ObjWriter/.nuget/toolchain.win7-x64.Microsoft.DotNet.ObjectWriter.nuspec b/src/Native/ObjWriter/.nuget/toolchain.win7-x64.Microsoft.DotNet.ObjectWriter.nuspec
deleted file mode 100644
index a54cdc230..000000000
--- a/src/Native/ObjWriter/.nuget/toolchain.win7-x64.Microsoft.DotNet.ObjectWriter.nuspec
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0"?>
-<package >
- <metadata>
- <id>toolchain.win7-x64.Microsoft.DotNet.ObjectWriter</id>
- <version>1.0.19-prerelease-00001</version>
- <title>Microsoft .NET Object File Generator</title>
- <authors>Microsoft</authors>
- <owners>Microsoft</owners>
- <licenseUrl>http://go.microsoft.com/fwlink/?LinkId=329770</licenseUrl>
- <projectUrl>https://github.com/dotnet/corert</projectUrl>
- <iconUrl>http://go.microsoft.com/fwlink/?LinkID=288859</iconUrl>
- <requireLicenseAcceptance>true</requireLicenseAcceptance>
- <description>Provides object writer to the managed to native code-generator.</description>
- <releaseNotes>Initial release</releaseNotes>
- <copyright>Copyright &#169; Microsoft Corporation</copyright>
- </metadata>
- <files>
- <file src="..\objwriter.dll" target="runtimes\win7-x64\native\objwriter.dll" />
- </files>
-</package>
diff --git a/src/Native/ObjWriter/CMakeLists.txt b/src/Native/ObjWriter/CMakeLists.txt
index fae4ddb12..490a36701 100644
--- a/src/Native/ObjWriter/CMakeLists.txt
+++ b/src/Native/ObjWriter/CMakeLists.txt
@@ -2,7 +2,15 @@ project(objwriter)
set(CMAKE_BUILD_TYPE "${OBJWRITER_BUILD_TYPE}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OBJWRITER_C_FLAGS}")
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OBJWRITER_CXX_FLAGS} -std=c++11 -fno-rtti")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OBJWRITER_CXX_FLAGS}")
+
+if(WIN32)
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
+endif()
+
+if(NOT WIN32)
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-rtti")
+endif()
message(STATUS "ObjWriter configuring with (${CMAKE_BUILD_TYPE}) build type and (${LLVM_DEFAULT_TARGET_TRIPLE}) default target triple")
@@ -29,9 +37,16 @@ endif()
add_library(objwriter
SHARED
objwriter.cpp
- typeBuilder.cpp
+ debugInfo/codeView/codeViewTypeBuilder.cpp
+ debugInfo/codeView/codeViewTypeBuilder.h
+ debugInfo/dwarf/dwarfTypeBuilder.cpp
+ debugInfo/dwarf/dwarfTypeBuilder.h
+ debugInfo/dwarf/dwarfGen.cpp
+ debugInfo/dwarf/dwarfGen.h
+ debugInfo/dwarf/dwarfAbbrev.cpp
+ debugInfo/dwarf/dwarfAbbrev.h
+ debugInfo/typeBuilder.h
objwriter.h # Visual Studio generator doesn't include necessary header files into the project automatically
- typeBuilder.h
${OBJWRITER_EXPORTS_DEF}
)
diff --git a/src/Native/ObjWriter/cordebuginfo.h b/src/Native/ObjWriter/cordebuginfo.h
index 1ed430a11..46d74c2e1 100644
--- a/src/Native/ObjWriter/cordebuginfo.h
+++ b/src/Native/ObjWriter/cordebuginfo.h
@@ -195,104 +195,114 @@ public:
VLT_INVALID,
};
+ // VLT_REG/VLT_REG_FP -- Any pointer-sized enregistered value (TYP_INT, TYP_REF, etc)
+ // eg. EAX
+ // VLT_REG_BYREF -- the specified register contains the address of the variable
+ // eg. [EAX]
+
+ struct vlReg
+ {
+ RegNum vlrReg;
+ };
+
+ // VLT_STK -- Any 32 bit value which is on the stack
+ // eg. [ESP+0x20], or [EBP-0x28]
+ // VLT_STK_BYREF -- the specified stack location contains the address of the variable
+ // eg. mov EAX, [ESP+0x20]; [EAX]
+
+ struct vlStk
+ {
+ RegNum vlsBaseReg;
+ signed vlsOffset;
+ };
+
+ // VLT_REG_REG -- TYP_LONG with both DWords enregistred
+ // eg. RBM_EAXEDX
+
+ struct vlRegReg
+ {
+ RegNum vlrrReg1;
+ RegNum vlrrReg2;
+ };
+
+ // VLT_REG_STK -- Partly enregistered TYP_LONG
+ // eg { LowerDWord=EAX UpperDWord=[ESP+0x8] }
+
+ struct vlRegStk
+ {
+ RegNum vlrsReg;
+ struct
+ {
+ RegNum vlrssBaseReg;
+ signed vlrssOffset;
+ } vlrsStk;
+ };
+
+ // VLT_STK_REG -- Partly enregistered TYP_LONG
+ // eg { LowerDWord=[ESP+0x8] UpperDWord=EAX }
+
+ struct vlStkReg
+ {
+ struct
+ {
+ RegNum vlsrsBaseReg;
+ signed vlsrsOffset;
+ } vlsrStk;
+ RegNum vlsrReg;
+ };
+
+ // VLT_STK2 -- Any 64 bit value which is on the stack,
+ // in 2 successsive DWords.
+ // eg 2 DWords at [ESP+0x10]
+
+ struct vlStk2
+ {
+ RegNum vls2BaseReg;
+ signed vls2Offset;
+ };
+
+ // VLT_FPSTK -- enregisterd TYP_DOUBLE (on the FP stack)
+ // eg. ST(3). Actually it is ST("FPstkHeigth - vpFpStk")
+
+ struct vlFPstk
+ {
+ unsigned vlfReg;
+ };
+
+ // VLT_FIXED_VA -- fixed argument of a varargs function.
+ // The argument location depends on the size of the variable
+ // arguments (...). Inspecting the VARARGS_HANDLE indicates the
+ // location of the first arg. This argument can then be accessed
+ // relative to the position of the first arg
+
+ struct vlFixedVarArg
+ {
+ unsigned vlfvOffset;
+ };
+
+ // VLT_MEMORY
+
+ struct vlMemory
+ {
+ void *rpValue; // pointer to the in-process
+ // location of the value.
+ };
+
struct VarLoc
{
VarLocType vlType;
union
{
- // VLT_REG/VLT_REG_FP -- Any pointer-sized enregistered value (TYP_INT, TYP_REF, etc)
- // eg. EAX
- // VLT_REG_BYREF -- the specified register contains the address of the variable
- // eg. [EAX]
-
- struct
- {
- RegNum vlrReg;
- } vlReg;
-
- // VLT_STK -- Any 32 bit value which is on the stack
- // eg. [ESP+0x20], or [EBP-0x28]
- // VLT_STK_BYREF -- the specified stack location contains the address of the variable
- // eg. mov EAX, [ESP+0x20]; [EAX]
-
- struct
- {
- RegNum vlsBaseReg;
- signed vlsOffset;
- } vlStk;
-
- // VLT_REG_REG -- TYP_LONG with both DWords enregistred
- // eg. RBM_EAXEDX
-
- struct
- {
- RegNum vlrrReg1;
- RegNum vlrrReg2;
- } vlRegReg;
-
- // VLT_REG_STK -- Partly enregistered TYP_LONG
- // eg { LowerDWord=EAX UpperDWord=[ESP+0x8] }
-
- struct
- {
- RegNum vlrsReg;
- struct
- {
- RegNum vlrssBaseReg;
- signed vlrssOffset;
- } vlrsStk;
- } vlRegStk;
-
- // VLT_STK_REG -- Partly enregistered TYP_LONG
- // eg { LowerDWord=[ESP+0x8] UpperDWord=EAX }
-
- struct
- {
- struct
- {
- RegNum vlsrsBaseReg;
- signed vlsrsOffset;
- } vlsrStk;
- RegNum vlsrReg;
- } vlStkReg;
-
- // VLT_STK2 -- Any 64 bit value which is on the stack,
- // in 2 successsive DWords.
- // eg 2 DWords at [ESP+0x10]
-
- struct
- {
- RegNum vls2BaseReg;
- signed vls2Offset;
- } vlStk2;
-
- // VLT_FPSTK -- enregisterd TYP_DOUBLE (on the FP stack)
- // eg. ST(3). Actually it is ST("FPstkHeigth - vpFpStk")
-
- struct
- {
- unsigned vlfReg;
- } vlFPstk;
-
- // VLT_FIXED_VA -- fixed argument of a varargs function.
- // The argument location depends on the size of the variable
- // arguments (...). Inspecting the VARARGS_HANDLE indicates the
- // location of the first arg. This argument can then be accessed
- // relative to the position of the first arg
-
- struct
- {
- unsigned vlfvOffset;
- } vlFixedVarArg;
-
- // VLT_MEMORY
-
- struct
- {
- void *rpValue; // pointer to the in-process
- // location of the value.
- } vlMemory;
+ ICorDebugInfo::vlReg vlReg;
+ ICorDebugInfo::vlStk vlStk;
+ ICorDebugInfo::vlRegReg vlRegReg;
+ ICorDebugInfo::vlRegStk vlRegStk;
+ ICorDebugInfo::vlStkReg vlStkReg;
+ ICorDebugInfo::vlStk2 vlStk2;
+ ICorDebugInfo::vlFPstk vlFPstk;
+ ICorDebugInfo::vlFixedVarArg vlFixedVarArg;
+ ICorDebugInfo::vlMemory vlMemory;
};
};
diff --git a/src/Native/ObjWriter/cvconst.h b/src/Native/ObjWriter/cvconst.h
index 5c4f2569e..92c5bb4e7 100644
--- a/src/Native/ObjWriter/cvconst.h
+++ b/src/Native/ObjWriter/cvconst.h
@@ -1,18 +1,6 @@
-///////////////////////////////////////////////////////////////////////////////
-//
-// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
-//
-// This code is licensed under the MIT License (MIT).
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-//
-///////////////////////////////////////////////////////////////////////////////
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
// cvconst.h - codeview constant definitions
//-----------------------------------------------------------------
diff --git a/src/Native/ObjWriter/typeBuilder.cpp b/src/Native/ObjWriter/debugInfo/codeView/codeViewTypeBuilder.cpp
index 2b6edacc5..d3af316ca 100644
--- a/src/Native/ObjWriter/typeBuilder.cpp
+++ b/src/Native/ObjWriter/debugInfo/codeView/codeViewTypeBuilder.cpp
@@ -1,55 +1,43 @@
-//===---- typeBuilder.cpp --------------------------------*- C++ -*-===//
+//===---- codeViewTypeBuilder.cpp -------------------------------*- C++ -*-===//
//
// type builder implementation using codeview::TypeTableBuilder
//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license.
-// See LICENSE file in the project root for full license information.
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
//
//===----------------------------------------------------------------------===//
-#include "typeBuilder.h"
+#include "codeViewTypeBuilder.h"
#include "llvm/BinaryFormat/COFF.h"
#include <sstream>
#include <vector>
-UserDefinedTypesBuilder::UserDefinedTypesBuilder()
- : Allocator(), TypeTable(Allocator), Streamer(nullptr),
- TargetPointerSize(0)
+UserDefinedCodeViewTypesBuilder::UserDefinedCodeViewTypesBuilder()
+ : Allocator(), TypeTable(Allocator)
{
VFTableShapeRecord vfTableShape(TypeRecordKind::VFTableShape);
ClassVTableTypeIndex = TypeTable.writeKnownType(vfTableShape);
}
-void UserDefinedTypesBuilder::SetStreamer(MCObjectStreamer *Streamer) {
- assert(this->Streamer == nullptr);
- assert(Streamer != nullptr);
- this->Streamer = Streamer;
-}
-
-void UserDefinedTypesBuilder::SetTargetPointerSize(unsigned TargetPointerSize) {
- assert(this->TargetPointerSize == 0);
- assert(TargetPointerSize != 0);
- this->TargetPointerSize = TargetPointerSize;
-}
-
-void UserDefinedTypesBuilder::EmitCodeViewMagicVersion() {
+void UserDefinedCodeViewTypesBuilder::EmitCodeViewMagicVersion() {
Streamer->EmitValueToAlignment(4);
Streamer->AddComment("Debug section magic");
Streamer->EmitIntValue(COFF::DEBUG_SECTION_MAGIC, 4);
}
-ClassOptions UserDefinedTypesBuilder::GetCommonClassOptions() {
+ClassOptions UserDefinedCodeViewTypesBuilder::GetCommonClassOptions() {
return ClassOptions();
}
-void UserDefinedTypesBuilder::EmitTypeInformation(
- MCSection *COFFDebugTypesSection) {
+void UserDefinedCodeViewTypesBuilder::EmitTypeInformation(
+ MCSection *TypeSection,
+ MCSection *StrSection) {
if (TypeTable.empty())
return;
- Streamer->SwitchSection(COFFDebugTypesSection);
+ Streamer->SwitchSection(TypeSection);
EmitCodeViewMagicVersion();
TypeTable.ForEachRecord([&](TypeIndex FieldTypeIndex,
@@ -59,7 +47,7 @@ void UserDefinedTypesBuilder::EmitTypeInformation(
});
}
-unsigned UserDefinedTypesBuilder::GetEnumFieldListType(
+unsigned UserDefinedCodeViewTypesBuilder::GetEnumFieldListType(
uint64 Count, const EnumRecordTypeDescriptor *TypeRecords) {
FieldListRecordBuilder FLRB(TypeTable);
FLRB.begin();
@@ -77,7 +65,7 @@ unsigned UserDefinedTypesBuilder::GetEnumFieldListType(
return Type.getIndex();
}
-unsigned UserDefinedTypesBuilder::GetEnumTypeIndex(
+unsigned UserDefinedCodeViewTypesBuilder::GetEnumTypeIndex(
const EnumTypeDescriptor &TypeDescriptor,
const EnumRecordTypeDescriptor *TypeRecords) {
@@ -92,11 +80,11 @@ unsigned UserDefinedTypesBuilder::GetEnumTypeIndex(
ElementTypeIndex);
TypeIndex Type = TypeTable.writeKnownType(EnumRecord);
- UserDefinedTypes.push_back(std::make_pair(TypeDescriptor.Name, Type));
+ UserDefinedTypes.push_back(std::make_pair(TypeDescriptor.Name, Type.getIndex()));
return Type.getIndex();
}
-unsigned UserDefinedTypesBuilder::GetClassTypeIndex(
+unsigned UserDefinedCodeViewTypesBuilder::GetClassTypeIndex(
const ClassTypeDescriptor &ClassDescriptor) {
TypeRecordKind Kind =
ClassDescriptor.IsStruct ? TypeRecordKind::Struct : TypeRecordKind::Class;
@@ -119,10 +107,11 @@ unsigned UserDefinedTypesBuilder::GetClassTypeIndex(
return FwdDeclTI.getIndex();
}
-unsigned UserDefinedTypesBuilder::GetCompleteClassTypeIndex(
+unsigned UserDefinedCodeViewTypesBuilder::GetCompleteClassTypeIndex(
const ClassTypeDescriptor &ClassDescriptor,
const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
- const DataFieldDescriptor *FieldsDescriptors) {
+ const DataFieldDescriptor *FieldsDescriptors,
+ const StaticDataFieldDescriptor *StaticsDescriptors) {
FieldListRecordBuilder FLBR(TypeTable);
FLBR.begin();
@@ -165,12 +154,12 @@ unsigned UserDefinedTypesBuilder::GetCompleteClassTypeIndex(
ClassDescriptor.Name, StringRef());
TypeIndex ClassIndex = TypeTable.writeKnownType(CR);
- UserDefinedTypes.push_back(std::make_pair(ClassDescriptor.Name, ClassIndex));
+ UserDefinedTypes.push_back(std::make_pair(ClassDescriptor.Name, ClassIndex.getIndex()));
return ClassIndex.getIndex();
}
-unsigned UserDefinedTypesBuilder::GetArrayTypeIndex(
+unsigned UserDefinedCodeViewTypesBuilder::GetArrayTypeIndex(
const ClassTypeDescriptor &ClassDescriptor,
const ArrayTypeDescriptor &ArrayDescriptor) {
FieldListRecordBuilder FLBR(TypeTable);
@@ -229,12 +218,12 @@ unsigned UserDefinedTypesBuilder::GetArrayTypeIndex(
StringRef());
TypeIndex ClassIndex = TypeTable.writeKnownType(CR);
- UserDefinedTypes.push_back(std::make_pair(ClassDescriptor.Name, ClassIndex));
+ UserDefinedTypes.push_back(std::make_pair(ClassDescriptor.Name, ClassIndex.getIndex()));
return ClassIndex.getIndex();
}
-unsigned UserDefinedTypesBuilder::GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor)
+unsigned UserDefinedCodeViewTypesBuilder::GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor)
{
uint32_t elementType = PointerDescriptor.ElementType;
PointerKind pointerKind = PointerDescriptor.Is64Bit ? PointerKind::Near64 : PointerKind::Near32;
@@ -246,7 +235,7 @@ unsigned UserDefinedTypesBuilder::GetPointerTypeIndex(const PointerTypeDescripto
return PointerIndex.getIndex();
}
-unsigned UserDefinedTypesBuilder::GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor,
+unsigned UserDefinedCodeViewTypesBuilder::GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor,
uint32_t const *const ArgumentTypes)
{
std::vector<TypeIndex> argumentTypes;
@@ -271,14 +260,52 @@ unsigned UserDefinedTypesBuilder::GetMemberFunctionTypeIndex(const MemberFunctio
return MemberFunctionIndex.getIndex();
}
-unsigned UserDefinedTypesBuilder::GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor)
+unsigned UserDefinedCodeViewTypesBuilder::GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor)
{
MemberFuncIdRecord MemberFuncId(TypeIndex(MemberIdDescriptor.MemberFunction), TypeIndex(MemberIdDescriptor.ParentClass), MemberIdDescriptor.Name);
TypeIndex MemberFuncIdIndex = TypeTable.writeKnownType(MemberFuncId);
return MemberFuncIdIndex.getIndex();
}
-void UserDefinedTypesBuilder::AddBaseClass(FieldListRecordBuilder &FLBR,
+unsigned UserDefinedCodeViewTypesBuilder::GetPrimitiveTypeIndex(PrimitiveTypeFlags Type) {
+ switch (Type) {
+ case PrimitiveTypeFlags::Void:
+ return TypeIndex::Void().getIndex();
+ case PrimitiveTypeFlags::Boolean:
+ return TypeIndex(SimpleTypeKind::Boolean8).getIndex();
+ case PrimitiveTypeFlags::Char:
+ return TypeIndex::WideCharacter().getIndex();
+ case PrimitiveTypeFlags::SByte:
+ return TypeIndex(SimpleTypeKind::SByte).getIndex();
+ case PrimitiveTypeFlags::Byte:
+ return TypeIndex(SimpleTypeKind::Byte).getIndex();
+ case PrimitiveTypeFlags::Int16:
+ return TypeIndex(SimpleTypeKind::Int16).getIndex();
+ case PrimitiveTypeFlags::UInt16:
+ return TypeIndex(SimpleTypeKind::UInt16).getIndex();
+ case PrimitiveTypeFlags::Int32:
+ return TypeIndex::Int32().getIndex();
+ case PrimitiveTypeFlags::UInt32:
+ return TypeIndex::UInt32().getIndex();
+ case PrimitiveTypeFlags::Int64:
+ return TypeIndex::Int64().getIndex();
+ case PrimitiveTypeFlags::UInt64:
+ return TypeIndex::UInt64().getIndex();
+ case PrimitiveTypeFlags::Single:
+ return TypeIndex::Float32().getIndex();
+ case PrimitiveTypeFlags::Double:
+ return TypeIndex::Float64().getIndex();
+ case PrimitiveTypeFlags::IntPtr:
+ case PrimitiveTypeFlags::UIntPtr:
+ return TargetPointerSize == 4 ? TypeIndex::VoidPointer32().getIndex() :
+ TypeIndex::VoidPointer64().getIndex();
+ default:
+ assert(false && "Unexpected type");
+ return 0;
+ }
+}
+
+void UserDefinedCodeViewTypesBuilder::AddBaseClass(FieldListRecordBuilder &FLBR,
unsigned BaseClassId) {
MemberAttributes def;
TypeIndex BaseTypeIndex(BaseClassId);
@@ -286,7 +313,7 @@ void UserDefinedTypesBuilder::AddBaseClass(FieldListRecordBuilder &FLBR,
FLBR.writeMemberType(BCR);
}
-void UserDefinedTypesBuilder::AddClassVTShape(FieldListRecordBuilder &FLBR) {
+void UserDefinedCodeViewTypesBuilder::AddClassVTShape(FieldListRecordBuilder &FLBR) {
VFPtrRecord VfPtr(ClassVTableTypeIndex);
FLBR.writeMemberType(VfPtr);
}
diff --git a/src/Native/ObjWriter/debugInfo/codeView/codeViewTypeBuilder.h b/src/Native/ObjWriter/debugInfo/codeView/codeViewTypeBuilder.h
new file mode 100644
index 000000000..5534cc7d3
--- /dev/null
+++ b/src/Native/ObjWriter/debugInfo/codeView/codeViewTypeBuilder.h
@@ -0,0 +1,73 @@
+//===---- codeViewTypeBuilder.h ---------------------------------*- C++ -*-===//
+//
+// type builder is used to convert .Net types into CodeView descriptors.
+//
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include "debugInfo/typeBuilder.h"
+#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
+
+#include <vector>
+
+using namespace llvm::codeview;
+
+class ArrayDimensionsDescriptor {
+public:
+ const char *GetLengthName(unsigned index);
+ const char *GetBoundsName(unsigned index);
+
+private:
+ void Resize(unsigned NewSize);
+
+ std::vector<std::string> Lengths;
+ std::vector<std::string> Bounds;
+};
+
+class UserDefinedCodeViewTypesBuilder : public UserDefinedTypesBuilder {
+public:
+ UserDefinedCodeViewTypesBuilder();
+ void EmitTypeInformation(MCSection *TypeSection, MCSection *StrSection = nullptr) override;
+
+ unsigned GetEnumTypeIndex(const EnumTypeDescriptor &TypeDescriptor,
+ const EnumRecordTypeDescriptor *TypeRecords) override;
+ unsigned GetClassTypeIndex(const ClassTypeDescriptor &ClassDescriptor) override;
+ unsigned GetCompleteClassTypeIndex(
+ const ClassTypeDescriptor &ClassDescriptor,
+ const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
+ const DataFieldDescriptor *FieldsDescriptors,
+ const StaticDataFieldDescriptor *StaticsDescriptors) override;
+
+ unsigned GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor,
+ const ArrayTypeDescriptor &ArrayDescriptor) override;
+
+ unsigned GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor) override;
+
+ unsigned GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor,
+ uint32_t const *const ArgumentTypes) override;
+
+ unsigned GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor) override;
+
+ unsigned GetPrimitiveTypeIndex(PrimitiveTypeFlags Type) override;
+
+private:
+ void EmitCodeViewMagicVersion();
+ ClassOptions GetCommonClassOptions();
+
+ unsigned GetEnumFieldListType(uint64 Count,
+ const EnumRecordTypeDescriptor *TypeRecords);
+
+ void AddBaseClass(FieldListRecordBuilder &FLBR, unsigned BaseClassId);
+ void AddClassVTShape(FieldListRecordBuilder &FLBR);
+
+ BumpPtrAllocator Allocator;
+ TypeTableBuilder TypeTable;
+
+ ArrayDimensionsDescriptor ArrayDimentions;
+ TypeIndex ClassVTableTypeIndex;
+}; \ No newline at end of file
diff --git a/src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.cpp b/src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.cpp
new file mode 100644
index 000000000..23ee3fa30
--- /dev/null
+++ b/src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.cpp
@@ -0,0 +1,284 @@
+//===---- dwarfAbbrev.cpp ---------------------------------------*- C++ -*-===//
+//
+// dwarf abbreviations implementation
+//
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "dwarfAbbrev.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+
+namespace DwarfAbbrev {
+
+void Dump(MCObjectStreamer *Streamer, uint16_t DwarfVersion, unsigned TargetPointerSize) {
+ uint16_t DW_FORM_size;
+ switch (TargetPointerSize) {
+ case 1:
+ DW_FORM_size = dwarf::DW_FORM_data1;
+ break;
+ case 2:
+ DW_FORM_size = dwarf::DW_FORM_data2;
+ break;
+ case 4:
+ DW_FORM_size = dwarf::DW_FORM_data4;
+ break;
+ case 8:
+ DW_FORM_size = dwarf::DW_FORM_data8;
+ break;
+ default:
+ assert(false && "Unexpected TargerPointerSize");
+ return;
+ }
+
+ const uint16_t AbbrevTable[] = {
+ CompileUnit,
+ dwarf::DW_TAG_compile_unit, dwarf::DW_CHILDREN_yes,
+ dwarf::DW_AT_producer, dwarf::DW_FORM_string,
+ dwarf::DW_AT_language, dwarf::DW_FORM_data2,
+ dwarf::DW_AT_stmt_list, (DwarfVersion >= 4 ? dwarf::DW_FORM_sec_offset : dwarf::DW_FORM_data4),
+ 0, 0,
+
+ BaseType,
+ dwarf::DW_TAG_base_type, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_encoding, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1,
+ 0, 0,
+
+ EnumerationType,
+ dwarf::DW_TAG_enumeration_type, dwarf::DW_CHILDREN_yes,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1,
+ 0, 0,
+
+ Enumerator1,
+ dwarf::DW_TAG_enumerator, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_const_value, dwarf::DW_FORM_data1,
+ 0, 0,
+
+ Enumerator2,
+ dwarf::DW_TAG_enumerator, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_const_value, dwarf::DW_FORM_data2,
+ 0, 0,
+
+ Enumerator4,
+ dwarf::DW_TAG_enumerator, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_const_value, dwarf::DW_FORM_data4,
+ 0, 0,
+
+ Enumerator8,
+ dwarf::DW_TAG_enumerator, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_const_value, dwarf::DW_FORM_data8,
+ 0, 0,
+
+ TypeDef,
+ dwarf::DW_TAG_typedef, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ 0, 0,
+
+ Subprogram,
+ dwarf::DW_TAG_subprogram, dwarf::DW_CHILDREN_yes,
+ dwarf::DW_AT_specification, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
+ dwarf::DW_AT_high_pc, DW_FORM_size,
+ dwarf::DW_AT_frame_base, dwarf::DW_FORM_exprloc,
+ dwarf::DW_AT_object_pointer, dwarf::DW_FORM_ref4,
+ 0, 0,
+
+ SubprogramStatic,
+ dwarf::DW_TAG_subprogram, dwarf::DW_CHILDREN_yes,
+ dwarf::DW_AT_specification, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
+ dwarf::DW_AT_high_pc, DW_FORM_size,
+ dwarf::DW_AT_frame_base, dwarf::DW_FORM_exprloc,
+ 0, 0,
+
+ SubprogramSpec,
+ dwarf::DW_TAG_subprogram, dwarf::DW_CHILDREN_yes,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_linkage_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_external, dwarf::DW_FORM_flag_present,
+ dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
+ dwarf::DW_AT_object_pointer, dwarf::DW_FORM_ref4,
+ 0, 0,
+
+ SubprogramStaticSpec,
+ dwarf::DW_TAG_subprogram, dwarf::DW_CHILDREN_yes,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_linkage_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_external, dwarf::DW_FORM_flag_present,
+ dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
+ 0, 0,
+
+ Variable,
+ dwarf::DW_TAG_variable, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_location, dwarf::DW_FORM_exprloc,
+ 0, 0,
+
+ VariableLoc,
+ dwarf::DW_TAG_variable, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_location, dwarf::DW_FORM_sec_offset,
+ 0, 0,
+
+ VariableStatic,
+ dwarf::DW_TAG_variable, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_specification, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_location, dwarf::DW_FORM_exprloc,
+ 0, 0,
+
+ FormalParameter,
+ dwarf::DW_TAG_formal_parameter, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_location, dwarf::DW_FORM_exprloc,
+ 0, 0,
+
+ FormalParameterThis,
+ dwarf::DW_TAG_formal_parameter, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_location, dwarf::DW_FORM_exprloc,
+ dwarf::DW_AT_artificial, dwarf::DW_FORM_flag_present,
+ 0, 0,
+
+ FormalParameterLoc,
+ dwarf::DW_TAG_formal_parameter, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_location, dwarf::DW_FORM_sec_offset,
+ 0, 0,
+
+ FormalParameterThisLoc,
+ dwarf::DW_TAG_formal_parameter, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_location, dwarf::DW_FORM_sec_offset,
+ dwarf::DW_AT_artificial, dwarf::DW_FORM_flag_present,
+ 0, 0,
+
+ FormalParameterSpec,
+ dwarf::DW_TAG_formal_parameter, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ 0, 0,
+
+ FormalParameterThisSpec,
+ dwarf::DW_TAG_formal_parameter, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_artificial, dwarf::DW_FORM_flag_present,
+ 0, 0,
+
+ ClassType,
+ dwarf::DW_TAG_class_type, dwarf::DW_CHILDREN_yes,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_byte_size, dwarf::DW_FORM_data4,
+ 0, 0,
+
+ ClassTypeDecl,
+ dwarf::DW_TAG_class_type, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
+ 0, 0,
+
+ ClassMember,
+ dwarf::DW_TAG_member, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data4,
+ 0, 0,
+
+ ClassMemberStatic,
+ dwarf::DW_TAG_member, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_name, dwarf::DW_FORM_strp,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_external, dwarf::DW_FORM_flag_present,
+ dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
+ 0, 0,
+
+ PointerType,
+ dwarf::DW_TAG_pointer_type, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1,
+ 0, 0,
+
+ ReferenceType,
+ dwarf::DW_TAG_reference_type, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1,
+ 0, 0,
+
+ ArrayType,
+ dwarf::DW_TAG_array_type, dwarf::DW_CHILDREN_yes,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ 0, 0,
+
+ SubrangeType,
+ dwarf::DW_TAG_subrange_type, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_upper_bound, dwarf::DW_FORM_udata,
+ 0, 0,
+
+ ClassInheritance,
+ dwarf::DW_TAG_inheritance, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
+ 0, 0,
+
+ LexicalBlock,
+ dwarf::DW_TAG_lexical_block, dwarf::DW_CHILDREN_yes,
+ dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
+ dwarf::DW_AT_high_pc, DW_FORM_size,
+ 0, 0,
+
+ TryBlock,
+ dwarf::DW_TAG_try_block, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
+ dwarf::DW_AT_high_pc, DW_FORM_size,
+ 0, 0,
+
+ CatchBlock,
+ dwarf::DW_TAG_catch_block, dwarf::DW_CHILDREN_no,
+ dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
+ dwarf::DW_AT_high_pc, DW_FORM_size,
+ 0, 0
+ };
+
+ MCContext &context = Streamer->getContext();
+ Streamer->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
+
+ for (uint16_t e : AbbrevTable) {
+ Streamer->EmitULEB128IntValue(e);
+ }
+}
+
+} \ No newline at end of file
diff --git a/src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.h b/src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.h
new file mode 100644
index 000000000..82589c027
--- /dev/null
+++ b/src/Native/ObjWriter/debugInfo/dwarf/dwarfAbbrev.h
@@ -0,0 +1,59 @@
+//===---- dwarfAbbrev.h -----------------------------------------*- C++ -*-===//
+//
+// dwarf abbreviations
+//
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/MC/MCObjectStreamer.h"
+
+using namespace llvm;
+
+namespace DwarfAbbrev {
+
+enum DwarfAbbrev : uint16_t
+{
+ CompileUnit = 0x1,
+ BaseType,
+ EnumerationType,
+ Enumerator1,
+ Enumerator2,
+ Enumerator4,
+ Enumerator8,
+ TypeDef,
+ Subprogram,
+ SubprogramStatic,
+ SubprogramSpec,
+ SubprogramStaticSpec,
+ Variable,
+ VariableLoc,
+ VariableStatic,
+ FormalParameter,
+ FormalParameterThis,
+ FormalParameterLoc,
+ FormalParameterThisLoc,
+ FormalParameterSpec,
+ FormalParameterThisSpec,
+ ClassType,
+ ClassTypeDecl,
+ ClassMember,
+ ClassMemberStatic,
+ PointerType,
+ ReferenceType,
+ ArrayType,
+ SubrangeType,
+ ClassInheritance,
+ LexicalBlock,
+ TryBlock,
+ CatchBlock
+};
+
+void Dump(MCObjectStreamer *Streamer, uint16_t DwarfVersion, unsigned TargetPointerSize);
+
+}
diff --git a/src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.cpp b/src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.cpp
new file mode 100644
index 000000000..518608673
--- /dev/null
+++ b/src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.cpp
@@ -0,0 +1,1066 @@
+//===---- dwarfGen.cpp ------------------------------------------*- C++ -*-===//
+//
+// dwarf generator implementation
+//
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "dwarfGen.h"
+#include "dwarfAbbrev.h"
+
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/Support/LEB128.h"
+
+#ifdef FEATURE_LANGID_CS
+#define DW_LANG_MICROSOFT_CSHARP 0x9e57
+#endif
+
+// Keep sync with ICorDebugInfo::RegNum (cordebuginfo.h)
+
+enum class RegNumX86
+{
+ REGNUM_EAX,
+ REGNUM_ECX,
+ REGNUM_EDX,
+ REGNUM_EBX,
+ REGNUM_ESP,
+ REGNUM_EBP,
+ REGNUM_ESI,
+ REGNUM_EDI,
+ REGNUM_COUNT,
+ REGNUM_FP = REGNUM_EBP,
+ REGNUM_SP = REGNUM_ESP
+};
+
+enum class RegNumArm
+{
+ REGNUM_R0,
+ REGNUM_R1,
+ REGNUM_R2,
+ REGNUM_R3,
+ REGNUM_R4,
+ REGNUM_R5,
+ REGNUM_R6,
+ REGNUM_R7,
+ REGNUM_R8,
+ REGNUM_R9,
+ REGNUM_R10,
+ REGNUM_R11,
+ REGNUM_R12,
+ REGNUM_SP,
+ REGNUM_LR,
+ REGNUM_PC,
+ REGNUM_COUNT,
+ REGNUM_FP = REGNUM_R7
+};
+
+enum class RegNumArm64
+{
+ REGNUM_X0,
+ REGNUM_X1,
+ REGNUM_X2,
+ REGNUM_X3,
+ REGNUM_X4,
+ REGNUM_X5,
+ REGNUM_X6,
+ REGNUM_X7,
+ REGNUM_X8,
+ REGNUM_X9,
+ REGNUM_X10,
+ REGNUM_X11,
+ REGNUM_X12,
+ REGNUM_X13,
+ REGNUM_X14,
+ REGNUM_X15,
+ REGNUM_X16,
+ REGNUM_X17,
+ REGNUM_X18,
+ REGNUM_X19,
+ REGNUM_X20,
+ REGNUM_X21,
+ REGNUM_X22,
+ REGNUM_X23,
+ REGNUM_X24,
+ REGNUM_X25,
+ REGNUM_X26,
+ REGNUM_X27,
+ REGNUM_X28,
+ REGNUM_FP,
+ REGNUM_LR,
+ REGNUM_SP,
+ REGNUM_PC,
+ REGNUM_COUNT
+};
+
+enum class RegNumAmd64
+{
+ REGNUM_RAX,
+ REGNUM_RCX,
+ REGNUM_RDX,
+ REGNUM_RBX,
+ REGNUM_RSP,
+ REGNUM_RBP,
+ REGNUM_RSI,
+ REGNUM_RDI,
+ REGNUM_R8,
+ REGNUM_R9,
+ REGNUM_R10,
+ REGNUM_R11,
+ REGNUM_R12,
+ REGNUM_R13,
+ REGNUM_R14,
+ REGNUM_R15,
+ REGNUM_COUNT,
+ REGNUM_SP = REGNUM_RSP,
+ REGNUM_FP = REGNUM_RBP
+};
+
+// Helper routines from lib/MC/MCDwarf.cpp
+static const MCExpr *forceExpAbs(MCStreamer &OS, const MCExpr* Expr) {
+ MCContext &Context = OS.getContext();
+ assert(!isa<MCSymbolRefExpr>(Expr));
+ if (Context.getAsmInfo()->hasAggressiveSymbolFolding())
+ return Expr;
+
+ MCSymbol *ABS = Context.createTempSymbol();
+ OS.EmitAssignment(ABS, Expr);
+ return MCSymbolRefExpr::create(ABS, Context);
+}
+
+static void emitAbsValue(MCStreamer &OS, const MCExpr *Value, unsigned Size) {
+ const MCExpr *ABS = forceExpAbs(OS, Value);
+ OS.EmitValue(ABS, Size);
+}
+
+static const MCExpr *MakeStartMinusEndExpr(const MCStreamer &MCOS,
+ const MCSymbol &Start,
+ const MCSymbol &End,
+ int IntVal) {
+ MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
+ const MCExpr *Res =
+ MCSymbolRefExpr::create(&End, Variant, MCOS.getContext());
+ const MCExpr *RHS =
+ MCSymbolRefExpr::create(&Start, Variant, MCOS.getContext());
+ const MCExpr *Res1 =
+ MCBinaryExpr::create(MCBinaryExpr::Sub, Res, RHS, MCOS.getContext());
+ const MCExpr *Res2 =
+ MCConstantExpr::create(IntVal, MCOS.getContext());
+ const MCExpr *Res3 =
+ MCBinaryExpr::create(MCBinaryExpr::Sub, Res1, Res2, MCOS.getContext());
+ return Res3;
+}
+
+static int GetDwarfRegNum(Triple::ArchType ArchType, int RegNum) {
+ switch (ArchType) {
+ case Triple::x86:
+ switch (static_cast<RegNumX86>(RegNum)) {
+ case RegNumX86::REGNUM_EAX: return 0;
+ case RegNumX86::REGNUM_ECX: return 1;
+ case RegNumX86::REGNUM_EDX: return 2;
+ case RegNumX86::REGNUM_EBX: return 3;
+ case RegNumX86::REGNUM_ESP: return 4;
+ case RegNumX86::REGNUM_EBP: return 5;
+ case RegNumX86::REGNUM_ESI: return 6;
+ case RegNumX86::REGNUM_EDI: return 7;
+ // fp registers
+ default:
+ return RegNum - static_cast<int>(RegNumX86::REGNUM_COUNT) + 32;
+ }
+ case Triple::arm: // fall through
+ case Triple::armeb: // fall through
+ case Triple::thumb: // fall through
+ case Triple::thumbeb:
+ switch (static_cast<RegNumArm>(RegNum)) {
+ case RegNumArm::REGNUM_R0: return 0;
+ case RegNumArm::REGNUM_R1: return 1;
+ case RegNumArm::REGNUM_R2: return 2;
+ case RegNumArm::REGNUM_R3: return 3;
+ case RegNumArm::REGNUM_R4: return 4;
+ case RegNumArm::REGNUM_R5: return 5;
+ case RegNumArm::REGNUM_R6: return 6;
+ case RegNumArm::REGNUM_R7: return 7;
+ case RegNumArm::REGNUM_R8: return 8;
+ case RegNumArm::REGNUM_R9: return 9;
+ case RegNumArm::REGNUM_R10: return 10;
+ case RegNumArm::REGNUM_R11: return 11;
+ case RegNumArm::REGNUM_R12: return 12;
+ case RegNumArm::REGNUM_SP: return 13;
+ case RegNumArm::REGNUM_LR: return 14;
+ case RegNumArm::REGNUM_PC: return 15;
+ // fp registers
+ default:
+ return RegNum - static_cast<int>(RegNumArm::REGNUM_COUNT) + 64;
+ }
+ case Triple::aarch64: // fall through
+ case Triple::aarch64_be:
+ switch (static_cast<RegNumArm64>(RegNum)) {
+ case RegNumArm64::REGNUM_X0: return 0;
+ case RegNumArm64::REGNUM_X1: return 1;
+ case RegNumArm64::REGNUM_X2: return 2;
+ case RegNumArm64::REGNUM_X3: return 3;
+ case RegNumArm64::REGNUM_X4: return 4;
+ case RegNumArm64::REGNUM_X5: return 5;
+ case RegNumArm64::REGNUM_X6: return 6;
+ case RegNumArm64::REGNUM_X7: return 7;
+ case RegNumArm64::REGNUM_X8: return 8;
+ case RegNumArm64::REGNUM_X9: return 9;
+ case RegNumArm64::REGNUM_X10: return 10;
+ case RegNumArm64::REGNUM_X11: return 11;
+ case RegNumArm64::REGNUM_X12: return 12;
+ case RegNumArm64::REGNUM_X13: return 13;
+ case RegNumArm64::REGNUM_X14: return 14;
+ case RegNumArm64::REGNUM_X15: return 15;
+ case RegNumArm64::REGNUM_X16: return 16;
+ case RegNumArm64::REGNUM_X17: return 17;
+ case RegNumArm64::REGNUM_X18: return 18;
+ case RegNumArm64::REGNUM_X19: return 19;
+ case RegNumArm64::REGNUM_X20: return 20;
+ case RegNumArm64::REGNUM_X21: return 21;
+ case RegNumArm64::REGNUM_X22: return 22;
+ case RegNumArm64::REGNUM_X23: return 23;
+ case RegNumArm64::REGNUM_X24: return 24;
+ case RegNumArm64::REGNUM_X25: return 25;
+ case RegNumArm64::REGNUM_X26: return 26;
+ case RegNumArm64::REGNUM_X27: return 27;
+ case RegNumArm64::REGNUM_X28: return 28;
+ case RegNumArm64::REGNUM_FP: return 29;
+ case RegNumArm64::REGNUM_LR: return 30;
+ case RegNumArm64::REGNUM_SP: return 31;
+ case RegNumArm64::REGNUM_PC: return 32;
+ // fp registers
+ default:
+ return RegNum - static_cast<int>(RegNumArm64::REGNUM_COUNT) + 64;
+ }
+ case Triple::x86_64:
+ switch (static_cast<RegNumAmd64>(RegNum)) {
+ case RegNumAmd64::REGNUM_RAX: return 0;
+ case RegNumAmd64::REGNUM_RDX: return 1;
+ case RegNumAmd64::REGNUM_RCX: return 2;
+ case RegNumAmd64::REGNUM_RBX: return 3;
+ case RegNumAmd64::REGNUM_RSI: return 4;
+ case RegNumAmd64::REGNUM_RDI: return 5;
+ case RegNumAmd64::REGNUM_RBP: return 6;
+ case RegNumAmd64::REGNUM_RSP: return 7;
+ case RegNumAmd64::REGNUM_R8: return 8;
+ case RegNumAmd64::REGNUM_R9: return 9;
+ case RegNumAmd64::REGNUM_R10: return 10;
+ case RegNumAmd64::REGNUM_R11: return 11;
+ case RegNumAmd64::REGNUM_R12: return 12;
+ case RegNumAmd64::REGNUM_R13: return 13;
+ case RegNumAmd64::REGNUM_R14: return 14;
+ case RegNumAmd64::REGNUM_R15: return 15;
+ // fp registers
+ default:
+ return RegNum - static_cast<int>(RegNumAmd64::REGNUM_COUNT) + 17;
+ }
+ default:
+ assert(false && "Unexpected architecture");
+ return 0;
+ }
+}
+
+static int GetDwarfFpRegNum(Triple::ArchType ArchType)
+{
+ switch (ArchType) {
+ case Triple::x86:
+ return GetDwarfRegNum(ArchType, static_cast<int>(RegNumX86::REGNUM_FP));
+ case Triple::arm: // fall through
+ case Triple::armeb: // fall through
+ case Triple::thumb: // fall through
+ case Triple::thumbeb:
+ return GetDwarfRegNum(ArchType, static_cast<int>(RegNumArm::REGNUM_FP));
+ case Triple::aarch64: // fall through
+ case Triple::aarch64_be:
+ return GetDwarfRegNum(ArchType, static_cast<int>(RegNumArm64::REGNUM_FP));
+ case Triple::x86_64:
+ return GetDwarfRegNum(ArchType, static_cast<int>(RegNumAmd64::REGNUM_FP));
+ default:
+ assert(false && "Unexpected architecture");
+ return 0;
+ }
+}
+
+static void EmitVarLocation(MCObjectStreamer *Streamer,
+ const ICorDebugInfo::NativeVarInfo &VarInfo,
+ bool IsLocList = false) {
+ MCContext &context = Streamer->getContext();
+ unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize();
+ Triple::ArchType ArchType = context.getObjectFileInfo()->getTargetTriple().getArch();
+
+ int DwarfRegNum;
+ int DwarfRegNum2;
+ int DwarfBaseRegNum;
+ unsigned Len;
+
+ bool IsByRef = false;
+ bool IsStk2 = false;
+ bool IsRegStk = false;
+
+ switch (VarInfo.loc.vlType) {
+ case ICorDebugInfo::VLT_REG_BYREF: // fall through
+ IsByRef = true;
+ case ICorDebugInfo::VLT_REG_FP: // fall through
+ case ICorDebugInfo::VLT_REG: {
+ DwarfRegNum = GetDwarfRegNum(ArchType, VarInfo.loc.vlReg.vlrReg);
+ if (IsByRef) {
+ Len = 2;
+ if (IsLocList) {
+ Streamer->EmitIntValue(Len, 2);
+ } else {
+ Streamer->EmitULEB128IntValue(Len);
+ }
+ Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_breg0, 1);
+ Streamer->EmitSLEB128IntValue(0);
+ } else {
+ Len = 1;
+ if (IsLocList) {
+ Streamer->EmitIntValue(Len, 2);
+ } else {
+ Streamer->EmitULEB128IntValue(Len);
+ }
+ Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_reg0, 1);
+ }
+
+ break;
+ }
+ case ICorDebugInfo::VLT_STK_BYREF: // fall through
+ IsByRef = true;
+ case ICorDebugInfo::VLT_STK2:
+ IsStk2 = true;
+ case ICorDebugInfo::VLT_STK: {
+ DwarfBaseRegNum = GetDwarfRegNum(ArchType, IsStk2 ? VarInfo.loc.vlStk2.vls2BaseReg :
+ VarInfo.loc.vlStk.vlsBaseReg);
+
+ SmallString<128> Tmp;
+ raw_svector_ostream OSE(Tmp);
+ encodeSLEB128(IsStk2 ? VarInfo.loc.vlStk2.vls2Offset :
+ VarInfo.loc.vlStk.vlsOffset, OSE);
+ StringRef OffsetRepr = OSE.str();
+
+ if (IsByRef) {
+ Len = OffsetRepr.size() + 2;
+ if (IsLocList) {
+ Streamer->EmitIntValue(Len, 2);
+ } else {
+ Streamer->EmitULEB128IntValue(Len);
+ }
+ Streamer->EmitIntValue(DwarfBaseRegNum + dwarf::DW_OP_breg0, 1);
+ Streamer->EmitBytes(OffsetRepr);
+ Streamer->EmitIntValue(dwarf::DW_OP_deref, 1);
+ } else {
+ Len = OffsetRepr.size() + 1;
+ if (IsLocList) {
+ Streamer->EmitIntValue(Len, 2);
+ } else {
+ Streamer->EmitULEB128IntValue(Len);
+ }
+ Streamer->EmitIntValue(DwarfBaseRegNum + dwarf::DW_OP_breg0, 1);
+ Streamer->EmitBytes(OffsetRepr);
+ }
+
+ break;
+ }
+ case ICorDebugInfo::VLT_REG_REG: {
+ DwarfRegNum = GetDwarfRegNum(ArchType, VarInfo.loc.vlRegReg.vlrrReg1);
+ DwarfRegNum2 = GetDwarfRegNum(ArchType, VarInfo.loc.vlRegReg.vlrrReg2);
+
+ Len = (1 /* DW_OP_reg */ + 1 /* DW_OP_piece */ + 1 /* Reg size */) * 2 + 1;
+ if (IsLocList) {
+ Streamer->EmitIntValue(Len, 2);
+ } else {
+ Streamer->EmitULEB128IntValue(Len + 1);
+ }
+
+ Streamer->EmitIntValue(DwarfRegNum2 + dwarf::DW_OP_reg0, 1);
+ Streamer->EmitIntValue(dwarf::DW_OP_piece, 1);
+ Streamer->EmitULEB128IntValue(TargetPointerSize);
+
+ Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_reg0, 1);
+ Streamer->EmitIntValue(dwarf::DW_OP_piece, 1);
+ Streamer->EmitULEB128IntValue(TargetPointerSize);
+
+ break;
+ }
+ case ICorDebugInfo::VLT_REG_STK: // fall through
+ IsRegStk = true;
+ case ICorDebugInfo::VLT_STK_REG: {
+ DwarfRegNum = GetDwarfRegNum(ArchType, IsRegStk ? VarInfo.loc.vlRegStk.vlrsReg :
+ VarInfo.loc.vlStkReg.vlsrReg);
+ DwarfBaseRegNum = GetDwarfRegNum(ArchType, IsRegStk ? VarInfo.loc.vlRegStk.vlrsStk.vlrssBaseReg :
+ VarInfo.loc.vlStkReg.vlsrStk.vlsrsBaseReg);
+
+ SmallString<128> Tmp;
+ raw_svector_ostream OSE(Tmp);
+ encodeSLEB128(IsRegStk ? VarInfo.loc.vlRegStk.vlrsStk.vlrssOffset :
+ VarInfo.loc.vlStkReg.vlsrStk.vlsrsOffset, OSE);
+ StringRef OffsetRepr = OSE.str();
+
+ Len = (1 /* DW_OP_reg */ + 1 /* DW_OP_piece */ + 1 /* Reg size */) +
+ (1 /*DW_OP_breg */ + OffsetRepr.size() + 1 /* DW_OP_piece */ + 1 /* Reg size */) + 1;
+
+ if (IsLocList) {
+ Streamer->EmitIntValue(Len, 2);
+ } else {
+ Streamer->EmitULEB128IntValue(Len + 1);
+ }
+
+ if (IsRegStk) {
+ Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_reg0, 1);
+ Streamer->EmitIntValue(dwarf::DW_OP_piece, 1);
+ Streamer->EmitULEB128IntValue(TargetPointerSize);
+
+ Streamer->EmitIntValue(DwarfBaseRegNum + dwarf::DW_OP_breg0, 1);
+ Streamer->EmitBytes(OffsetRepr);
+ Streamer->EmitIntValue(dwarf::DW_OP_piece, 1);
+ Streamer->EmitULEB128IntValue(TargetPointerSize);
+ } else {
+ Streamer->EmitIntValue(DwarfBaseRegNum + dwarf::DW_OP_breg0, 1);
+ Streamer->EmitBytes(OffsetRepr);
+ Streamer->EmitIntValue(dwarf::DW_OP_piece, 1);
+ Streamer->EmitULEB128IntValue(TargetPointerSize);
+
+ Streamer->EmitIntValue(DwarfRegNum + dwarf::DW_OP_reg0, 1);
+ Streamer->EmitIntValue(dwarf::DW_OP_piece, 1);
+ Streamer->EmitULEB128IntValue(TargetPointerSize);
+ }
+
+ break;
+ }
+ case ICorDebugInfo::VLT_FPSTK:
+ case ICorDebugInfo::VLT_FIXED_VA:
+ assert(false && "Unsupported varloc type!");
+ default:
+ assert(false && "Unknown varloc type!");
+ if (IsLocList) {
+ Streamer->EmitIntValue(0, 2);
+ } else {
+ Streamer->EmitULEB128IntValue(0);
+ }
+ }
+}
+
+// Lexical scope
+
+class LexicalScope
+{
+public:
+ LexicalScope(uint64_t Start, uint64_t End, bool IsFuncScope = false) :
+ Start(Start),
+ End(End),
+ IsFuncScope(IsFuncScope) {}
+
+ LexicalScope(VarInfo *Info) :
+ Start(Info->GetStartOffset()),
+ End(Info->GetEndOffset()),
+ IsFuncScope(false) { Vars.push_back(Info); }
+
+ bool IsContains(const VarInfo *Info) const {
+ return Start <= Info->GetStartOffset() && End >= Info->GetEndOffset();
+ }
+
+ void AddVar(VarInfo *Info);
+
+ void Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection, const MCExpr *SymExpr);
+
+private:
+ uint64_t Start;
+ uint64_t End;
+ bool IsFuncScope;
+ std::vector<VarInfo*> Vars;
+ std::vector<LexicalScope> InnerScopes;
+};
+
+void LexicalScope::AddVar(VarInfo *Info) {
+ if (Info->IsParam() && IsFuncScope) {
+ Vars.push_back(Info);
+ return;
+ }
+
+ if (!IsContains(Info))
+ return;
+
+ uint64_t VarStart = Info->GetStartOffset();
+ uint64_t VarEnd = Info->GetEndOffset();
+
+ // Var belongs to inner scope
+ if (VarStart != Start || VarEnd != End) {
+ // Try to add variable to one the inner scopes
+ for (auto &Scope : InnerScopes) {
+ if (Scope.IsContains(Info)) {
+ Scope.AddVar(Info);
+ return;
+ }
+ }
+ // We need to create new inner scope for this var
+ InnerScopes.emplace_back(Info);
+ } else {
+ Vars.push_back(Info);
+ }
+}
+
+void LexicalScope::Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection, const MCExpr *SymExpr) {
+ Streamer->SwitchSection(TypeSection);
+
+ if (!IsFuncScope)
+ {
+ // Dump lexical block DIE
+ MCContext &context = Streamer->getContext();
+ unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize();
+
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::LexicalBlock);
+
+ // DW_AT_low_pc
+ const MCExpr *StartExpr = MCConstantExpr::create(Start, context);
+ const MCExpr *LowPcExpr = MCBinaryExpr::create(MCBinaryExpr::Add, SymExpr,
+ StartExpr, context);
+ Streamer->EmitValue(LowPcExpr, TargetPointerSize);
+
+ // DW_AT_high_pc
+ Streamer->EmitIntValue(End - Start, TargetPointerSize);
+ }
+
+ for (auto *Var : Vars) {
+ Var->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+
+ for (auto &Scope : InnerScopes) {
+ Scope.Dump(TypeBuilder, Streamer, TypeSection, StrSection, SymExpr);
+ }
+
+ if (!IsFuncScope) {
+ // Terminate block
+ Streamer->EmitIntValue(0, 1);
+ }
+}
+
+// StaticVarInfo
+
+class StaticVarInfo : public DwarfInfo
+{
+public:
+ StaticVarInfo(const DwarfStaticDataField *StaticField) : StaticField(StaticField) {}
+
+ void Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) override;
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override {};
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ const DwarfStaticDataField *StaticField;
+
+ void EmitLocation(MCObjectStreamer *Streamer);
+};
+
+void StaticVarInfo::Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ MCContext &context = Streamer->getContext();
+ MCSymbol *Sym = context.getOrCreateSymbol(Twine(StaticField->GetStaticDataName()));
+ if (Sym->isUndefined())
+ return;
+
+ DwarfInfo::Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+}
+
+void StaticVarInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::VariableStatic);
+
+ // DW_AT_specification
+ EmitInfoOffset(Streamer, StaticField, 4);
+
+ // DW_AT_location
+ EmitLocation(Streamer);
+}
+
+void StaticVarInfo::EmitLocation(MCObjectStreamer *Streamer) {
+ MCContext &context = Streamer->getContext();
+ unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize();
+
+ MCSymbol *Sym = context.getOrCreateSymbol(Twine(StaticField->GetStaticDataName()));
+
+ SmallString<128> Tmp;
+ raw_svector_ostream OSE(Tmp);
+ encodeULEB128(StaticField->GetStaticOffset(), OSE);
+ StringRef OffsetRepr = OSE.str();
+
+ unsigned Len = 1 /* DW_OP_addr */ + TargetPointerSize;
+
+ // Need double deref
+ if (StaticField->IsStaticDataInObject()) {
+ Len += (1 /* DW_OP_deref */) * 2;
+ }
+
+ if (StaticField->GetStaticOffset() != 0) {
+ Len += 1 /* DW_OP_plus_uconst */ + OffsetRepr.size();
+ }
+
+ Streamer->EmitULEB128IntValue(Len);
+ Streamer->EmitIntValue(dwarf::DW_OP_addr, 1);
+ Streamer->EmitSymbolValue(Sym, TargetPointerSize);
+
+ if (StaticField->IsStaticDataInObject()) {
+ Streamer->EmitIntValue(dwarf::DW_OP_deref, 1);
+ Streamer->EmitIntValue(dwarf::DW_OP_deref, 1);
+ }
+
+ if (StaticField->GetStaticOffset() != 0) {
+ Streamer->EmitIntValue(dwarf::DW_OP_plus_uconst, 1);
+ Streamer->EmitBytes(OffsetRepr);
+ }
+}
+
+// VarInfo
+
+VarInfo::VarInfo(const DebugVarInfo &Info, bool IsThis) :
+ DebugInfo(Info),
+ LocSymbol(nullptr),
+ IsThis(IsThis) {
+ if (!Info.IsParam) {
+ assert(!Info.Ranges.empty());
+ StartOffset = Info.Ranges.front().startOffset;
+ EndOffset = Info.Ranges.back().endOffset;
+ } else {
+ // Params belong to func scope
+ StartOffset = 0xFFFFFFFF;
+ EndOffset = 0xFFFFFFFF;
+ }
+}
+
+void VarInfo::DumpLocsIfNeeded(MCObjectStreamer *Streamer,
+ MCSection *LocSection,
+ const MCExpr *SymExpr) {
+ if (!IsDebugLocNeeded())
+ return;
+
+ Streamer->SwitchSection(LocSection);
+
+ MCContext &context = Streamer->getContext();
+ unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize();
+
+ LocSymbol = context.createTempSymbol();
+ Streamer->EmitLabel(LocSymbol);
+
+ for (const auto &NativeInfo : DebugInfo.Ranges) {
+ const MCExpr *StartOffsetExpr = MCConstantExpr::create(NativeInfo.startOffset, context);
+ const MCExpr *EndOffsetExpr = MCConstantExpr::create(NativeInfo.endOffset, context);
+
+ // Begin address
+ const MCExpr *BeginAddrExpr = MCBinaryExpr::create(MCBinaryExpr::Add, SymExpr,
+ StartOffsetExpr, context);
+ Streamer->EmitValue(BeginAddrExpr, TargetPointerSize);
+
+ // End address
+ const MCExpr *EndAddrExpr = MCBinaryExpr::create(MCBinaryExpr::Add, SymExpr,
+ EndOffsetExpr, context);
+ Streamer->EmitValue(EndAddrExpr, TargetPointerSize);
+
+ // Expression
+ EmitVarLocation(Streamer, NativeInfo, true);
+ }
+
+ // Terminate list entry
+ Streamer->EmitIntValue(0, TargetPointerSize);
+ Streamer->EmitIntValue(0, TargetPointerSize);
+}
+
+void VarInfo::DumpStrings(MCObjectStreamer *Streamer) {
+ if (IsThis) {
+ Streamer->EmitBytes(StringRef("this"));
+ } else {
+ Streamer->EmitBytes(StringRef(DebugInfo.Name));
+ }
+ Streamer->EmitIntValue(0, 1);
+}
+
+void VarInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ bool IsDebugLocUsed = IsDebugLocNeeded();
+
+ // Abbrev Number
+ if (DebugInfo.IsParam) {
+ if (IsThis) {
+ Streamer->EmitULEB128IntValue(IsDebugLocUsed ? DwarfAbbrev::FormalParameterThisLoc :
+ DwarfAbbrev::FormalParameterThis);
+ } else {
+ Streamer->EmitULEB128IntValue(IsDebugLocUsed ? DwarfAbbrev::FormalParameterLoc :
+ DwarfAbbrev::FormalParameter);
+ }
+ } else {
+ Streamer->EmitULEB128IntValue(IsDebugLocUsed ? DwarfAbbrev::VariableLoc :
+ DwarfAbbrev::Variable);
+ }
+
+ // DW_AT_name
+ EmitSectionOffset(Streamer, StrSymbol, 4);
+
+ // DW_AT_decl_file
+ Streamer->EmitIntValue(1, 1);
+
+ // DW_AT_decl_line
+ Streamer->EmitIntValue(1, 1);
+
+ // DW_AT_type
+ DwarfInfo *Info = TypeBuilder->GetTypeInfoByIndex(DebugInfo.TypeIndex);
+ assert(Info != nullptr);
+
+ EmitInfoOffset(Streamer, Info, 4);
+
+ // DW_AT_location
+ if (IsDebugLocUsed) {
+ EmitSectionOffset(Streamer, LocSymbol, 4);
+ } else {
+ assert(DebugInfo.Ranges.size() == 1);
+ EmitVarLocation(Streamer, DebugInfo.Ranges[0]);
+ }
+}
+
+// SubprogramInfo
+
+SubprogramInfo::SubprogramInfo(const char *Name,
+ int Size,
+ DwarfMemberFunctionIdTypeInfo *MethodTypeInfo,
+ const std::vector<DebugVarInfo> &DebugVarInfos,
+ const std::vector<DebugEHClauseInfo> &DebugEHClauseInfos) :
+ Name(Name),
+ Size(Size),
+ MethodTypeInfo(MethodTypeInfo),
+ DebugEHClauseInfos(DebugEHClauseInfos) {
+ bool IsStatic = MethodTypeInfo->IsStatic();
+ for (unsigned i = 0; i < DebugVarInfos.size(); i++) {
+ VarInfos.emplace_back(DebugVarInfos[i], i == 0 && !IsStatic);
+ }
+}
+
+void SubprogramInfo::Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection, MCSection *LocSection) {
+ DumpDebugLoc(Streamer, LocSection);
+
+ DwarfInfo::Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ // Dump vars
+ DumpVars(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ // Dump try-catch blocks
+ Streamer->SwitchSection(TypeSection);
+ DumpEHClauses(Streamer, TypeSection);
+
+ // Terminate subprogram DIE
+ Streamer->EmitIntValue(0, 1);
+}
+
+void SubprogramInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ MCContext &context = Streamer->getContext();
+ bool IsStatic = MethodTypeInfo->IsStatic();
+ unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize();
+ Triple::ArchType ArchType = context.getObjectFileInfo()->getTargetTriple().getArch();
+
+ // Subprogram DIE
+
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(IsStatic ? DwarfAbbrev::SubprogramStatic :
+ DwarfAbbrev::Subprogram);
+
+ // DW_AT_specification
+ EmitInfoOffset(Streamer, MethodTypeInfo, 4);
+
+ // DW_AT_low_pc
+ MCSymbol *Sym = context.getOrCreateSymbol(Twine(Name));
+ const MCExpr *SymExpr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, context);
+ Streamer->EmitValue(SymExpr, TargetPointerSize);
+
+ // DW_AT_high_pc
+ Streamer->EmitIntValue(Size, TargetPointerSize);
+
+ // DW_AT_frame_base
+ Streamer->EmitULEB128IntValue(1);
+ Streamer->EmitIntValue(GetDwarfFpRegNum(ArchType) + dwarf::DW_OP_reg0, 1);
+
+ if (!IsStatic) {
+ // DW_AT_object_pointer
+ uint32_t Offset = Streamer->getOrCreateDataFragment()->getContents().size();
+
+ Streamer->EmitIntValue(Offset + 4, 4);
+ }
+}
+
+void SubprogramInfo::DumpDebugLoc(MCObjectStreamer *Streamer, MCSection *LocSection) {
+ MCContext &context = Streamer->getContext();
+ MCSymbol *Sym = context.getOrCreateSymbol(Twine(Name));
+ const MCExpr *SymExpr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, context);
+
+ for (auto &VarInfo : VarInfos) {
+ VarInfo.DumpLocsIfNeeded(Streamer, LocSection, SymExpr);
+ }
+}
+
+void SubprogramInfo::DumpVars(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ MCContext &context = Streamer->getContext();
+ MCSymbol *Sym = context.getOrCreateSymbol(Twine(Name));
+ const MCExpr *SymExpr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, context);
+
+ LexicalScope FuncScope(0, Size, true);
+
+ for (unsigned i = 0; i < VarInfos.size(); i++) {
+ FuncScope.AddVar(&VarInfos[i]);
+ }
+
+ FuncScope.Dump(TypeBuilder, Streamer, TypeSection, StrSection, SymExpr);
+}
+
+static void DumpEHClause(MCObjectStreamer *Streamer, MCSection *TypeSection, int Abbrev,
+ const MCExpr *SymExpr, unsigned Offset, unsigned Length) {
+ MCContext &context = Streamer->getContext();
+ unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize();
+
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(Abbrev);
+
+ // DW_AT_low_pc
+ const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, context);
+ const MCExpr *AddrExpr = MCBinaryExpr::create(MCBinaryExpr::Add, SymExpr,
+ OffsetExpr, context);
+
+ Streamer->EmitValue(AddrExpr, TargetPointerSize);
+
+ // DW_AT_high_pc
+ Streamer->EmitIntValue(Length, TargetPointerSize);
+}
+
+void SubprogramInfo::DumpEHClauses(MCObjectStreamer *Streamer, MCSection *TypeSection) {
+ MCContext &context = Streamer->getContext();
+
+ MCSymbol *Sym = context.getOrCreateSymbol(Twine(Name));
+ const MCExpr *SymExpr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, context);
+
+ for (const auto &EHClause: DebugEHClauseInfos) {
+ // Try block DIE
+ DumpEHClause(Streamer, TypeSection, DwarfAbbrev::TryBlock,
+ SymExpr, EHClause.TryOffset, EHClause.TryLength);
+
+ // Catch block DIE
+ DumpEHClause(Streamer, TypeSection, DwarfAbbrev::CatchBlock,
+ SymExpr, EHClause.HandlerOffset, EHClause.HandlerLength);
+ }
+}
+
+// DwarfGen
+
+void DwarfGen::SetTypeBuilder(UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ assert(this->TypeBuilder == nullptr);
+ assert(TypeBuilder != nullptr);
+ this->TypeBuilder = TypeBuilder;
+ this->Streamer = TypeBuilder->GetStreamer();
+}
+
+void DwarfGen::EmitCompileUnit() {
+ MCContext &context = Streamer->getContext();
+
+ MCSymbol *LineSectionSymbol = nullptr;
+ MCSymbol *AbbrevSectionSymbol = nullptr;
+ if (context.getAsmInfo()->doesDwarfUseRelocationsAcrossSections()) {
+ LineSectionSymbol = Streamer->getDwarfLineTableSymbol(0);
+
+ Streamer->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
+ AbbrevSectionSymbol = context.createTempSymbol();
+ Streamer->EmitLabel(AbbrevSectionSymbol);
+ }
+
+ MCSection *debugSection = context.getObjectFileInfo()->getDwarfInfoSection();
+ Streamer->SwitchSection(debugSection);
+
+ InfoStart = debugSection->getBeginSymbol();
+ InfoEnd = context.createTempSymbol();
+
+ // Length
+ const MCExpr *Length = MakeStartMinusEndExpr(*Streamer, *InfoStart, *InfoEnd, 4);
+ emitAbsValue(*Streamer, Length, 4);
+
+ // Version
+ Streamer->EmitIntValue(context.getDwarfVersion(), 2);
+
+ // Unit type, Addr Size and Abbrev offset - DWARF >= 5
+ // Abbrev offset, Addr Size - DWARF <= 4
+ unsigned addrSize = context.getAsmInfo()->getCodePointerSize();
+ if (context.getDwarfVersion() >= 5) {
+ Streamer->EmitIntValue(dwarf::DW_UT_compile, 1);
+ Streamer->EmitIntValue(addrSize, 1);
+ }
+
+ // Abbrev Offset
+ if (AbbrevSectionSymbol == nullptr) {
+ Streamer->EmitIntValue(0, 4);
+ } else {
+ Streamer->EmitSymbolValue(AbbrevSectionSymbol, 4,
+ context.getAsmInfo()->needsDwarfSectionOffsetDirective());
+ }
+
+ if (context.getDwarfVersion() <= 4)
+ Streamer->EmitIntValue(addrSize, 1);
+
+ // CompileUnit DIE
+
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::CompileUnit);
+
+ // DW_AT_producer: CoreRT
+ Streamer->EmitBytes(StringRef("CoreRT"));
+ Streamer->EmitIntValue(0, 1);
+
+ // DW_AT_language
+#ifdef FEATURE_LANGID_CS
+ Streamer->EmitIntValue(DW_LANG_MICROSOFT_CSHARP, 2);
+#else
+ Streamer->EmitIntValue(dwarf::DW_LANG_C_plus_plus, 2);
+#endif
+
+ // DW_AT_stmt_list
+ if (LineSectionSymbol == nullptr) {
+ Streamer->EmitIntValue(0, 4);
+ } else {
+ Streamer->EmitSymbolValue(LineSectionSymbol, 4,
+ context.getAsmInfo()->needsDwarfSectionOffsetDirective());
+ }
+}
+
+void DwarfGen::EmitSubprogramInfo(const char *FunctionName,
+ int FunctionSize,
+ unsigned MethodTypeIndex,
+ const std::vector<DebugVarInfo> &VarInfos,
+ const std::vector<DebugEHClauseInfo> &DebugEHClauseInfos) {
+ // return if CU isn't emitted
+ if (InfoStart == nullptr)
+ return;
+
+ if (MethodTypeIndex == 0)
+ return;
+
+ DwarfMemberFunctionIdTypeInfo *MethodTypeInfo = static_cast<DwarfMemberFunctionIdTypeInfo*>(
+ TypeBuilder->GetTypeInfoByIndex(MethodTypeIndex));
+ assert(MethodTypeInfo != nullptr);
+
+ MethodTypeInfo->SetLinkageName(FunctionName);
+
+ Subprograms.emplace_back(FunctionName, FunctionSize, MethodTypeInfo, VarInfos, DebugEHClauseInfos);
+}
+
+void DwarfGen::EmitAbbrev() {
+ // return if CU isn't emitted
+ if (InfoStart == nullptr)
+ return;
+
+ MCContext &context = Streamer->getContext();
+
+ DwarfAbbrev::Dump(Streamer, context.getDwarfVersion(),
+ context.getAsmInfo()->getCodePointerSize());
+}
+
+void DwarfGen::EmitAranges() {
+ // return if CU isn't emitted
+ if (InfoStart == nullptr)
+ return;
+
+ MCContext &context = Streamer->getContext();
+ Streamer->SwitchSection(context.getObjectFileInfo()->getDwarfARangesSection());
+
+ auto &Sections = context.getGenDwarfSectionSyms();
+
+ int Length = 4 + 2 + 4 + 1 + 1;
+ int AddrSize = context.getAsmInfo()->getCodePointerSize();
+ int Pad = 2 * AddrSize - (Length & (2 * AddrSize - 1));
+ if (Pad == 2 * AddrSize)
+ Pad = 0;
+ Length += Pad;
+
+ Length += 2 * AddrSize * Sections.size();
+ Length += 2 * AddrSize;
+
+ // Emit the header for this section.
+ // The 4 byte length not including the 4 byte value for the length.
+ Streamer->EmitIntValue(Length - 4, 4);
+
+ // The 2 byte version, which is 2.
+ Streamer->EmitIntValue(2, 2);
+
+ // The 4 byte offset to the compile unit in the .debug_info from the start
+ // of the .debug_info.
+ Streamer->EmitSymbolValue(InfoStart, 4,
+ context.getAsmInfo()->needsDwarfSectionOffsetDirective());
+
+ Streamer->EmitIntValue(AddrSize, 1);
+
+ Streamer->EmitIntValue(0, 1);
+
+ for(int i = 0; i < Pad; i++)
+ Streamer->EmitIntValue(0, 1);
+
+ for (MCSection *Sec : Sections) {
+ const MCSymbol *StartSymbol = Sec->getBeginSymbol();
+ MCSymbol *EndSymbol = Sec->getEndSymbol(context);
+ assert(StartSymbol && "StartSymbol must not be NULL");
+ assert(EndSymbol && "EndSymbol must not be NULL");
+
+ const MCExpr *Addr = MCSymbolRefExpr::create(
+ StartSymbol, MCSymbolRefExpr::VK_None, context);
+ const MCExpr *Size = MakeStartMinusEndExpr(*Streamer,
+ *StartSymbol, *EndSymbol, 0);
+ Streamer->EmitValue(Addr, AddrSize);
+ emitAbsValue(*Streamer, Size, AddrSize);
+ }
+
+ // Terminating zeros.
+ Streamer->EmitIntValue(0, AddrSize);
+ Streamer->EmitIntValue(0, AddrSize);
+}
+
+void DwarfGen::Finish() {
+ // return if CU isn't emitted
+ if (InfoStart == nullptr)
+ return;
+
+ MCContext &context = Streamer->getContext();
+
+ // Dump type info
+
+ MCSection *InfoSection = context.getObjectFileInfo()->getDwarfInfoSection();
+ MCSection *StrSection = context.getObjectFileInfo()->getDwarfStrSection();
+ MCSection *LocSection = context.getObjectFileInfo()->getDwarfLocSection();
+
+ TypeBuilder->EmitTypeInformation(InfoSection, StrSection);
+
+ // Dump subprograms
+
+ for (auto &Subprogram : Subprograms) {
+ Subprogram.Dump(TypeBuilder, Streamer, InfoSection, StrSection, LocSection);
+ }
+
+ // Dump static vars
+
+ for (const auto *ClassTypeInfo : TypeBuilder->GetClassesWithStaticFields()) {
+ for (const auto &StaticField : ClassTypeInfo->GetStaticFields()) {
+ StaticVarInfo Info(&StaticField);
+ Info.Dump(TypeBuilder, Streamer, InfoSection, StrSection);
+ }
+ }
+
+ // Add the NULL terminating the Compile Unit DIE's.
+ Streamer->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection());
+
+ Streamer->EmitIntValue(0, 1);
+
+ Streamer->EmitLabel(InfoEnd);
+
+ Streamer->SwitchSection(context.getObjectFileInfo()->getDwarfAbbrevSection());
+
+ // Terminate the abbreviations for this compilation unit
+ Streamer->EmitIntValue(0, 1);
+} \ No newline at end of file
diff --git a/src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.h b/src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.h
new file mode 100644
index 000000000..2fd78a5c6
--- /dev/null
+++ b/src/Native/ObjWriter/debugInfo/dwarf/dwarfGen.h
@@ -0,0 +1,106 @@
+//===---- dwarfGen.h --------------------------------------------*- C++ -*-===//
+//
+// dwarf generator is used to generate dwarf debuginfo.
+//
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include "llvm/MC/MCObjectStreamer.h"
+
+#include "dwarfTypeBuilder.h"
+#include "jitDebugInfo.h"
+
+#include <vector>
+
+class VarInfo : public DwarfInfo
+{
+public:
+ VarInfo(const DebugVarInfo &Info, bool IsThis);
+
+ bool IsDebugLocNeeded() const { return DebugInfo.Ranges.size() > 1; }
+
+ void DumpLocsIfNeeded(MCObjectStreamer *Streamer, MCSection *LocSection, const MCExpr *SymExpr);
+
+ uint64_t GetStartOffset() const { return StartOffset; }
+
+ uint64_t GetEndOffset() const { return EndOffset; }
+
+ bool IsParam() const { return DebugInfo.IsParam; }
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override;
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ DebugVarInfo DebugInfo;
+ MCSymbol *LocSymbol;
+ bool IsThis;
+ uint64_t StartOffset;
+ uint64_t EndOffset;
+};
+
+class SubprogramInfo : public DwarfInfo
+{
+public:
+ using DwarfInfo::Dump;
+
+ SubprogramInfo(const char *Name,
+ int Size,
+ DwarfMemberFunctionIdTypeInfo *MethodTypeInfo,
+ const std::vector<DebugVarInfo> &DebugVarInfos,
+ const std::vector<DebugEHClauseInfo> &DebugEHClauseInfos);
+
+ void Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection, MCSection *LocSection);
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override {}
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ void DumpDebugLoc(MCObjectStreamer *Streamer, MCSection *LocSection);
+ void DumpVars(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection);
+ void DumpEHClauses(MCObjectStreamer *Streamer, MCSection *TypeSection);
+
+ std::string Name;
+ int Size;
+ DwarfMemberFunctionIdTypeInfo *MethodTypeInfo;
+ std::vector<DebugEHClauseInfo> DebugEHClauseInfos;
+ std::vector<VarInfo> VarInfos;
+};
+
+class DwarfGen
+{
+public:
+ DwarfGen() : Streamer(nullptr),
+ TypeBuilder(nullptr),
+ InfoStart(nullptr),
+ InfoEnd(nullptr) {}
+
+ void SetTypeBuilder(UserDefinedDwarfTypesBuilder *TypeBuilder);
+ void EmitCompileUnit();
+ void EmitSubprogramInfo(const char *FunctionName,
+ int FunctionSize,
+ unsigned MethodTypeIndex,
+ const std::vector<DebugVarInfo> &VarsInfo,
+ const std::vector<DebugEHClauseInfo> &DebugEHClauseInfos);
+
+ void EmitAbbrev();
+ void EmitAranges();
+ void Finish();
+
+private:
+ MCObjectStreamer *Streamer;
+ UserDefinedDwarfTypesBuilder *TypeBuilder;
+
+ MCSymbol *InfoStart;
+ MCSymbol *InfoEnd;
+
+ std::vector<SubprogramInfo> Subprograms;
+}; \ No newline at end of file
diff --git a/src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.cpp b/src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.cpp
new file mode 100644
index 000000000..da5448bf1
--- /dev/null
+++ b/src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.cpp
@@ -0,0 +1,780 @@
+//===---- dwarfTypeBuilder.cpp ----------------------------------*- C++ -*-===//
+//
+// dwarf type builder implementation
+//
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "dwarfTypeBuilder.h"
+#include "dwarfAbbrev.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+
+#include <sstream>
+#include <vector>
+
+// DwarfInfo
+
+void DwarfInfo::Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ if (IsDumped)
+ return;
+
+ IsDumped = true;
+
+ MCContext &context = Streamer->getContext();
+
+ InfoSymbol = context.createTempSymbol();
+ InfoExpr = CreateOffsetExpr(context, TypeSection->getBeginSymbol(), InfoSymbol);
+
+ DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ Streamer->SwitchSection(StrSection);
+ StrSymbol = context.createTempSymbol();
+ Streamer->EmitLabel(StrSymbol);
+ DumpStrings(Streamer);
+
+ Streamer->SwitchSection(TypeSection);
+ Streamer->EmitLabel(InfoSymbol);
+ DumpTypeInfo(Streamer, TypeBuilder);
+}
+
+void DwarfInfo::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ if (IsDumpedTypes)
+ return;
+
+ IsDumpedTypes = true;
+}
+
+void DwarfInfo::EmitSectionOffset(MCObjectStreamer *Streamer,
+ MCSymbol *Symbol,
+ unsigned Size,
+ uint32_t Offset) {
+ MCContext &context = Streamer->getContext();
+
+ if (context.getAsmInfo()->doesDwarfUseRelocationsAcrossSections()) {
+ if (Offset == 0) {
+ Streamer->EmitSymbolValue(Symbol, Size);
+ } else {
+ const MCSymbolRefExpr *SymbolExpr = MCSymbolRefExpr::create(Symbol,
+ MCSymbolRefExpr::VK_None, context);
+ const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, context);
+ const MCExpr *Expr = MCBinaryExpr::createAdd(SymbolExpr, OffsetExpr, context);
+ Streamer->EmitValue(Expr, Size);
+ }
+ } else {
+ Streamer->EmitIntValue(Symbol->getOffset() + Offset, Size);
+ }
+}
+
+const MCExpr *DwarfInfo::CreateOffsetExpr(MCContext &Context,
+ MCSymbol *BeginSymbol,
+ MCSymbol *Symbol) {
+ MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
+ const MCExpr *StartExpr =
+ MCSymbolRefExpr::create(BeginSymbol, Variant, Context);
+ const MCExpr *EndExpr =
+ MCSymbolRefExpr::create(Symbol, Variant, Context);
+ return MCBinaryExpr::createSub(EndExpr, StartExpr, Context);
+}
+
+void DwarfInfo::EmitOffset(MCObjectStreamer *Streamer,
+ const MCExpr *OffsetExpr,
+ unsigned Size) {
+ MCContext &context = Streamer->getContext();
+
+ if (!context.getAsmInfo()->hasAggressiveSymbolFolding()) {
+ MCSymbol *Temp = context.createTempSymbol();
+ Streamer->EmitAssignment(Temp, OffsetExpr);
+ OffsetExpr = MCSymbolRefExpr::create(Temp, context);
+ }
+
+ Streamer->EmitValue(OffsetExpr, Size);
+}
+
+void DwarfInfo::EmitInfoOffset(MCObjectStreamer *Streamer, const DwarfInfo *Info, unsigned Size) {
+ uint64_t Offset = Info->InfoSymbol->getOffset();
+ if (Offset != 0) {
+ Streamer->EmitIntValue(Offset, Size);
+ } else {
+ EmitOffset(Streamer, Info->InfoExpr, Size);
+ }
+}
+
+// DwarfPrimitiveTypeInfo
+
+struct PrimitiveTypeDesc {
+ const char *Name;
+ int Encoding;
+ unsigned ByteSize;
+};
+
+static PrimitiveTypeDesc GetPrimitiveTypeDesc(PrimitiveTypeFlags Type, unsigned TargetPointerSize) {
+ switch (Type) {
+ case PrimitiveTypeFlags::Void: return {"void", dwarf::DW_ATE_address, 0};
+ case PrimitiveTypeFlags::Boolean: return {"bool", dwarf::DW_ATE_boolean, 1};
+ case PrimitiveTypeFlags::Char: return {"char16_t", dwarf::DW_ATE_UTF, 2};
+ case PrimitiveTypeFlags::SByte: return {"sbyte", dwarf::DW_ATE_signed, 1};
+ case PrimitiveTypeFlags::Byte: return {"byte", dwarf::DW_ATE_unsigned, 1};
+ case PrimitiveTypeFlags::Int16: return {"short", dwarf::DW_ATE_signed, 2};
+ case PrimitiveTypeFlags::UInt16: return {"ushort", dwarf::DW_ATE_unsigned, 2};
+ case PrimitiveTypeFlags::Int32: return {"int", dwarf::DW_ATE_signed, 4};
+ case PrimitiveTypeFlags::UInt32: return {"uint", dwarf::DW_ATE_unsigned, 4};
+ case PrimitiveTypeFlags::Int64: return {"long", dwarf::DW_ATE_signed, 8};
+ case PrimitiveTypeFlags::UInt64: return {"ulong", dwarf::DW_ATE_unsigned, 8};
+ case PrimitiveTypeFlags::IntPtr: return {"System.IntPtr", dwarf::DW_ATE_signed, TargetPointerSize};
+ case PrimitiveTypeFlags::UIntPtr: return {"System.UIntPtr", dwarf::DW_ATE_unsigned, TargetPointerSize};
+ case PrimitiveTypeFlags::Single: return {"float", dwarf::DW_ATE_float, 4};
+ case PrimitiveTypeFlags::Double: return {"double", dwarf::DW_ATE_float, 8};
+ default:
+ assert(false && "Unexpected type");
+ return {nullptr, 0, 0};
+ }
+}
+
+void DwarfPrimitiveTypeInfo::DumpStrings(MCObjectStreamer *Streamer) {
+ MCContext &context = Streamer->getContext();
+ unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize();
+
+ PrimitiveTypeDesc TD = GetPrimitiveTypeDesc(Type, TargetPointerSize);
+ if (TD.Name == nullptr)
+ return;
+
+ Streamer->EmitBytes(StringRef(TD.Name));
+ Streamer->EmitIntValue(0, 1);
+}
+
+void DwarfPrimitiveTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ MCContext &context = Streamer->getContext();
+ unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize();
+
+ PrimitiveTypeDesc TD = GetPrimitiveTypeDesc(Type, TargetPointerSize);
+ if (TD.Name == nullptr)
+ return;
+
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::BaseType);
+
+ // DW_AT_name
+ EmitSectionOffset(Streamer, StrSymbol, 4);
+
+ // DW_AT_encoding
+ Streamer->EmitIntValue(TD.Encoding, 1);
+
+ // DW_AT_byte_size
+ Streamer->EmitIntValue(TD.ByteSize, 1);
+}
+
+// DwarfEnumerator
+
+void DwarfEnumerator::DumpStrings(MCObjectStreamer *Streamer) {
+ Streamer->EmitBytes(Name);
+ Streamer->EmitIntValue(0, 1);
+}
+
+void DwarfEnumerator::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ uint8_t Size = EnumTypeInfo->GetByteSize();
+
+ // Abbrev Number
+ switch (Size) {
+ case 1:
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::Enumerator1);
+ break;
+ case 2:
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::Enumerator2);
+ break;
+ case 4:
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::Enumerator4);
+ break;
+ case 8:
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::Enumerator8);
+ break;
+ default:
+ assert(false && "Unexpected byte size value");
+ }
+
+ // DW_AT_name
+ EmitSectionOffset(Streamer, StrSymbol, 4);
+
+ // DW_AT_const_value
+ Streamer->EmitIntValue(Value, Size);
+}
+
+// DwarfEnumTypeInfo
+
+DwarfEnumTypeInfo::DwarfEnumTypeInfo(const EnumTypeDescriptor &TypeDescriptor,
+ const EnumRecordTypeDescriptor *TypeRecords) :
+ Name(TypeDescriptor.Name),
+ ElementType(TypeDescriptor.ElementType) {
+ for (uint64 i = 0; i < TypeDescriptor.ElementCount; i++) {
+ Records.emplace_back(TypeRecords[i], this);
+ }
+}
+
+void DwarfEnumTypeInfo::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ if (IsDumpedTypes)
+ return;
+
+ DwarfInfo::DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ DwarfInfo *Info = TypeBuilder->GetTypeInfoByIndex(ElementType);
+ assert(Info != nullptr);
+
+ Info->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+}
+
+void DwarfEnumTypeInfo::Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ if (IsDumped)
+ return;
+
+ MCContext &context = Streamer->getContext();
+ unsigned TargetPointerSize = context.getAsmInfo()->getCodePointerSize();
+
+ DwarfPrimitiveTypeInfo *ElementTypeInfo = static_cast<DwarfPrimitiveTypeInfo*>(
+ TypeBuilder->GetTypeInfoByIndex(ElementType));
+ assert(ElementTypeInfo != nullptr);
+
+ PrimitiveTypeDesc TD = GetPrimitiveTypeDesc(ElementTypeInfo->GetType(), TargetPointerSize);
+ ByteSize = TD.ByteSize;
+
+ DwarfInfo::Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ for (auto &Enumerator : Records) {
+ Enumerator.Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+
+ // Terminate DIE
+ Streamer->SwitchSection(TypeSection);
+ Streamer->EmitIntValue(0, 1);
+}
+
+void DwarfEnumTypeInfo::DumpStrings(MCObjectStreamer *Streamer) {
+ Streamer->EmitBytes(Name);
+ Streamer->EmitIntValue(0, 1);
+}
+
+void DwarfEnumTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::EnumerationType);
+
+ // DW_AT_name
+ EmitSectionOffset(Streamer, StrSymbol, 4);
+
+ // DW_AT_type
+ DwarfInfo *Info = TypeBuilder->GetTypeInfoByIndex(ElementType);
+ assert(Info != nullptr);
+
+ EmitInfoOffset(Streamer, Info, 4);
+
+ // DW_AT_byte_size
+ Streamer->EmitIntValue(ByteSize, 1);
+}
+
+// DwarfDataField
+
+void DwarfDataField::DumpStrings(MCObjectStreamer *Streamer) {
+ Streamer->EmitBytes(StringRef(Name));
+ Streamer->EmitIntValue(0, 1);
+}
+
+void DwarfDataField::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ if (IsDumpedTypes)
+ return;
+
+ DwarfInfo::DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ DwarfInfo *MemberTypeInfo = TypeBuilder->GetTypeInfoByIndex(TypeIndex);
+ assert(MemberTypeInfo != nullptr);
+
+ MemberTypeInfo->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+}
+
+void DwarfDataField::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::ClassMember);
+
+ // DW_AT_name
+ EmitSectionOffset(Streamer, StrSymbol, 4);
+
+ // DW_AT_type
+ DwarfInfo *MemberTypeInfo = TypeBuilder->GetTypeInfoByIndex(TypeIndex);
+ assert(MemberTypeInfo != nullptr);
+ EmitInfoOffset(Streamer, MemberTypeInfo, 4);
+
+ // DW_AT_data_member_location
+ Streamer->EmitIntValue(Offset, 4);
+}
+
+// DwarfStaticDataField
+
+void DwarfStaticDataField::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::ClassMemberStatic);
+
+ // DW_AT_name
+ EmitSectionOffset(Streamer, StrSymbol, 4);
+
+ // DW_AT_type
+ DwarfInfo *MemberTypeInfo = TypeBuilder->GetTypeInfoByIndex(TypeIndex);
+ assert(MemberTypeInfo != nullptr);
+ EmitInfoOffset(Streamer, MemberTypeInfo, 4);
+}
+
+// DwarfClassTypeInfo
+
+DwarfClassTypeInfo::DwarfClassTypeInfo(const ClassTypeDescriptor &ClassDescriptor,
+ const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
+ const DataFieldDescriptor *FieldsDescriptors,
+ const StaticDataFieldDescriptor *StaticsDescriptors) :
+ Name(ClassDescriptor.Name),
+ IsStruct(ClassDescriptor.IsStruct),
+ BaseClassId(ClassDescriptor.BaseClassId),
+ Size(ClassDescriptor.InstanceSize),
+ IsForwardDecl(false) {
+ int32_t staticIdx = 0;
+ for (int32_t i = 0; i < ClassFieldsDescriptor.FieldsCount; i++) {
+ if (FieldsDescriptors[i].Offset == 0xFFFFFFFF) {
+ StaticFields.emplace_back(FieldsDescriptors[i], StaticsDescriptors[staticIdx++]);
+ } else {
+ Fields.emplace_back(FieldsDescriptors[i]);
+ }
+ }
+}
+
+void DwarfClassTypeInfo::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ if (IsDumpedTypes)
+ return;
+
+ DwarfInfo::DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ if (BaseClassId != 0) {
+ DwarfInfo *BaseClassInfo = TypeBuilder->GetTypeInfoByIndex(BaseClassId);
+ assert(BaseClassInfo != nullptr);
+
+ BaseClassInfo->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+
+ for (auto &Field : Fields) {
+ Field.DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+
+ for (auto &StaticField : StaticFields) {
+ StaticField.DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+
+ for (auto *Function : MemberFunctions) {
+ Function->DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+}
+
+void DwarfClassTypeInfo::Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ if (IsDumped)
+ return;
+
+ DwarfInfo::Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ if (IsForwardDecl)
+ return;
+
+ for (auto &Field : Fields) {
+ Field.Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+
+ for (auto &StaticField : StaticFields) {
+ StaticField.Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+
+ for (auto *Function : MemberFunctions) {
+ Function->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+
+ // Terminate DIE
+ Streamer->SwitchSection(TypeSection);
+ Streamer->EmitIntValue(0, 1);
+}
+
+void DwarfClassTypeInfo::DumpStrings(MCObjectStreamer *Streamer) {
+ Streamer->EmitBytes(StringRef(Name));
+ Streamer->EmitIntValue(0, 1);
+}
+
+void DwarfClassTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(IsForwardDecl ? DwarfAbbrev::ClassTypeDecl : DwarfAbbrev::ClassType);
+
+ // DW_AT_name
+ EmitSectionOffset(Streamer, StrSymbol, 4);
+
+ if (!IsForwardDecl) {
+ // DW_AT_byte_size
+ Streamer->EmitIntValue(Size, 4);
+ }
+
+ if (BaseClassId != 0) {
+ DwarfInfo *BaseClassInfo = TypeBuilder->GetTypeInfoByIndex(BaseClassId);
+ assert(BaseClassInfo != nullptr);
+
+ // DW_TAG_inheritance DIE
+
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::ClassInheritance);
+
+ // DW_AT_type
+ EmitInfoOffset(Streamer, BaseClassInfo, 4);
+
+ // DW_AT_data_member_location = 0
+ Streamer->EmitIntValue(0, 1);
+ }
+}
+
+// DwarfSimpleArrayTypeInfo
+
+void DwarfSimpleArrayTypeInfo::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ if (IsDumpedTypes)
+ return;
+
+ DwarfInfo::DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ DwarfInfo *ElementInfo = TypeBuilder->GetTypeInfoByIndex(ElementType);
+ assert(ElementInfo != nullptr);
+
+ ElementInfo->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+}
+
+void DwarfSimpleArrayTypeInfo::DumpStrings(MCObjectStreamer *Streamer) {
+ // nothing to dump
+}
+
+void DwarfSimpleArrayTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::ArrayType);
+
+ DwarfInfo *Info = TypeBuilder->GetTypeInfoByIndex(ElementType);
+ assert(Info != nullptr);
+
+ // DW_AT_type
+ EmitInfoOffset(Streamer, Info, 4);
+
+ // DW_TAG_subrange_type DIE
+
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::SubrangeType);
+
+ // DW_AT_upper_bound
+ Streamer->EmitULEB128IntValue(Size - 1);
+
+ // Terminate DIE
+ Streamer->EmitIntValue(0, 1);
+}
+
+// DwarfPointerTypeInfo
+
+void DwarfPointerTypeInfo::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ if (IsDumpedTypes)
+ return;
+
+ DwarfInfo::DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ DwarfInfo *Info = TypeBuilder->GetTypeInfoByIndex(TypeDesc.ElementType);
+ assert(Info != nullptr);
+
+ Info->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+}
+
+void DwarfPointerTypeInfo::DumpStrings(MCObjectStreamer *Streamer) {
+ // nothing to dump
+}
+
+void DwarfPointerTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(TypeDesc.IsReference ? DwarfAbbrev::ReferenceType : DwarfAbbrev::PointerType);
+
+ DwarfInfo *Info = TypeBuilder->GetTypeInfoByIndex(TypeDesc.ElementType);
+ assert(Info != nullptr);
+
+ // DW_AT_type
+ EmitInfoOffset(Streamer, Info, 4);
+
+ // DW_AT_byte_size
+ Streamer->EmitIntValue(TypeDesc.Is64Bit ? 8 : 4, 1);
+}
+
+// DwarfMemberFunctionTypeInfo
+
+DwarfMemberFunctionTypeInfo::DwarfMemberFunctionTypeInfo(
+ const MemberFunctionTypeDescriptor& MemberDescriptor,
+ uint32_t const *const ArgumentTypes,
+ bool IsStaticMethod) :
+ TypeDesc(MemberDescriptor),
+ IsStaticMethod(IsStaticMethod) {
+ for (uint16_t i = 0; i < MemberDescriptor.NumberOfArguments; i++) {
+ this->ArgumentTypes.push_back(ArgumentTypes[i]);
+ }
+}
+
+void DwarfMemberFunctionTypeInfo::DumpStrings(MCObjectStreamer *Streamer) {
+ // nothing to dump
+}
+
+void DwarfMemberFunctionTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ // nothing to dump
+}
+
+// DwarfMemberFunctionIdTypeInfo
+
+void DwarfMemberFunctionIdTypeInfo::DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) {
+ if (IsDumpedTypes)
+ return;
+
+ DwarfInfo::DumpTypes(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ // Dump return type
+ DwarfInfo *ReturnTypeInfo = TypeBuilder->GetTypeInfoByIndex(MemberFunctionTypeInfo->GetReturnTypeIndex());
+ assert(ReturnTypeInfo != nullptr);
+
+ ReturnTypeInfo->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+
+ // Dump this pointer type
+ if (!MemberFunctionTypeInfo->IsStatic()) {
+ DwarfInfo *ThisPtrTypeInfo = TypeBuilder->GetTypeInfoByIndex(MemberFunctionTypeInfo->GetThisPtrTypeIndex());
+ assert(ThisPtrTypeInfo != nullptr);
+
+ ThisPtrTypeInfo->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+
+ // Dump argument types
+ for (uint32_t ArgTypeIndex : MemberFunctionTypeInfo->GetArgTypes()) {
+ DwarfInfo *ArgTypeInfo = TypeBuilder->GetTypeInfoByIndex(ArgTypeIndex);
+ assert(ArgTypeInfo != nullptr);
+ ArgTypeInfo->Dump(TypeBuilder, Streamer, TypeSection, StrSection);
+ }
+}
+
+void DwarfMemberFunctionIdTypeInfo::DumpStrings(MCObjectStreamer *Streamer) {
+ Streamer->EmitBytes(StringRef(Name));
+ Streamer->EmitIntValue(0, 1);
+
+ MCContext &context = Streamer->getContext();
+ LinkageNameSymbol = context.createTempSymbol();
+ Streamer->EmitLabel(LinkageNameSymbol);
+ Streamer->EmitBytes(StringRef(LinkageName));
+ Streamer->EmitIntValue(0, 1);
+}
+
+void DwarfMemberFunctionIdTypeInfo::DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) {
+ // Abbrev Number
+ bool IsStatic = MemberFunctionTypeInfo->IsStatic();
+
+ Streamer->EmitULEB128IntValue(IsStatic ? DwarfAbbrev::SubprogramStaticSpec : DwarfAbbrev::SubprogramSpec);
+
+ // DW_AT_name
+ EmitSectionOffset(Streamer, StrSymbol, 4);
+
+ // DW_AT_linkage_name
+ EmitSectionOffset(Streamer, LinkageNameSymbol, 4);
+
+ // DW_AT_decl_file
+ Streamer->EmitIntValue(1, 1);
+
+ // DW_AT_decl_line
+ Streamer->EmitIntValue(1, 1);
+
+ // DW_AT_type
+ DwarfInfo *ReturnTypeInfo = TypeBuilder->GetTypeInfoByIndex(MemberFunctionTypeInfo->GetReturnTypeIndex());
+ assert(ReturnTypeInfo != nullptr);
+
+ EmitInfoOffset(Streamer, ReturnTypeInfo, 4);
+
+ if (!IsStatic) {
+ // DW_AT_object_pointer
+ uint32_t Offset = Streamer->getOrCreateDataFragment()->getContents().size();
+
+ Streamer->EmitIntValue(Offset + 4, 4);
+
+ // This formal parameter DIE
+ DwarfInfo *ThisTypeInfo = TypeBuilder->GetTypeInfoByIndex(MemberFunctionTypeInfo->GetThisPtrTypeIndex());
+ assert(ThisTypeInfo != nullptr);
+
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::FormalParameterThisSpec);
+
+ // DW_AT_type
+ EmitInfoOffset(Streamer, ThisTypeInfo, 4);
+ }
+
+ for (uint32_t ArgTypeIndex : MemberFunctionTypeInfo->GetArgTypes()) {
+ DwarfInfo *ArgTypeInfo = TypeBuilder->GetTypeInfoByIndex(ArgTypeIndex);
+ assert(ArgTypeInfo != nullptr);
+
+ // Formal parameter DIE
+
+ // Abbrev Number
+ Streamer->EmitULEB128IntValue(DwarfAbbrev::FormalParameterSpec);
+
+ // DW_AT_type
+ EmitInfoOffset(Streamer, ArgTypeInfo, 4);
+ }
+
+ // Ternimate DIE
+ Streamer->EmitIntValue(0, 1);
+}
+
+// DwarfTypesBuilder
+
+void UserDefinedDwarfTypesBuilder::EmitTypeInformation(
+ MCSection *TypeSection,
+ MCSection *StrSection) {
+ for (auto &Info : DwarfTypes) {
+ Info->Dump(this, Streamer, TypeSection, StrSection);
+ }
+}
+
+unsigned UserDefinedDwarfTypesBuilder::GetEnumTypeIndex(
+ const EnumTypeDescriptor &TypeDescriptor,
+ const EnumRecordTypeDescriptor *TypeRecords) {
+ unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size());
+ UserDefinedTypes.push_back(std::make_pair(TypeDescriptor.Name, TypeIndex));
+ DwarfTypes.push_back(make_unique<DwarfEnumTypeInfo>(TypeDescriptor, TypeRecords));
+ return TypeIndex;
+}
+
+unsigned UserDefinedDwarfTypesBuilder::GetClassTypeIndex(
+ const ClassTypeDescriptor &ClassDescriptor) {
+ unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size());
+ DwarfTypes.push_back(make_unique<DwarfClassTypeInfo>(ClassDescriptor));
+ return TypeIndex;
+}
+
+unsigned UserDefinedDwarfTypesBuilder::GetCompleteClassTypeIndex(
+ const ClassTypeDescriptor &ClassDescriptor,
+ const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
+ const DataFieldDescriptor *FieldsDescriptors,
+ const StaticDataFieldDescriptor *StaticsDescriptors) {
+ unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size());
+ UserDefinedTypes.push_back(std::make_pair(ClassDescriptor.Name, TypeIndex));
+
+ DwarfClassTypeInfo *ClassTypeInfo = new DwarfClassTypeInfo(ClassDescriptor, ClassFieldsDescriptor,
+ FieldsDescriptors, StaticsDescriptors);
+
+ DwarfTypes.push_back(std::unique_ptr<DwarfClassTypeInfo>(ClassTypeInfo));
+
+ if (ClassTypeInfo->GetStaticFields().size() > 0) {
+ ClassesWithStaticFields.push_back(ClassTypeInfo);
+ }
+
+ return TypeIndex;
+}
+
+unsigned UserDefinedDwarfTypesBuilder::GetArrayTypeIndex(
+ const ClassTypeDescriptor &ClassDescriptor,
+ const ArrayTypeDescriptor &ArrayDescriptor) {
+ // Create corresponding class info
+ ClassTypeDescriptor ArrayClassDescriptor = ClassDescriptor;
+
+ std::vector<DataFieldDescriptor> FieldDescs;
+ unsigned FieldOffset = TargetPointerSize;
+
+ FieldDescs.push_back({GetPrimitiveTypeIndex(PrimitiveTypeFlags::Int32), FieldOffset, "m_NumComponents"});
+ FieldOffset += TargetPointerSize;
+
+ if (ArrayDescriptor.IsMultiDimensional == 1) {
+ unsigned BoundsTypeIndex = GetSimpleArrayTypeIndex(GetPrimitiveTypeIndex(PrimitiveTypeFlags::Int32), ArrayDescriptor.Rank);
+ FieldDescs.push_back({BoundsTypeIndex, FieldOffset, "m_Bounds"});
+ FieldOffset += 2 * 4 * ArrayDescriptor.Rank;
+ }
+
+ unsigned DataTypeIndex = GetSimpleArrayTypeIndex(ArrayDescriptor.ElementType, 0);
+ FieldDescs.push_back({DataTypeIndex, FieldOffset, "m_Data"});
+
+ ClassFieldsTypeDescriptior FieldsTypeDesc =
+ {TargetPointerSize, ArrayDescriptor.IsMultiDimensional ? 3 : 2};
+
+ ArrayClassDescriptor.InstanceSize = FieldOffset;
+
+ unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size());
+ UserDefinedTypes.push_back(std::make_pair(ArrayClassDescriptor.Name, TypeIndex));
+ DwarfTypes.push_back(make_unique<DwarfClassTypeInfo>(ArrayClassDescriptor, FieldsTypeDesc, FieldDescs.data(), nullptr));
+
+ return TypeIndex;
+}
+
+unsigned UserDefinedDwarfTypesBuilder::GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor)
+{
+ unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size());
+ DwarfTypes.push_back(make_unique<DwarfPointerTypeInfo>(PointerDescriptor));
+ return TypeIndex;
+}
+
+unsigned UserDefinedDwarfTypesBuilder::GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor,
+ uint32_t const *const ArgumentTypes)
+{
+ unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size());
+ bool IsStatic = MemberDescriptor.TypeIndexOfThisPointer == GetPrimitiveTypeIndex(PrimitiveTypeFlags::Void);
+ DwarfTypes.push_back(make_unique<DwarfMemberFunctionTypeInfo>(MemberDescriptor, ArgumentTypes, IsStatic));
+ return TypeIndex;
+}
+
+unsigned UserDefinedDwarfTypesBuilder::GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor)
+{
+ unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size());
+
+ DwarfMemberFunctionTypeInfo *MemberFunctionTypeInfo = static_cast<DwarfMemberFunctionTypeInfo*>(
+ GetTypeInfoByIndex(MemberIdDescriptor.MemberFunction));
+ assert(MemberFunctionTypeInfo != nullptr);
+
+ DwarfMemberFunctionIdTypeInfo *MemberFunctionIdTypeInfo =
+ new DwarfMemberFunctionIdTypeInfo(MemberIdDescriptor, MemberFunctionTypeInfo);
+
+ DwarfTypes.push_back(std::unique_ptr<DwarfMemberFunctionIdTypeInfo>(MemberFunctionIdTypeInfo));
+
+ DwarfClassTypeInfo *ParentClassInfo = static_cast<DwarfClassTypeInfo*>(
+ GetTypeInfoByIndex(MemberIdDescriptor.ParentClass));
+ assert(ParentClassInfo != nullptr);
+
+ ParentClassInfo->AddMemberFunction(MemberFunctionIdTypeInfo);
+
+ return TypeIndex;
+}
+
+unsigned UserDefinedDwarfTypesBuilder::GetPrimitiveTypeIndex(PrimitiveTypeFlags Type) {
+ auto Iter = PrimitiveDwarfTypes.find(Type);
+ if (Iter != PrimitiveDwarfTypes.end())
+ return Iter->second;
+
+ unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size());
+ DwarfTypes.push_back(make_unique<DwarfPrimitiveTypeInfo>(Type));
+
+ PrimitiveDwarfTypes.insert(std::make_pair(Type, TypeIndex));
+
+ return TypeIndex;
+}
+
+unsigned UserDefinedDwarfTypesBuilder::GetSimpleArrayTypeIndex(unsigned ElemIndex, unsigned Size) {
+ auto Iter = SimpleArrayDwarfTypes.find(ElemIndex);
+ if (Iter != SimpleArrayDwarfTypes.end()) {
+ auto CountMap = Iter->second;
+ auto CountIter = CountMap.find(Size);
+ if (CountIter != CountMap.end())
+ return CountIter->second;
+ }
+
+ unsigned TypeIndex = ArrayIndexToTypeIndex(DwarfTypes.size());
+ DwarfTypes.push_back(make_unique<DwarfSimpleArrayTypeInfo>(ElemIndex, Size));
+
+ SimpleArrayDwarfTypes[ElemIndex][Size] = TypeIndex;
+
+ return TypeIndex;
+} \ No newline at end of file
diff --git a/src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.h b/src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.h
new file mode 100644
index 000000000..0ea43a451
--- /dev/null
+++ b/src/Native/ObjWriter/debugInfo/dwarf/dwarfTypeBuilder.h
@@ -0,0 +1,366 @@
+//===---- dwarfTypeBuilder.h ------------------------------------*- C++ -*-===//
+//
+// type builder is used to convert .Net types into Dwarf debuginfo.
+//
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include "debugInfo/typeBuilder.h"
+
+#include <vector>
+#include <unordered_map>
+
+class UserDefinedDwarfTypesBuilder;
+
+class DwarfInfo
+{
+public:
+ DwarfInfo() :
+ StrSymbol(nullptr),
+ InfoSymbol(nullptr),
+ IsDumped(false),
+ IsDumpedTypes(false) {}
+
+ virtual ~DwarfInfo() {}
+
+ virtual void Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection);
+
+ virtual void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection);
+
+ MCSymbol *GetInfoSymbol() { return InfoSymbol; }
+
+ const MCExpr *GetInfoExpr() { return InfoExpr; }
+
+protected:
+ virtual void DumpStrings(MCObjectStreamer *Streamer) = 0;
+ virtual void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) = 0;
+
+ static void EmitSectionOffset(MCObjectStreamer *Streamer,
+ MCSymbol *Symbol,
+ unsigned Size,
+ uint32_t Offset = 0);
+
+ static const MCExpr *CreateOffsetExpr(MCContext &Context,
+ MCSymbol *BeginSymbol,
+ MCSymbol *Symbol);
+
+ static void EmitOffset(MCObjectStreamer *Streamer,
+ const MCExpr *OffsetExpr,
+ unsigned Size);
+
+ static void EmitInfoOffset(MCObjectStreamer *Streamer, const DwarfInfo *Info, unsigned Size);
+
+ MCSymbol *StrSymbol;
+ MCSymbol *InfoSymbol;
+ const MCExpr *InfoExpr;
+
+ bool IsDumped;
+ bool IsDumpedTypes;
+};
+
+class DwarfPrimitiveTypeInfo : public DwarfInfo
+{
+public:
+ DwarfPrimitiveTypeInfo(PrimitiveTypeFlags PrimitiveType) : Type(PrimitiveType) {}
+
+ PrimitiveTypeFlags GetType() { return Type; }
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override;
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ PrimitiveTypeFlags Type;
+};
+
+class DwarfEnumTypeInfo;
+
+class DwarfEnumerator : public DwarfInfo
+{
+public:
+ DwarfEnumerator(const EnumRecordTypeDescriptor &Descriptor, DwarfEnumTypeInfo *TypeInfo) :
+ Name(Descriptor.Name), Value(Descriptor.Value), EnumTypeInfo(TypeInfo) {}
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override;
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ std::string Name;
+ uint64 Value;
+ DwarfEnumTypeInfo *EnumTypeInfo;
+};
+
+class DwarfEnumTypeInfo : public DwarfInfo
+{
+public:
+ DwarfEnumTypeInfo(const EnumTypeDescriptor &TypeDescriptor,
+ const EnumRecordTypeDescriptor *TypeRecords);
+
+ void Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) override;
+
+ void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) override;
+
+ uint8_t GetByteSize() const { return ByteSize; }
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override;
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ std::string Name;
+ uint32_t ElementType;
+ std::vector<DwarfEnumerator> Records;
+ uint8_t ByteSize;
+};
+
+class DwarfDataField : public DwarfInfo
+{
+public:
+ DwarfDataField(const DataFieldDescriptor &Descriptor) :
+ Name(Descriptor.Name),
+ TypeIndex(Descriptor.FieldTypeIndex),
+ Offset(Descriptor.Offset) {}
+
+ void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) override;
+
+ uint32_t GetTypeIndex() const { return TypeIndex; }
+
+ const std::string &GetName() const { return Name; }
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override;
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+ std::string Name;
+ uint32_t TypeIndex;
+ uint64 Offset;
+};
+
+class DwarfStaticDataField : public DwarfDataField
+{
+public:
+ DwarfStaticDataField(const DataFieldDescriptor &Descriptor,
+ const StaticDataFieldDescriptor &StaticDescriptor) :
+ DwarfDataField(Descriptor),
+ StaticDataName(StaticDescriptor.StaticDataName),
+ StaticOffset(StaticDescriptor.StaticOffset),
+ StaticDataInObject(StaticDescriptor.IsStaticDataInObject) {}
+
+ const std::string &GetStaticDataName() const { return StaticDataName; }
+ uint64 GetStaticOffset() const { return StaticOffset; }
+ bool IsStaticDataInObject() const { return StaticDataInObject; }
+
+protected:
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ std::string StaticDataName;
+ uint64 StaticOffset;
+ bool StaticDataInObject;
+};
+
+class DwarfMemberFunctionIdTypeInfo;
+
+class DwarfClassTypeInfo : public DwarfInfo
+{
+public:
+ DwarfClassTypeInfo(const ClassTypeDescriptor &ClassDescriptor) :
+ Name(ClassDescriptor.Name),
+ IsStruct(ClassDescriptor.IsStruct),
+ BaseClassId(ClassDescriptor.BaseClassId),
+ Size(ClassDescriptor.InstanceSize),
+ IsForwardDecl(true) {}
+
+ DwarfClassTypeInfo(const ClassTypeDescriptor &ClassDescriptor,
+ const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
+ const DataFieldDescriptor *FieldsDescriptors,
+ const StaticDataFieldDescriptor *StaticsDescriptors);
+
+ void Dump(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) override;
+
+ void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) override;
+
+ void AddMemberFunction(DwarfMemberFunctionIdTypeInfo* TypeInfo) {
+ MemberFunctions.push_back(TypeInfo);
+ }
+
+ const std::vector<DwarfStaticDataField> &GetStaticFields() const { return StaticFields; }
+
+ const std::string &GetName() const { return Name; }
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override;
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ std::string Name;
+ bool IsStruct;
+ uint32_t BaseClassId;
+ uint64 Size;
+ bool IsForwardDecl;
+ std::vector<DwarfDataField> Fields;
+ std::vector<DwarfStaticDataField> StaticFields;
+ std::vector<DwarfMemberFunctionIdTypeInfo*> MemberFunctions;
+};
+
+class DwarfSimpleArrayTypeInfo : public DwarfInfo
+{
+public:
+ DwarfSimpleArrayTypeInfo(uint32_t ArrayElementType, uint64_t Size) :
+ ElementType(ArrayElementType),
+ Size(Size) {}
+
+ void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) override;
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override;
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ uint32_t ElementType;
+ uint64_t Size;
+};
+
+class DwarfPointerTypeInfo : public DwarfInfo
+{
+public:
+ DwarfPointerTypeInfo(const PointerTypeDescriptor& PointerDescriptor) :
+ TypeDesc(PointerDescriptor) {}
+
+ void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) override;
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override;
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ PointerTypeDescriptor TypeDesc;
+};
+
+class DwarfMemberFunctionTypeInfo : public DwarfInfo
+{
+public:
+ DwarfMemberFunctionTypeInfo(const MemberFunctionTypeDescriptor& MemberDescriptor,
+ uint32_t const *const ArgumentTypes,
+ bool IsStaticMethod);
+
+ const std::vector<uint32_t> &GetArgTypes() const { return ArgumentTypes; }
+
+ bool IsStatic() const { return IsStaticMethod; }
+
+ uint32_t GetReturnTypeIndex() const { return TypeDesc.ReturnType; }
+
+ uint32_t GetThisPtrTypeIndex() const { return TypeDesc.TypeIndexOfThisPointer; }
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override;
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ MemberFunctionTypeDescriptor TypeDesc;
+ std::vector<uint32_t> ArgumentTypes;
+ bool IsStaticMethod;
+};
+
+class DwarfMemberFunctionIdTypeInfo : public DwarfInfo
+{
+public:
+ DwarfMemberFunctionIdTypeInfo(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor,
+ DwarfMemberFunctionTypeInfo *TypeInfo) :
+ LinkageName(MemberIdDescriptor.Name),
+ Name(MemberIdDescriptor.Name),
+ ParentClass(MemberIdDescriptor.ParentClass),
+ MemberFunctionTypeInfo(TypeInfo),
+ LinkageNameSymbol(nullptr) {}
+
+ const std::vector<uint32_t> &GetArgTypes() const { return MemberFunctionTypeInfo->GetArgTypes(); }
+
+ void SetLinkageName(const char *Name) { LinkageName = Name; }
+
+ void DumpTypes(UserDefinedDwarfTypesBuilder *TypeBuilder, MCObjectStreamer *Streamer,
+ MCSection *TypeSection, MCSection *StrSection) override;
+
+ bool IsStatic() const { return MemberFunctionTypeInfo->IsStatic(); }
+
+protected:
+ void DumpStrings(MCObjectStreamer *Streamer) override;
+ void DumpTypeInfo(MCObjectStreamer *Streamer, UserDefinedDwarfTypesBuilder *TypeBuilder) override;
+
+private:
+ std::string LinkageName;
+ std::string Name;
+ uint32_t ParentClass;
+ DwarfMemberFunctionTypeInfo *MemberFunctionTypeInfo;
+ MCSymbol *LinkageNameSymbol;
+};
+
+template<class T>
+class EnumHash
+{
+ typedef typename std::underlying_type<T>::type enumType;
+public:
+ size_t operator()(const T& elem) const {
+ return std::hash<enumType>()(static_cast<enumType>(elem));
+ }
+};
+
+class UserDefinedDwarfTypesBuilder : public UserDefinedTypesBuilder
+{
+public:
+ UserDefinedDwarfTypesBuilder() {}
+ void EmitTypeInformation(MCSection *TypeSection, MCSection *StrSection = nullptr) override;
+
+ unsigned GetEnumTypeIndex(const EnumTypeDescriptor &TypeDescriptor,
+ const EnumRecordTypeDescriptor *TypeRecords) override;
+ unsigned GetClassTypeIndex(const ClassTypeDescriptor &ClassDescriptor) override;
+ unsigned GetCompleteClassTypeIndex(
+ const ClassTypeDescriptor &ClassDescriptor,
+ const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
+ const DataFieldDescriptor *FieldsDescriptors,
+ const StaticDataFieldDescriptor *StaticsDescriptors) override;
+
+ unsigned GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor,
+ const ArrayTypeDescriptor &ArrayDescriptor) override;
+
+ unsigned GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor) override;
+
+ unsigned GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor,
+ uint32_t const *const ArgumentTypes) override;
+
+ unsigned GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor) override;
+
+ unsigned GetPrimitiveTypeIndex(PrimitiveTypeFlags Type) override;
+
+ DwarfInfo *GetTypeInfoByIndex(unsigned Index) const { return DwarfTypes[TypeIndexToArrayIndex(Index)].get(); }
+
+ unsigned GetSimpleArrayTypeIndex(unsigned ElemIndex, unsigned Size);
+
+ const std::vector<DwarfClassTypeInfo*> &GetClassesWithStaticFields() const { return ClassesWithStaticFields; }
+
+private:
+ static const unsigned StartTypeIndex = 1; // Make TypeIndex 0 - Invalid
+ static unsigned TypeIndexToArrayIndex(unsigned TypeIndex) { return TypeIndex - StartTypeIndex; }
+ static unsigned ArrayIndexToTypeIndex(unsigned ArrayIndex) { return ArrayIndex + StartTypeIndex; }
+
+ std::vector<std::unique_ptr<DwarfInfo>> DwarfTypes;
+ std::unordered_map<PrimitiveTypeFlags, uint32_t, EnumHash<PrimitiveTypeFlags>> PrimitiveDwarfTypes;
+ // map[ElemTypeIndex][Size] -> ArrTypeIndex
+ std::unordered_map<uint32_t, std::unordered_map<uint32_t, uint32_t>> SimpleArrayDwarfTypes;
+
+ std::vector<DwarfClassTypeInfo*> ClassesWithStaticFields;
+}; \ No newline at end of file
diff --git a/src/Native/ObjWriter/debugInfo/typeBuilder.h b/src/Native/ObjWriter/debugInfo/typeBuilder.h
new file mode 100644
index 000000000..f3e3046e5
--- /dev/null
+++ b/src/Native/ObjWriter/debugInfo/typeBuilder.h
@@ -0,0 +1,158 @@
+//===---- typeBuilder.h -----------------------------------------*- C++ -*-===//
+//
+// type builder is used to convert .Net types into debuginfo.
+//
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include "llvm/MC/MCObjectStreamer.h"
+
+#include <string>
+#include <vector>
+
+using namespace llvm;
+
+// Keep in sync with Internal.TypeSystem.TypeFlags (Common/src/TypeSystem/Common/TypeFlags.cs)
+enum class PrimitiveTypeFlags {
+ Unknown = 0x00,
+ Void = 0x01,
+ Boolean = 0x02,
+ Char = 0x03,
+ SByte = 0x04,
+ Byte = 0x05,
+ Int16 = 0x06,
+ UInt16 = 0x07,
+ Int32 = 0x08,
+ UInt32 = 0x09,
+ Int64 = 0x0A,
+ UInt64 = 0x0B,
+ IntPtr = 0x0C,
+ UIntPtr = 0x0D,
+ Single = 0x0E,
+ Double = 0x0F
+};
+
+typedef unsigned long long uint64;
+
+#pragma pack(push, 8)
+
+extern "C" struct EnumRecordTypeDescriptor {
+ uint64 Value;
+ const char *Name;
+};
+
+extern "C" struct EnumTypeDescriptor {
+ uint32_t ElementType;
+ uint64 ElementCount;
+ const char *Name;
+};
+
+extern "C" struct ClassTypeDescriptor {
+ int32_t IsStruct;
+ const char *Name;
+ uint32_t BaseClassId;
+ uint64 InstanceSize;
+};
+
+extern "C" struct DataFieldDescriptor {
+ uint32_t FieldTypeIndex;
+ uint64 Offset;
+ const char *Name;
+};
+
+extern "C" struct StaticDataFieldDescriptor {
+ const char *StaticDataName;
+ uint64 StaticOffset;
+ int IsStaticDataInObject;
+};
+
+extern "C" struct ClassFieldsTypeDescriptior {
+ uint64 Size;
+ int32_t FieldsCount;
+};
+
+extern "C" struct ArrayTypeDescriptor {
+ uint32_t Rank;
+ uint32_t ElementType;
+ uint32_t Size; // ElementSize
+ int32_t IsMultiDimensional;
+};
+
+extern "C" struct PointerTypeDescriptor {
+ uint32_t ElementType;
+ int32_t IsReference;
+ int32_t IsConst;
+ int32_t Is64Bit;
+};
+
+extern "C" struct MemberFunctionTypeDescriptor {
+ uint32_t ReturnType;
+ uint32_t ContainingClass;
+ uint32_t TypeIndexOfThisPointer;
+ int32_t ThisAdjust;
+ uint32_t CallingConvention;
+ uint16_t NumberOfArguments;
+};
+
+extern "C" struct MemberFunctionIdTypeDescriptor {
+ uint32_t MemberFunction;
+ uint32_t ParentClass;
+ const char *Name;
+};
+
+#pragma pack(pop)
+class UserDefinedTypesBuilder {
+public:
+ UserDefinedTypesBuilder() : Streamer(nullptr), TargetPointerSize(0) {}
+ virtual ~UserDefinedTypesBuilder() {}
+ void SetStreamer(MCObjectStreamer *Streamer) {
+ assert(this->Streamer == nullptr);
+ assert(Streamer != nullptr);
+ this->Streamer = Streamer;
+ }
+ MCObjectStreamer *GetStreamer() const {
+ return Streamer;
+ }
+ void SetTargetPointerSize(unsigned TargetPointerSize) {
+ assert(this->TargetPointerSize == 0);
+ assert(TargetPointerSize != 0);
+ this->TargetPointerSize = TargetPointerSize;
+ }
+ virtual void EmitTypeInformation(MCSection *TypeSection, MCSection *StrSection = nullptr) = 0;
+
+ virtual unsigned GetEnumTypeIndex(const EnumTypeDescriptor &TypeDescriptor,
+ const EnumRecordTypeDescriptor *TypeRecords) = 0;
+ virtual unsigned GetClassTypeIndex(const ClassTypeDescriptor &ClassDescriptor) = 0;
+ virtual unsigned GetCompleteClassTypeIndex(
+ const ClassTypeDescriptor &ClassDescriptor,
+ const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
+ const DataFieldDescriptor *FieldsDescriptors,
+ const StaticDataFieldDescriptor *StaticsDescriptors) = 0;
+
+ virtual unsigned GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor,
+ const ArrayTypeDescriptor &ArrayDescriptor) = 0;
+
+ virtual unsigned GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor) = 0;
+
+ virtual unsigned GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor,
+ uint32_t const *const ArgumentTypes) = 0;
+
+ virtual unsigned GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor) = 0;
+
+ virtual unsigned GetPrimitiveTypeIndex(PrimitiveTypeFlags Type) = 0;
+
+ virtual const std::vector<std::pair<std::string, uint32_t>> &GetUDTs() {
+ return UserDefinedTypes;
+ }
+
+protected:
+ MCObjectStreamer *Streamer;
+ unsigned TargetPointerSize;
+
+ std::vector<std::pair<std::string, uint32_t>> UserDefinedTypes;
+}; \ No newline at end of file
diff --git a/src/Native/ObjWriter/jitDebugInfo.h b/src/Native/ObjWriter/jitDebugInfo.h
index 103dff8ad..ec63c3dfb 100644
--- a/src/Native/ObjWriter/jitDebugInfo.h
+++ b/src/Native/ObjWriter/jitDebugInfo.h
@@ -26,6 +26,18 @@ struct DebugVarInfo {
: Name(ArgName), TypeIndex(ArgTypeIndex), IsParam(ArgIsParam) {}
};
+struct DebugEHClauseInfo {
+ unsigned TryOffset;
+ unsigned TryLength;
+ unsigned HandlerOffset;
+ unsigned HandlerLength;
+
+ DebugEHClauseInfo(unsigned TryOffset, unsigned TryLength,
+ unsigned HandlerOffset, unsigned HandlerLength) :
+ TryOffset(TryOffset), TryLength(TryLength),
+ HandlerOffset(HandlerOffset), HandlerLength(HandlerLength) {}
+};
+
typedef unsigned short CVRegMapping;
#define CVREGDAT(p2, cv) cv
diff --git a/src/Native/ObjWriter/llvm.patch b/src/Native/ObjWriter/llvm.patch
index fd8420125..67ae23ec9 100644
--- a/src/Native/ObjWriter/llvm.patch
+++ b/src/Native/ObjWriter/llvm.patch
@@ -15,7 +15,7 @@ index 7c1189e..d1d77c9 100644
/// can change its size during relaxation.
virtual void EmitInstToFragment(const MCInst &Inst, const MCSubtargetInfo &);
diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h
-index 5390e79..e28a3cc 100644
+index 5390e79..5b258e7 100644
--- a/include/llvm/MC/MCStreamer.h
+++ b/include/llvm/MC/MCStreamer.h
@@ -115,6 +115,7 @@ public:
@@ -26,6 +26,16 @@ index 5390e79..e28a3cc 100644
virtual void emitUnwindRaw(int64_t StackOffset,
const SmallVectorImpl<uint8_t> &Opcodes);
+@@ -548,6 +549,9 @@ public:
+ /// etc.
+ virtual void EmitBytes(StringRef Data);
+
++ /// \brief Emit the given \p Instruction data into the current section.
++ virtual void EmitInstructionBytes(StringRef Data);
++
+ /// Functionally identical to EmitBytes. When emitting textual assembly, this
+ /// method uses .byte directives instead of .ascii or .asciz for readability.
+ virtual void EmitBinaryData(StringRef Data);
diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp
index 174397e..ef7161f 100644
--- a/lib/MC/MCObjectStreamer.cpp
@@ -57,6 +67,18 @@ index 174397e..ef7161f 100644
void MCObjectStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
// We need to create a local symbol to avoid relocations.
Frame.Begin = getContext().createTempSymbol();
+diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp
+index 2bfb9a6..a710098 100644
+--- a/lib/MC/MCStreamer.cpp
++++ b/lib/MC/MCStreamer.cpp
+@@ -830,6 +830,7 @@ void MCStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
+ void MCStreamer::ChangeSection(MCSection *, const MCExpr *) {}
+ void MCStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {}
+ void MCStreamer::EmitBytes(StringRef Data) {}
++void MCStreamer::EmitInstructionBytes(StringRef Data) { EmitBytes(Data); }
+ void MCStreamer::EmitBinaryData(StringRef Data) { EmitBytes(Data); }
+ void MCStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) {
+ visitUsedExpr(*Value);
diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
index a77df7a..e1aa752 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
@@ -122,7 +144,7 @@ index 59f31be..9b95598 100644
case ARM::fixup_arm_uncondbl:
switch (Modifier) {
diff --git a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
-index 93f4006..67ae439 100644
+index 93f4006..81e4caa 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
@@ -396,6 +396,7 @@ private:
@@ -141,7 +163,26 @@ index 93f4006..67ae439 100644
void emitUnwindRaw(int64_t Offset, const SmallVectorImpl<uint8_t> &Opcodes);
void ChangeSection(MCSection *Section, const MCExpr *Subsection) override {
-@@ -698,6 +700,7 @@ private:
+@@ -533,6 +535,18 @@ public:
+ MCELFStreamer::EmitBytes(Data);
+ }
+
++ /// This function is the one used to emit instruction data into the ELF
++ /// streamer. We override it to add the appropriate mapping symbol if
++ /// necessary.
++ void EmitInstructionBytes(StringRef Data) override {
++ if (IsThumb)
++ EmitThumbMappingSymbol();
++ else
++ EmitARMMappingSymbol();
++
++ MCELFStreamer::EmitBytes(Data);
++ }
++
+ void FlushPendingMappingSymbol() {
+ if (!LastEMSInfo->hasInfo())
+ return;
+@@ -698,6 +712,7 @@ private:
bool CantUnwind;
SmallVector<uint8_t, 64> Opcodes;
UnwindOpcodeAssembler UnwindOpAsm;
@@ -149,7 +190,7 @@ index 93f4006..67ae439 100644
};
} // end anonymous namespace
-@@ -740,6 +743,10 @@ void ARMTargetELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
+@@ -740,6 +755,10 @@ void ARMTargetELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
getStreamer().emitRegSave(RegList, isVector);
}
@@ -160,7 +201,7 @@ index 93f4006..67ae439 100644
void ARMTargetELFStreamer::emitUnwindRaw(int64_t Offset,
const SmallVectorImpl<uint8_t> &Opcodes) {
getStreamer().emitUnwindRaw(Offset, Opcodes);
-@@ -1233,6 +1240,7 @@ void ARMELFStreamer::EHReset() {
+@@ -1233,6 +1252,7 @@ void ARMELFStreamer::EHReset() {
PendingOffset = 0;
UsedFP = false;
CantUnwind = false;
@@ -168,7 +209,7 @@ index 93f4006..67ae439 100644
Opcodes.clear();
UnwindOpAsm.Reset();
-@@ -1330,6 +1338,8 @@ void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) {
+@@ -1330,6 +1350,8 @@ void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) {
}
// Finalize the unwind opcode sequence
@@ -177,7 +218,7 @@ index 93f4006..67ae439 100644
UnwindOpAsm.Finalize(PersonalityIndex, Opcodes);
// For compact model 0, we have to emit the unwind opcodes in the .ARM.exidx
-@@ -1374,7 +1384,13 @@ void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) {
+@@ -1374,7 +1396,13 @@ void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) {
//
// In case that the .handlerdata directive is not specified by the
// programmer, we should emit zero to terminate the handler data.
@@ -192,7 +233,7 @@ index 93f4006..67ae439 100644
EmitIntValue(0, 4);
}
-@@ -1457,6 +1473,10 @@ void ARMELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
+@@ -1457,6 +1485,10 @@ void ARMELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList,
UnwindOpAsm.EmitRegSave(Mask);
}
diff --git a/src/Native/ObjWriter/llvmCap/CMakeLists.txt b/src/Native/ObjWriter/llvmCap/CMakeLists.txt
index a749ea878..07dca10e9 100644
--- a/src/Native/ObjWriter/llvmCap/CMakeLists.txt
+++ b/src/Native/ObjWriter/llvmCap/CMakeLists.txt
@@ -116,14 +116,32 @@ ExternalProject_Add(LLVM
ExternalProject_Get_Property(LLVM source_dir)
set(LLVM_SOURCE_DIR ${source_dir})
ExternalProject_Add_Step(LLVM PatchingLLVM
- COMMAND git apply --3way ${OBJWRITER_ROOT}/llvm.patch COMMENT "Applying LLVM patch with ObjWriter fixes"
+ COMMAND git checkout -- .
+ COMMAND git apply ${OBJWRITER_ROOT}/llvm.patch COMMENT "Applying LLVM patch with ObjWriter fixes"
WORKING_DIRECTORY ${LLVM_SOURCE_DIR}
DEPENDEES patch
USES_TERMINAL 1
)
+
+if(CMAKE_HOST_WIN32)
+ExternalProject_Add_Step(LLVM ObjWriterInjection
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${OBJWRITER_ROOT} ${OBJWRITER_LLVM_POINT} COMMENT "copy ${OBJWRITER_ROOT} -> ${OBJWRITER_LLVM_POINT}"
+ WORKING_DIRECTORY ${LLVM_SOURCE_DIR}
+ DEPENDEES patch
+ USES_TERMINAL 1
+ )
+else()
ExternalProject_Add_Step(LLVM ObjWriterInjection
COMMAND ${CMAKE_COMMAND} -E create_symlink ${OBJWRITER_ROOT} ${OBJWRITER_LLVM_POINT} COMMENT "mklink ${OBJWRITER_ROOT} -> ${OBJWRITER_LLVM_POINT}"
WORKING_DIRECTORY ${LLVM_SOURCE_DIR}
DEPENDEES patch
USES_TERMINAL 1
)
+endif()
+
+ExternalProject_Add_Step(LLVM forceconfigure
+ COMMAND ${CMAKE_COMMAND} -E echo "Force configure of LLVM"
+ DEPENDEES update
+ DEPENDERS configure
+ ALWAYS 1
+ )
diff --git a/src/Native/ObjWriter/objwriter.cpp b/src/Native/ObjWriter/objwriter.cpp
index 55f79aa47..bdf1016dc 100644
--- a/src/Native/ObjWriter/objwriter.cpp
+++ b/src/Native/ObjWriter/objwriter.cpp
@@ -1,10 +1,10 @@
-//===---- objwriter.cpp --------------------------------*- C++ -*-===//
+//===---- objwriter.cpp -----------------------------------------*- C++ -*-===//
//
// object writer
//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license.
-// See LICENSE file in the project root for full license information.
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
//
//===----------------------------------------------------------------------===//
///
@@ -14,6 +14,8 @@
//===----------------------------------------------------------------------===//
#include "objwriter.h"
+#include "debugInfo/dwarf/dwarfTypeBuilder.h"
+#include "debugInfo/codeView/codeViewTypeBuilder.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
@@ -162,9 +164,18 @@ bool ObjectWriter::Init(llvm::StringRef ObjectFilePath) {
SetCodeSectionAttribute("text", CustomSectionAttributes_Executable, nullptr);
if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF) {
- TypeBuilder.SetStreamer(Streamer);
- unsigned TargetPointerSize = AssemblerPrinter->getPointerSize();
- TypeBuilder.SetTargetPointerSize(TargetPointerSize);
+ TypeBuilder.reset(new UserDefinedCodeViewTypesBuilder());
+ } else {
+ TypeBuilder.reset(new UserDefinedDwarfTypesBuilder());
+ }
+
+ TypeBuilder->SetStreamer(Streamer);
+ unsigned TargetPointerSize = AssemblerPrinter->getPointerSize();
+ TypeBuilder->SetTargetPointerSize(TargetPointerSize);
+
+ if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsELF) {
+ DwarfGenerator.reset(new DwarfGen());
+ DwarfGenerator->SetTypeBuilder(static_cast<UserDefinedDwarfTypesBuilder*>(TypeBuilder.get()));
}
return true;
@@ -294,7 +305,11 @@ void ObjectWriter::EmitAlignment(int ByteAlignment) {
}
void ObjectWriter::EmitBlob(int BlobSize, const char *Blob) {
- Streamer->EmitBytes(StringRef(Blob, BlobSize));
+ if (Streamer->getCurrentSectionOnly()->getKind().isText()) {
+ Streamer->EmitInstructionBytes(StringRef(Blob, BlobSize));
+ } else {
+ Streamer->EmitBytes(StringRef(Blob, BlobSize));
+ }
}
void ObjectWriter::EmitIntValue(uint64_t Value, unsigned Size) {
@@ -690,6 +705,22 @@ void ObjectWriter::EmitCVDebugFunctionInfo(const char *FunctionName,
Streamer->EmitCVLinetableDirective(FuncId++, Fn, FnEnd);
}
+void ObjectWriter::EmitDwarfFunctionInfo(const char *FunctionName,
+ int FunctionSize,
+ unsigned MethodTypeIndex) {
+ if (FuncId == 1) {
+ DwarfGenerator->EmitCompileUnit();
+ }
+
+ DwarfGenerator->EmitSubprogramInfo(FunctionName, FunctionSize,
+ MethodTypeIndex, DebugVarInfos, DebugEHClauseInfos);
+
+ DebugVarInfos.clear();
+ DebugEHClauseInfos.clear();
+
+ FuncId++;
+}
+
void ObjectWriter::EmitDebugFileInfo(int FileId, const char *FileName) {
assert(FileId > 0 && "FileId should be greater than 0.");
if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF) {
@@ -700,7 +731,8 @@ void ObjectWriter::EmitDebugFileInfo(int FileId, const char *FileName) {
}
void ObjectWriter::EmitDebugFunctionInfo(const char *FunctionName,
- int FunctionSize) {
+ int FunctionSize,
+ unsigned MethodTypeIndex) {
if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF) {
Streamer->EmitCVFuncIdDirective(FuncId);
EmitCVDebugFunctionInfo(FunctionName, FunctionSize);
@@ -710,6 +742,7 @@ void ObjectWriter::EmitDebugFunctionInfo(const char *FunctionName,
Streamer->EmitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
Streamer->emitELFSize(Sym,
MCConstantExpr::create(FunctionSize, *OutContext));
+ EmitDwarfFunctionInfo(FunctionName, FunctionSize, MethodTypeIndex);
}
// TODO: Should test it for Macho.
}
@@ -729,6 +762,13 @@ void ObjectWriter::EmitDebugVar(char *Name, int TypeIndex, bool IsParm,
DebugVarInfos.push_back(NewVar);
}
+void ObjectWriter::EmitDebugEHClause(unsigned TryOffset, unsigned TryLength,
+ unsigned HandlerOffset, unsigned HandlerLength) {
+ if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsELF) {
+ DebugEHClauseInfos.emplace_back(TryOffset, TryLength, HandlerOffset, HandlerLength);
+ }
+}
+
void ObjectWriter::EmitDebugLoc(int NativeOffset, int FileId, int LineNumber,
int ColNumber) {
assert(FileId > 0 && "FileId should be greater than 0.");
@@ -742,7 +782,7 @@ void ObjectWriter::EmitDebugLoc(int NativeOffset, int FileId, int LineNumber,
}
void ObjectWriter::EmitCVUserDefinedTypesSymbols() {
- const auto &UDTs = TypeBuilder.GetUDTs();
+ const auto &UDTs = TypeBuilder->GetUDTs();
if (UDTs.empty()) {
return;
}
@@ -755,12 +795,12 @@ void ObjectWriter::EmitCVUserDefinedTypesSymbols() {
EmitLabelDiff(SymbolsBegin, SymbolsEnd);
Streamer->EmitLabel(SymbolsBegin);
- for (const std::pair<std::string, codeview::TypeIndex> &UDT : UDTs) {
+ for (const std::pair<std::string, uint32_t> &UDT : UDTs) {
unsigned NameLength = UDT.first.length() + 1;
unsigned RecordLength = 2 + 4 + NameLength;
Streamer->EmitIntValue(RecordLength, 2);
Streamer->EmitIntValue(unsigned(SymbolKind::S_UDT), 2);
- Streamer->EmitIntValue(UDT.second.getIndex(), 4);
+ Streamer->EmitIntValue(UDT.second, 4);
Streamer->EmitBytes(StringRef(UDT.first.c_str(), NameLength));
}
Streamer->EmitLabel(SymbolsEnd);
@@ -769,7 +809,7 @@ void ObjectWriter::EmitCVUserDefinedTypesSymbols() {
void ObjectWriter::EmitDebugModuleInfo() {
if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF) {
- TypeBuilder.EmitTypeInformation(ObjFileInfo->getCOFFDebugTypesSection());
+ TypeBuilder->EmitTypeInformation(ObjFileInfo->getCOFFDebugTypesSection());
EmitCVUserDefinedTypesSymbols();
}
@@ -783,6 +823,10 @@ void ObjectWriter::EmitDebugModuleInfo() {
Streamer->SwitchSection(Section);
Streamer->EmitCVFileChecksumsDirective();
Streamer->EmitCVStringTableDirective();
+ } else if (ObjFileInfo->getObjectFileType() == ObjFileInfo->IsELF) {
+ DwarfGenerator->EmitAbbrev();
+ DwarfGenerator->EmitAranges();
+ DwarfGenerator->Finish();
} else {
OutContext->setGenDwarfForAssembly(true);
}
@@ -791,56 +835,50 @@ void ObjectWriter::EmitDebugModuleInfo() {
unsigned
ObjectWriter::GetEnumTypeIndex(const EnumTypeDescriptor &TypeDescriptor,
const EnumRecordTypeDescriptor *TypeRecords) {
- assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF &&
- "only COFF is supported now");
- return TypeBuilder.GetEnumTypeIndex(TypeDescriptor, TypeRecords);
+ return TypeBuilder->GetEnumTypeIndex(TypeDescriptor, TypeRecords);
}
unsigned
ObjectWriter::GetClassTypeIndex(const ClassTypeDescriptor &ClassDescriptor) {
- assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF &&
- "only COFF is supported now");
- return TypeBuilder.GetClassTypeIndex(ClassDescriptor);
+ unsigned res = TypeBuilder->GetClassTypeIndex(ClassDescriptor);
+ return res;
}
unsigned ObjectWriter::GetCompleteClassTypeIndex(
const ClassTypeDescriptor &ClassDescriptor,
const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
- const DataFieldDescriptor *FieldsDescriptors) {
- assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF &&
- "only COFF is supported now");
- return TypeBuilder.GetCompleteClassTypeIndex(
- ClassDescriptor, ClassFieldsDescriptor, FieldsDescriptors);
+ const DataFieldDescriptor *FieldsDescriptors,
+ const StaticDataFieldDescriptor *StaticsDescriptors) {
+ unsigned res = TypeBuilder->GetCompleteClassTypeIndex(ClassDescriptor,
+ ClassFieldsDescriptor, FieldsDescriptors, StaticsDescriptors);
+ return res;
}
unsigned
ObjectWriter::GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor,
const ArrayTypeDescriptor &ArrayDescriptor) {
- assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF &&
- "only COFF is supported now");
- return TypeBuilder.GetArrayTypeIndex(ClassDescriptor, ArrayDescriptor);
+ return TypeBuilder->GetArrayTypeIndex(ClassDescriptor, ArrayDescriptor);
}
unsigned
ObjectWriter::GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor) {
- assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF &&
- "only COFF is supported now");
- return TypeBuilder.GetPointerTypeIndex(PointerDescriptor);
+ return TypeBuilder->GetPointerTypeIndex(PointerDescriptor);
}
unsigned
ObjectWriter::GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor,
uint32_t const *const ArgumentTypes) {
- assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF &&
- "only COFF is supported now");
- return TypeBuilder.GetMemberFunctionTypeIndex(MemberDescriptor, ArgumentTypes);
+ return TypeBuilder->GetMemberFunctionTypeIndex(MemberDescriptor, ArgumentTypes);
}
unsigned
ObjectWriter::GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor) {
- assert(ObjFileInfo->getObjectFileType() == ObjFileInfo->IsCOFF &&
- "only COFF is supported now");
- return TypeBuilder.GetMemberFunctionId(MemberIdDescriptor);
+ return TypeBuilder->GetMemberFunctionId(MemberIdDescriptor);
+}
+
+unsigned
+ObjectWriter::GetPrimitiveTypeIndex(int Type) {
+ return TypeBuilder->GetPrimitiveTypeIndex(static_cast<PrimitiveTypeFlags>(Type));
}
void
@@ -883,13 +921,13 @@ void ObjectWriter::EmitARMExIdxCode(int Offset, const char *Blob)
ATS.emitPad(CfiCode->Offset);
break;
case CFI_REL_OFFSET:
- RegList.push_back(CfiCode->DwarfReg);
+ RegList.push_back(CfiCode->DwarfReg + 14); // See ARMRegEncodingTable in ARMGenRegisterInfo.inc by getEncodingValue
ATS.emitRegSave(RegList, false);
break;
case CFI_DEF_CFA_REGISTER:
assert(CfiCode->Offset == 0 &&
"Unexpected Offset Value for OpDefCfaRegister");
- ATS.emitMovSP(CfiCode->DwarfReg, 0);
+ ATS.emitMovSP(CfiCode->DwarfReg + 14, 0); // See ARMRegEncodingTable in ARMGenRegisterInfo.inc by getEncodingValue
break;
default:
assert(false && "Unrecognized CFI");
diff --git a/src/Native/ObjWriter/objwriter.h b/src/Native/ObjWriter/objwriter.h
index 21327b3be..6c1ba8645 100644
--- a/src/Native/ObjWriter/objwriter.h
+++ b/src/Native/ObjWriter/objwriter.h
@@ -1,10 +1,10 @@
-//===---- objwriter.h --------------------------------*- C++ -*-===//
+//===---- objwriter.h ------------------------------------------*- C++ -*-===//
//
// object writer
//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license.
-// See LICENSE file in the project root for full license information.
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
//
//===----------------------------------------------------------------------===//
@@ -19,7 +19,8 @@
#include "jitDebugInfo.h"
#include <string>
#include <set>
-#include "typeBuilder.h"
+#include "debugInfo/typeBuilder.h"
+#include "debugInfo/dwarf/dwarfGen.h"
using namespace llvm;
using namespace llvm::codeview;
@@ -68,11 +69,13 @@ public:
int EmitSymbolRef(const char *SymbolName, RelocType RelocType, int Delta);
void EmitDebugFileInfo(int FileId, const char *FileName);
- void EmitDebugFunctionInfo(const char *FunctionName, int FunctionSize);
+ void EmitDebugFunctionInfo(const char *FunctionName, int FunctionSize, unsigned MethodTypeIndex);
void EmitDebugVar(char *Name, int TypeIndex, bool IsParm, int RangeCount,
const ICorDebugInfo::NativeVarInfo *Ranges);
void EmitDebugLoc(int NativeOffset, int FileId, int LineNumber,
int ColNumber);
+ void EmitDebugEHClause(unsigned TryOffset, unsigned TryLength,
+ unsigned HandlerOffset, unsigned HandlerLength);
void EmitDebugModuleInfo();
void EmitCFIStart(int Offset);
@@ -86,7 +89,8 @@ public:
unsigned GetCompleteClassTypeIndex(
const ClassTypeDescriptor &ClassDescriptor,
const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
- const DataFieldDescriptor *FieldsDescriptors);
+ const DataFieldDescriptor *FieldsDescriptors,
+ const StaticDataFieldDescriptor *StaticsDescriptors);
unsigned GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor,
const ArrayTypeDescriptor &ArrayDescriptor);
@@ -98,6 +102,8 @@ public:
unsigned GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor);
+ unsigned GetPrimitiveTypeIndex(int Type);
+
void EmitARMFnStart();
void EmitARMFnEnd();
void EmitARMExIdxCode(int Offset, const char *Blob);
@@ -114,6 +120,8 @@ private:
int NumVarInfos);
void EmitCVDebugFunctionInfo(const char *FunctionName, int FunctionSize);
+ void EmitDwarfFunctionInfo(const char *FunctionName, int FunctionSize, unsigned MethodTypeIndex);
+
const MCSymbolRefExpr *GetSymbolRefExpr(
const char *SymbolName,
MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None);
@@ -149,16 +157,18 @@ private:
std::unique_ptr<TargetMachine> TMachine;
std::unique_ptr<AsmPrinter> AssemblerPrinter;
MCAssembler *Assembler; // Owned by MCStreamer
+ std::unique_ptr<DwarfGen> DwarfGenerator;
std::unique_ptr<raw_fd_ostream> OS;
MCTargetOptions TargetMOptions;
bool FrameOpened;
std::vector<DebugVarInfo> DebugVarInfos;
+ std::vector<DebugEHClauseInfo> DebugEHClauseInfos;
std::set<MCSection *> Sections;
int FuncId;
- UserDefinedTypesBuilder TypeBuilder;
+ std::unique_ptr<UserDefinedTypesBuilder> TypeBuilder;
std::string TripleName;
@@ -258,9 +268,10 @@ DLL_EXPORT void EmitDebugFileInfo(ObjectWriter *OW, int FileId,
DLL_EXPORT void EmitDebugFunctionInfo(ObjectWriter *OW,
const char *FunctionName,
- int FunctionSize) {
+ int FunctionSize,
+ unsigned MethodTypeIndex) {
assert(OW && "ObjWriter is null");
- OW->EmitDebugFunctionInfo(FunctionName, FunctionSize);
+ OW->EmitDebugFunctionInfo(FunctionName, FunctionSize, MethodTypeIndex);
}
DLL_EXPORT void EmitDebugVar(ObjectWriter *OW, char *Name, int TypeIndex,
@@ -270,6 +281,13 @@ DLL_EXPORT void EmitDebugVar(ObjectWriter *OW, char *Name, int TypeIndex,
OW->EmitDebugVar(Name, TypeIndex, IsParam, RangeCount, Ranges);
}
+DLL_EXPORT void EmitDebugEHClause(ObjectWriter *OW, unsigned TryOffset,
+ unsigned TryLength, unsigned HandlerOffset,
+ unsigned HandlerLength) {
+ assert(OW && "ObjWriter is null");
+ OW->EmitDebugEHClause(TryOffset, TryLength, HandlerOffset, HandlerLength);
+}
+
DLL_EXPORT void EmitDebugLoc(ObjectWriter *OW, int NativeOffset, int FileId,
int LineNumber, int ColNumber) {
assert(OW && "ObjWriter is null");
@@ -299,10 +317,11 @@ DLL_EXPORT unsigned GetClassTypeIndex(ObjectWriter *OW,
DLL_EXPORT unsigned
GetCompleteClassTypeIndex(ObjectWriter *OW, ClassTypeDescriptor ClassDescriptor,
ClassFieldsTypeDescriptior ClassFieldsDescriptor,
- DataFieldDescriptor *FieldsDescriptors) {
+ DataFieldDescriptor *FieldsDescriptors,
+ StaticDataFieldDescriptor *StaticsDescriptors) {
assert(OW && "ObjWriter is null");
return OW->GetCompleteClassTypeIndex(ClassDescriptor, ClassFieldsDescriptor,
- FieldsDescriptors);
+ FieldsDescriptors, StaticsDescriptors);
}
DLL_EXPORT unsigned GetArrayTypeIndex(ObjectWriter *OW,
@@ -331,6 +350,11 @@ DLL_EXPORT unsigned GetMemberFunctionIdTypeIndex(ObjectWriter *OW,
return OW->GetMemberFunctionId(MemberIdDescriptor);
}
+DLL_EXPORT unsigned GetPrimitiveTypeIndex(ObjectWriter *OW, int Type) {
+ assert(OW && "ObjWriter is null");
+ return OW->GetPrimitiveTypeIndex(Type);
+}
+
DLL_EXPORT void EmitARMFnStart(ObjectWriter *OW) {
assert(OW && "ObjWriter is null");
return OW->EmitARMFnStart();
diff --git a/src/Native/ObjWriter/typeBuilder.h b/src/Native/ObjWriter/typeBuilder.h
deleted file mode 100644
index a5037b769..000000000
--- a/src/Native/ObjWriter/typeBuilder.h
+++ /dev/null
@@ -1,145 +0,0 @@
-//===---- typeBuilder.h --------------------------------*- C++ -*-===//
-//
-// type builder is used to convert .Net types into CodeView descriptors.
-//
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license.
-// See LICENSE file in the project root for full license information.
-//
-//===----------------------------------------------------------------------===//
-
-#pragma once
-
-#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
-#include "llvm/MC/MCObjectStreamer.h"
-
-#include <string>
-#include <vector>
-
-using namespace llvm;
-using namespace llvm::codeview;
-
-typedef unsigned long long uint64;
-
-#pragma pack(push, 8)
-
-extern "C" struct EnumRecordTypeDescriptor {
- uint64 Value;
- char *Name;
-};
-
-extern "C" struct EnumTypeDescriptor {
- uint32_t ElementType;
- uint64 ElementCount;
- char *Name;
-};
-
-extern "C" struct ClassTypeDescriptor {
- int32_t IsStruct;
- char *Name;
- uint32_t BaseClassId;
-};
-
-extern "C" struct DataFieldDescriptor {
- uint32_t FieldTypeIndex;
- uint64 Offset;
- char *Name;
-};
-
-extern "C" struct ClassFieldsTypeDescriptior {
- uint64 Size;
- int32_t FieldsCount;
-};
-
-extern "C" struct ArrayTypeDescriptor {
- uint32_t Rank;
- uint32_t ElementType;
- uint32_t Size;
- int32_t IsMultiDimensional;
-};
-
-extern "C" struct PointerTypeDescriptor {
- uint32_t ElementType;
- int32_t IsReference;
- int32_t IsConst;
- int32_t Is64Bit;
-};
-
-extern "C" struct MemberFunctionTypeDescriptor {
- uint32_t ReturnType;
- uint32_t ContainingClass;
- uint32_t TypeIndexOfThisPointer;
- int32_t ThisAdjust;
- uint32_t CallingConvention;
- uint16_t NumberOfArguments;
-};
-
-extern "C" struct MemberFunctionIdTypeDescriptor {
- uint32_t MemberFunction;
- uint32_t ParentClass;
- char *Name;
-};
-
-class ArrayDimensionsDescriptor {
-public:
- const char *GetLengthName(unsigned index);
- const char *GetBoundsName(unsigned index);
-
-private:
- void Resize(unsigned NewSize);
-
- std::vector<std::string> Lengths;
- std::vector<std::string> Bounds;
-};
-
-#pragma pack(pop)
-class UserDefinedTypesBuilder {
-public:
- UserDefinedTypesBuilder();
- void SetStreamer(MCObjectStreamer *Streamer);
- void SetTargetPointerSize(unsigned TargetPointerSize);
- void EmitTypeInformation(MCSection *COFFDebugTypesSection);
-
- unsigned GetEnumTypeIndex(const EnumTypeDescriptor &TypeDescriptor,
- const EnumRecordTypeDescriptor *TypeRecords);
- unsigned GetClassTypeIndex(const ClassTypeDescriptor &ClassDescriptor);
- unsigned GetCompleteClassTypeIndex(
- const ClassTypeDescriptor &ClassDescriptor,
- const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
- const DataFieldDescriptor *FieldsDescriptors);
-
- unsigned GetArrayTypeIndex(const ClassTypeDescriptor &ClassDescriptor,
- const ArrayTypeDescriptor &ArrayDescriptor);
-
- unsigned GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor);
-
- unsigned GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor,
- uint32_t const *const ArgumentTypes);
-
- unsigned GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor);
-
- const std::vector<std::pair<std::string, codeview::TypeIndex>> &GetUDTs() {
- return UserDefinedTypes;
- }
-
-private:
- void EmitCodeViewMagicVersion();
- ClassOptions GetCommonClassOptions();
-
- unsigned GetEnumFieldListType(uint64 Count,
- const EnumRecordTypeDescriptor *TypeRecords);
-
- void AddBaseClass(FieldListRecordBuilder &FLBR, unsigned BaseClassId);
- void AddClassVTShape(FieldListRecordBuilder &FLBR);
-
- BumpPtrAllocator Allocator;
- TypeTableBuilder TypeTable;
-
- MCObjectStreamer *Streamer;
- unsigned TargetPointerSize;
-
- ArrayDimensionsDescriptor ArrayDimentions;
- TypeIndex ClassVTableTypeIndex;
-
- std::vector<std::pair<std::string, codeview::TypeIndex>> UserDefinedTypes;
-};
diff --git a/src/Native/Runtime/CMakeLists.txt b/src/Native/Runtime/CMakeLists.txt
index 1cd4cd949..b65011432 100644
--- a/src/Native/Runtime/CMakeLists.txt
+++ b/src/Native/Runtime/CMakeLists.txt
@@ -48,8 +48,6 @@ set(COMMON_RUNTIME_SOURCES
../gc/gccommon.cpp
../gc/gceewks.cpp
../gc/gcwks.cpp
- ../gc/gceesvr.cpp
- ../gc/gcsvr.cpp
../gc/gcscan.cpp
../gc/handletable.cpp
../gc/handletablecache.cpp
@@ -58,6 +56,11 @@ set(COMMON_RUNTIME_SOURCES
../gc/objecthandle.cpp
)
+set(SERVER_GC_SOURCES
+ ../gc/gceesvr.cpp
+ ../gc/gcsvr.cpp
+)
+
set(FULL_RUNTIME_SOURCES
AsmOffsetsVerify.cpp
ThunksMapping.cpp
@@ -171,7 +174,6 @@ convert_to_absolute_path(ARCH_SOURCES_DIR ${ARCH_SOURCES_DIR})
include_directories(${ARCH_SOURCES_DIR})
add_definitions(-DFEATURE_BACKGROUND_GC)
-add_definitions(-DFEATURE_SVR_GC)
add_definitions(-DFEATURE_BASICFREEZE)
add_definitions(-DFEATURE_CONSERVATIVE_GC)
add_definitions(-DFEATURE_CUSTOM_IMPORTS)
@@ -183,6 +185,7 @@ add_definitions(-DCORERT)
add_definitions(-DFEATURE_CACHED_INTERFACE_DISPATCH)
add_definitions(-D_LIB)
add_definitions(-DEETYPE_TYPE_MANAGER)
+add_definitions(-DFEATURE_EMBEDDED_CONFIG)
if(WIN32)
# There is a problem with undefined symbol g_pConfig, windows don't care since it is in template method, but clang does
@@ -221,6 +224,7 @@ convert_to_absolute_path(COMMON_RUNTIME_SOURCES ${COMMON_RUNTIME_SOURCES})
convert_to_absolute_path(FULL_RUNTIME_SOURCES ${FULL_RUNTIME_SOURCES})
convert_to_absolute_path(PORTABLE_RUNTIME_SOURCES ${PORTABLE_RUNTIME_SOURCES})
+convert_to_absolute_path(SERVER_GC_SOURCES ${SERVER_GC_SOURCES})
convert_to_absolute_path(RUNTIME_SOURCES_ARCH_ASM ${RUNTIME_SOURCES_ARCH_ASM})
diff --git a/src/Native/Runtime/Full/CMakeLists.txt b/src/Native/Runtime/Full/CMakeLists.txt
index af7de3a21..fff2da4b3 100644
--- a/src/Native/Runtime/Full/CMakeLists.txt
+++ b/src/Native/Runtime/Full/CMakeLists.txt
@@ -11,6 +11,11 @@ add_definitions(-DFEATURE_RX_THUNKS)
add_library(Runtime STATIC ${COMMON_RUNTIME_SOURCES} ${FULL_RUNTIME_SOURCES} ${RUNTIME_SOURCES_ARCH_ASM})
+add_library(Runtime.ServerGC STATIC ${COMMON_RUNTIME_SOURCES} ${FULL_RUNTIME_SOURCES} ${RUNTIME_SOURCES_ARCH_ASM} ${SERVER_GC_SOURCES})
+
+target_compile_definitions(Runtime.ServerGC PRIVATE -DFEATURE_SVR_GC)
+
+
# Get the current list of definitions
get_compile_definitions(DEFINITIONS)
@@ -72,7 +77,8 @@ foreach(CONFIG IN LISTS CMAKE_CONFIGURATION_TYPES)
endforeach()
# Install the static Runtime library
-install (TARGETS Runtime DESTINATION sdk)
+install (TARGETS Runtime Runtime.ServerGC DESTINATION sdk)
if(WIN32)
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/Runtime.dir/$<CONFIG>/Runtime.pdb DESTINATION sdk)
+ install (FILES ${CMAKE_CURRENT_BINARY_DIR}/Runtime.ServerGC.dir/$<CONFIG>/Runtime.ServerGC.pdb DESTINATION sdk)
endif()
diff --git a/src/Native/Runtime/Portable/CMakeLists.txt b/src/Native/Runtime/Portable/CMakeLists.txt
index 21dbb7d7c..7de7ce9d0 100644
--- a/src/Native/Runtime/Portable/CMakeLists.txt
+++ b/src/Native/Runtime/Portable/CMakeLists.txt
@@ -1,6 +1,6 @@
project(PortableRuntime)
-# Portable version of the runtime is designed to be used with CppCodeGen only.
+# Portable version of the runtime is designed to be used with CppCodeGen or WASM.
# It should be written in pure C/C++, with no assembly code.
include_directories(..)
@@ -34,6 +34,7 @@ add_custom_command(
# Install the static Runtime library
install (TARGETS PortableRuntime DESTINATION sdk)
+
if(WIN32)
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/PortableRuntime.dir/$<CONFIG>/PortableRuntime.pdb DESTINATION sdk)
endif()
diff --git a/src/Native/Runtime/RHCodeMan.cpp b/src/Native/Runtime/RHCodeMan.cpp
index b6a173bb2..054287fc4 100644
--- a/src/Native/Runtime/RHCodeMan.cpp
+++ b/src/Native/Runtime/RHCodeMan.cpp
@@ -891,7 +891,7 @@ bool EECodeManager::UnwindStackFrame(GCInfoHeader * pInfoHeader,
{
CalleeSavedRegMask regMask = pInfoHeader->GetSavedRegs();
ASSERT_MSG(ebpFrame || !(regMask & CSR_MASK_RBP), "We should never use EBP as a preserved register");
- ASSERT_MSG(!(regMask & CSR_MASK_RBX) || !pInfoHeader->HasDynamicAlignment(), "Can't have EBX as preserved regster and dynamic alignment frame pointer")
+ ASSERT_MSG(!(regMask & CSR_MASK_RBX) || !pInfoHeader->HasDynamicAlignment(), "Can't have EBX as preserved register and dynamic alignment frame pointer")
if (regMask & CSR_MASK_RBX) { pContext->pRbx = (PTR_UIntNative)((PTR_UInt8)RSP - registerSaveDisplacement); ++RSP; } // registers saved at bottom of frame
if (regMask & CSR_MASK_RSI) { pContext->pRsi = (PTR_UIntNative)((PTR_UInt8)RSP - registerSaveDisplacement); ++RSP; } // registers saved at bottom of frame
if (regMask & CSR_MASK_RDI) { pContext->pRdi = (PTR_UIntNative)((PTR_UInt8)RSP - registerSaveDisplacement); ++RSP; } // registers saved at bottom of frame
@@ -1064,10 +1064,9 @@ bool EECodeManager::UnwindStackFrame(GCInfoHeader * pInfoHeader,
// The compiler enforces that by placing an 8-byte padding between those areas if needed.
// Account for that padding and ensure that the unwound SP is 16-byte aligned.
RSP = dac_cast<PTR_UIntNative>((dac_cast<TADDR>(RSP) + 0xf) & ~0xf);
-#else
-
-#error NYI - For this arch
+#else
+#error Unexpected target architecture
#endif
pContext->SetSP((UIntNative) dac_cast<TADDR>(RSP));
@@ -1135,7 +1134,7 @@ UIntNative EECodeManager::GetConservativeUpperBoundForOutgoingArgs(GCInfoHeader
upperBound = pContext->GetFP() - pInfoHeader->GetFramePointerOffset();
#else
-#error NYI - For this arch
+#error Unexpected target architecture
#endif
}
else
@@ -1145,21 +1144,15 @@ UIntNative EECodeManager::GetConservativeUpperBoundForOutgoingArgs(GCInfoHeader
// Adding the frame size to the SP is guaranteed to yield an address above all outgoing
// arguments.
//
- // If this frame contains one or more callee-saved register (guaranteed on ARM since at
+ // If this frame contains one or more callee-saved register (guaranteed on ARM/ARM64 since at
// least LR is saved in all functions that contain callsites), then the computed address
// will point at the lowest callee-saved register (or possibly above it in the x86 case
// where registers are saved at the bottom of the frame).
//
- // If the frame contains no callee-saved registers (impossible on ARM), then the computed
+ // If the frame contains no callee-saved registers (impossible on ARM/ARM64), then the computed
// address will point to the pushed return address.
upperBound = pContext->GetSP() + pInfoHeader->GetFrameSize();
-
-#if defined(_TARGET_ARM_)
- ASSERT(pInfoHeader->GetSavedRegs() != 0);
-#elif defined(_TARGET_ARM64_)
- PORTABILITY_ASSERT("@TODO: FIXME:ARM64");
-#endif
}
}
@@ -1200,37 +1193,24 @@ PTR_PTR_VOID EECodeManager::GetReturnAddressLocationForHijack(
}
#ifdef _ARM_
- // We cannot get the return address unless LR has
- // be saved in the prolog.
+ // We cannot get the return address unless LR has been saved in the prolog.
if (!pHeader->IsRegSaved(CSR_MASK_LR))
return NULL;
#elif defined(_ARM64_)
- // We can get return address if LR was saved either with FP or on its own:
- bool ebpFrame = pHeader->HasFramePointer();
- if (!ebpFrame && !pHeader->IsRegSaved(CSR_MASK_LR)) {
+ // We can get return address if LR was saved either with FP or on its own.
+ if (!pHeader->HasFramePointer() && !pHeader->IsRegSaved(CSR_MASK_LR))
return NULL;
- }
#endif // _ARM_
- void ** ppvResult;
-
UInt32 epilogOffset = 0;
UInt32 epilogSize = 0;
if (GetEpilogOffset(pGCInfoHeader, cbMethodCodeSize, pbEpilogTable, codeOffset, &epilogOffset, &epilogSize))
{
-#ifdef _ARM_
- // Disable hijacking from epilogs on ARM until we implement GetReturnAddressLocationFromEpilog.
- return NULL;
-#elif defined(_ARM64_)
- // Disable hijacking from epilogs on ARM64:
+#if defined(_ARM_) || defined(_ARM64_)
+ // Disable hijacking from epilogs until we implement GetReturnAddressLocationFromEpilog.
return NULL;
#else
- ppvResult = GetReturnAddressLocationFromEpilog(pHeader, pContext, epilogOffset, epilogSize);
- // Early out if GetReturnAddressLocationFromEpilog indicates a non-hijackable epilog (e.g. exception
- // throw epilog or tail call).
- if (ppvResult == NULL)
- return NULL;
- goto Finished;
+ return GetReturnAddressLocationFromEpilog(pHeader, pContext, epilogOffset, epilogSize);
#endif
}
@@ -1238,11 +1218,7 @@ PTR_PTR_VOID EECodeManager::GetReturnAddressLocationForHijack(
// ARM always sets up R11 as an OS frame chain pointer to enable fast ETW stack walking (except in the
// case where LR is not pushed, but that was handled above). The protocol specifies that the return
// address is pushed at [r11, #4].
- ppvResult = (void **)((*pContext->pR11) + sizeof(void *));
- goto Finished;
-#elif _ARM64_
- ppvResult = (void **)(pContext->pLR);
- goto Finished;
+ return (void **)((*pContext->pR11) + sizeof(void *));
#else
// We are in the body of the method, so just find the return address using the unwind info.
@@ -1254,8 +1230,7 @@ PTR_PTR_VOID EECodeManager::GetReturnAddressLocationForHijack(
// In this case, we have the normal EBP frame pointer, but also an EBX frame pointer. Use the EBX
// one, because the return address associated with that frame pointer is the one we're actually
// going to return to. The other one (next to EBP) is only for EBP-chain-walking.
- ppvResult = (void **)((*pContext->pRbx) + sizeof(void *));
- goto Finished;
+ return (void **)((*pContext->pRbx) + sizeof(void *));
}
#endif
@@ -1263,25 +1238,24 @@ PTR_PTR_VOID EECodeManager::GetReturnAddressLocationForHijack(
#ifdef _AMD64_
framePointerOffset = pHeader->GetFramePointerOffset();
#endif
- ppvResult = (void **)((*pContext->pRbp) + sizeof(void *) - framePointerOffset);
- goto Finished;
+ return (void **)(pContext->GetFP() + sizeof(void *) - framePointerOffset);
}
{
// We do not have a frame pointer, but we are also not in the prolog or epilog
- UInt8 * RSP = (UInt8 *)pContext->GetSP();
- RSP += pHeader->GetFrameSize();
+ UIntNative RSP = pContext->GetSP() + pHeader->GetFrameSize();
+#if _ARM64_
+ // LR is saved at the bottom of the preserved registers area
+ ASSERT(pHeader->IsRegSaved(CSR_MASK_LR));
+#else
RSP += pHeader->GetPreservedRegsSaveSize();
+#endif
// RSP should point to the return address now.
- ppvResult = (void**)RSP;
+ return (void**)RSP;
}
- goto Finished;
#endif
-
- Finished:
- return ppvResult;
}
#endif
@@ -1350,6 +1324,9 @@ bool EECodeManager::GetEpilogOffset(
#ifndef DACCESS_COMPILE
+// ARM64 epilogs have a window between loading the hijackable return address into LR and the RET instruction.
+// We cannot hijack or unhijack a thread while it is suspended in that window unless we implement hijacking
+// via LR register modification.
void ** EECodeManager::GetReturnAddressLocationFromEpilog(GCInfoHeader * pInfoHeader, REGDISPLAY * pContext,
UInt32 epilogOffset, UInt32 epilogSize)
{
diff --git a/src/Native/Runtime/RhConfig.cpp b/src/Native/Runtime/RhConfig.cpp
index f1879ab10..fb8575407 100644
--- a/src/Native/Runtime/RhConfig.cpp
+++ b/src/Native/Runtime/RhConfig.cpp
@@ -34,14 +34,20 @@ UInt32 RhConfig::ReadConfigValue(_In_z_ const TCHAR *wszName, UInt32 uiDefaultVa
UInt32 cchResult = 0;
-#ifdef RH_ENVIRONMENT_VARIABLE_CONFIG_ENABLED
+#ifdef FEATURE_ENVIRONMENT_VARIABLE_CONFIG
cchResult = PalGetEnvironmentVariable(wszName, wszBuffer, cchBuffer);
-#endif // RH_ENVIRONMENT_VARIABLE_CONFIG_ENABLED
+#endif // FEATURE_ENVIRONMENT_VARIABLE_CONFIG
//if the config key wasn't found in the environment
if ((cchResult == 0) || (cchResult >= cchBuffer))
cchResult = GetIniVariable(wszName, wszBuffer, cchBuffer);
+#ifdef FEATURE_EMBEDDED_CONFIG
+ // if the config key wasn't found in the ini file
+ if ((cchResult == 0) || (cchResult >= cchBuffer))
+ cchResult = GetEmbeddedVariable(wszName, wszBuffer, cchBuffer);
+#endif // FEATURE_EMBEDDED_CONFIG
+
if ((cchResult == 0) || (cchResult >= cchBuffer))
return uiDefaultValue; // not found, return default
@@ -90,10 +96,40 @@ UInt32 RhConfig::GetIniVariable(_In_z_ const TCHAR* configName, _Out_writes_all_
return 0;
}
+ return GetConfigVariable(configName, (ConfigPair*)g_iniSettings, outputBuffer, cchOutputBuffer);
+}
+
+#ifdef FEATURE_EMBEDDED_CONFIG
+UInt32 RhConfig::GetEmbeddedVariable(_In_z_ const TCHAR* configName, _Out_writes_all_(cchOutputBuffer) TCHAR* outputBuffer, _In_ UInt32 cchOutputBuffer)
+{
+ //the buffer needs to be big enough to read the value buffer + null terminator
+ if (cchOutputBuffer < CONFIG_VAL_MAXLEN + 1)
+ {
+ return 0;
+ }
+
+ //if we haven't read the config yet try to read
+ if (g_embeddedSettings == NULL)
+ {
+ ReadEmbeddedSettings();
+ }
+
+ //if the config wasn't read or reading failed return 0 immediately
+ if (g_embeddedSettings == CONFIG_INI_NOT_AVAIL)
+ {
+ return 0;
+ }
+
+ return GetConfigVariable(configName, (ConfigPair*)g_embeddedSettings, outputBuffer, cchOutputBuffer);
+}
+#endif // FEATURE_EMBEDDED_CONFIG
+
+UInt32 RhConfig::GetConfigVariable(_In_z_ const TCHAR* configName, const ConfigPair* configPairs, _Out_writes_all_(cchOutputBuffer) TCHAR* outputBuffer, _In_ UInt32 cchOutputBuffer)
+{
//find the first name which matches (case insensitive to be compat with environment variable counterpart)
for (int iSettings = 0; iSettings < RCV_Count; iSettings++)
{
- if (_tcsicmp(configName, ((ConfigPair*)g_iniSettings)[iSettings].Key) == 0)
+ if (_tcsicmp(configName, configPairs[iSettings].Key) == 0)
{
bool nullTerm = FALSE;
@@ -101,7 +137,7 @@ UInt32 RhConfig::GetIniVariable(_In_z_ const TCHAR* configName, _Out_writes_all_
for (iValue = 0; (iValue < CONFIG_VAL_MAXLEN + 1) && (iValue < (Int32)cchOutputBuffer); iValue++)
{
- outputBuffer[iValue] = ((ConfigPair*)g_iniSettings)[iSettings].Value[iValue];
+ outputBuffer[iValue] = configPairs[iSettings].Value[iValue];
if (outputBuffer[iValue] == '\0')
{
@@ -218,6 +254,81 @@ void RhConfig::ReadConfigIni()
return;
}
+#ifdef FEATURE_EMBEDDED_CONFIG
+struct CompilerEmbeddedSettingsBlob
+{
+ UInt32 Size;
+ char Data[1];
+};
+
+extern "C" CompilerEmbeddedSettingsBlob g_compilerEmbeddedSettingsBlob;
+
+void RhConfig::ReadEmbeddedSettings()
+{
+ if (g_embeddedSettings == NULL)
+ {
+ //if reading the file contents failed set g_embeddedSettings to CONFIG_INI_NOT_AVAIL
+ if (g_compilerEmbeddedSettingsBlob.Size == 0)
+ {
+ //only set if another thread hasn't initialized the buffer yet, otherwise ignore and let the first setter win
+ PalInterlockedCompareExchangePointer(&g_embeddedSettings, CONFIG_INI_NOT_AVAIL, NULL);
+
+ return;
+ }
+
+ ConfigPair* iniBuff = new (nothrow) ConfigPair[RCV_Count];
+ if (iniBuff == NULL)
+ {
+ //only set if another thread hasn't initialized the buffer yet, otherwise ignore and let the first setter win
+ PalInterlockedCompareExchangePointer(&g_embeddedSettings, CONFIG_INI_NOT_AVAIL, NULL);
+
+ return;
+ }
+
+ UInt32 iBuff = 0;
+ UInt32 iIniBuff = 0;
+ char* currLine;
+
+ //while we haven't reached the max number of config pairs, or the end of the file, read the next line
+ while (iIniBuff < RCV_Count && iBuff < g_compilerEmbeddedSettingsBlob.Size)
+ {
+ currLine = &g_compilerEmbeddedSettingsBlob.Data[iBuff];
+
+ //find the end of the line
+ while ((g_compilerEmbeddedSettingsBlob.Data[iBuff] != '\0') && (iBuff < g_compilerEmbeddedSettingsBlob.Size))
+ iBuff++;
+
+ //parse the line
+ //only increment iIniBuff if the parsing succeeded otherwise reuse the config struct
+ if (ParseConfigLine(&iniBuff[iIniBuff], currLine))
+ {
+ iIniBuff++;
+ }
+
+ //advance to the next line;
+ iBuff++;
+ }
+
+ //initialize the remaining config pairs to "\0"
+ while (iIniBuff < RCV_Count)
+ {
+ iniBuff[iIniBuff].Key[0] = '\0';
+ iniBuff[iIniBuff].Value[0] = '\0';
+ iIniBuff++;
+ }
+
+ //if another thread initialized first let the first setter win
+ //delete the iniBuff to avoid leaking memory
+ if (PalInterlockedCompareExchangePointer(&g_embeddedSettings, iniBuff, NULL) != NULL)
+ {
+ delete[] iniBuff;
+ }
+ }
+
+ return;
+}
+#endif // FEATURE_EMBEDDED_CONFIG
+
//returns the path to the runtime configuration ini
_Ret_maybenull_z_ TCHAR* RhConfig::GetConfigPath()
{
diff --git a/src/Native/Runtime/RhConfig.h b/src/Native/Runtime/RhConfig.h
index 677d97516..b5879c386 100644
--- a/src/Native/Runtime/RhConfig.h
+++ b/src/Native/Runtime/RhConfig.h
@@ -21,7 +21,7 @@
#ifndef DACCESS_COMPILE
#if defined(_DEBUG) || !defined(APP_LOCAL_RUNTIME)
-#define RH_ENVIRONMENT_VARIABLE_CONFIG_ENABLED
+#define FEATURE_ENVIRONMENT_VARIABLE_CONFIG
#endif
class RhConfig
@@ -53,6 +53,12 @@ private:
private:
void* volatile g_iniSettings = NULL;
+#ifdef FEATURE_EMBEDDED_CONFIG
+ // g_embeddedSettings works similarly to g_iniSettings, except the source of the data
+ // is a data blob generated by the compiler and embedded into the executable.
+ void* volatile g_embeddedSettings = NULL;
+#endif // FEATURE_EMBEDDED_CONFIG
+
public:
#define DEFINE_VALUE_ACCESSOR(_name, defaultVal) \
@@ -123,6 +129,14 @@ private:
//cchOutputBuffer is the maximum number of characters to write to outputBuffer
UInt32 GetIniVariable(_In_z_ const TCHAR* configName, _Out_writes_all_(cchOutputBuffer) TCHAR* outputBuffer, _In_ UInt32 cchOutputBuffer);
+#ifdef FEATURE_EMBEDDED_CONFIG
+ void ReadEmbeddedSettings();
+
+ UInt32 GetEmbeddedVariable(_In_z_ const TCHAR* configName, _Out_writes_all_(cchOutputBuffer) TCHAR* outputBuffer, _In_ UInt32 cchOutputBuffer);
+#endif // FEATURE_EMBEDDED_CONFIG
+
+ UInt32 GetConfigVariable(_In_z_ const TCHAR* configName, const ConfigPair* configPairs, _Out_writes_all_(cchOutputBuffer) TCHAR* outputBuffer, _In_ UInt32 cchOutputBuffer);
+
static bool priv_isspace(char c)
{
return (c == ' ') || (c == '\t') || (c == '\n') || (c == '\r');
diff --git a/src/Native/Runtime/RuntimeInstance.cpp b/src/Native/Runtime/RuntimeInstance.cpp
index d2efcf3bd..0f1db5c64 100644
--- a/src/Native/Runtime/RuntimeInstance.cpp
+++ b/src/Native/Runtime/RuntimeInstance.cpp
@@ -349,8 +349,6 @@ Module * RuntimeInstance::FindModuleByOsHandle(HANDLE hOsHandle)
RuntimeInstance::RuntimeInstance() :
m_pThreadStore(NULL),
- m_fStandaloneExeMode(false),
- m_pStandaloneExeModule(NULL),
m_pStaticGCRefsDescChunkList(NULL),
m_pThreadStaticGCRefsDescChunkList(NULL),
m_pGenericUnificationHashtable(NULL),
@@ -382,13 +380,6 @@ EXTERN_C void REDHAWK_CALLCONV RhpSetHaveNewClasslibs();
bool RuntimeInstance::RegisterModule(ModuleHeader *pModuleHeader)
{
- // Determine whether we're in standalone exe mode. If we are we'll see the runtime module load followed by
- // exactly one additional module (the exe itself). The exe module will have a standalone flag set in its
- // header.
- ASSERT(m_fStandaloneExeMode == false);
- if (pModuleHeader->Flags & ModuleHeader::StandaloneExe)
- m_fStandaloneExeMode = true;
-
CreateHolder<Module> pModule = Module::Create(pModuleHeader);
if (NULL == pModule)
@@ -401,9 +392,6 @@ bool RuntimeInstance::RegisterModule(ModuleHeader *pModuleHeader)
m_ModuleList.PushHead(pModule);
}
- if (m_fStandaloneExeMode)
- m_pStandaloneExeModule = pModule;
-
if (pModule->IsClasslibModule())
RhpSetHaveNewClasslibs();
diff --git a/src/Native/Runtime/RuntimeInstance.h b/src/Native/Runtime/RuntimeInstance.h
index 5bbc09651..2b49bfd90 100644
--- a/src/Native/Runtime/RuntimeInstance.h
+++ b/src/Native/Runtime/RuntimeInstance.h
@@ -66,14 +66,6 @@ public:
private:
TypeManagerList m_TypeManagerList;
- // Indicates whether the runtime is in standalone exe mode where the only Redhawk module that will be
- // loaded into the process (besides the runtime's own module) is the exe itself. This flag will be
- // correctly initialized once the exe module has loaded.
- bool m_fStandaloneExeMode;
-
- // If m_fStandaloneExeMode is set this contains a pointer to the exe module. Otherwise it's null.
- Module * m_pStandaloneExeModule;
-
#ifdef FEATURE_PROFILING
// The thread writing the profile data is created lazily, whenever
// a module with a profile section is registered.
@@ -236,16 +228,6 @@ public:
void WriteProfileInfo();
#endif // FEATURE_PROFILING
- bool IsInStandaloneExeMode()
- {
- return m_fStandaloneExeMode;
- }
-
- Module * GetStandaloneExeModule()
- {
- ASSERT(IsInStandaloneExeMode());
- return m_pStandaloneExeModule;
- }
};
typedef DPTR(RuntimeInstance) PTR_RuntimeInstance;
diff --git a/src/Native/Runtime/amd64/ExceptionHandling.S b/src/Native/Runtime/amd64/ExceptionHandling.S
index fcf4dfbda..fa80c26ad 100644
--- a/src/Native/Runtime/amd64/ExceptionHandling.S
+++ b/src/Native/Runtime/amd64/ExceptionHandling.S
@@ -207,6 +207,7 @@ NESTED_ENTRY RhpRethrow, _TEXT, NoHandler
mov [rsi + OFFSETOF__ExInfo__m_exception], rdx // init the exception object to null
mov byte ptr [rsi + OFFSETOF__ExInfo__m_passNumber], 1 // init to the first pass
mov dword ptr [rsi + OFFSETOF__ExInfo__m_idxCurClause], 0xFFFFFFFF
+ mov byte ptr [rsi + OFFSETOF__ExInfo__m_kind], 0 // init to a deterministic value (ExKind.None)
// link the ExInfo into the thread's ExInfo chain
diff --git a/src/Native/Runtime/amd64/ExceptionHandling.asm b/src/Native/Runtime/amd64/ExceptionHandling.asm
index 566dad71f..b8727fc84 100644
--- a/src/Native/Runtime/amd64/ExceptionHandling.asm
+++ b/src/Native/Runtime/amd64/ExceptionHandling.asm
@@ -254,6 +254,7 @@ NESTED_ENTRY RhpRethrow, _TEXT
mov [rdx + OFFSETOF__ExInfo__m_exception], r8 ;; init the exception object to null
mov byte ptr [rdx + OFFSETOF__ExInfo__m_passNumber], 1 ;; init to the first pass
mov dword ptr [rdx + OFFSETOF__ExInfo__m_idxCurClause], 0FFFFFFFFh
+ mov byte ptr [rdx + OFFSETOF__ExInfo__m_kind], 0 ;; init to a deterministic value (ExKind.None)
;; link the ExInfo into the thread's ExInfo chain
diff --git a/src/Native/Runtime/arm/AllocFast.S b/src/Native/Runtime/arm/AllocFast.S
index e4dd26643..ec9260855 100644
--- a/src/Native/Runtime/arm/AllocFast.S
+++ b/src/Native/Runtime/arm/AllocFast.S
@@ -469,7 +469,7 @@ LOCAL_LABEL(BoxAlloc8Failed):
// finalization.
mov r0, r4 // restore EEType
mov r1, #(GC_ALLOC_ALIGN8 | GC_ALLOC_ALIGN8_BIAS)
- EPILOG_POP "{r4,pc}"
+ EPILOG_POP "{r4,lr}"
b C_FUNC(RhpNewObject)
LEAF_END RhpNewFastMisalign, _TEXT
diff --git a/src/Native/Runtime/arm/ExceptionHandling.S b/src/Native/Runtime/arm/ExceptionHandling.S
index 2732282e8..3037905be 100644
--- a/src/Native/Runtime/arm/ExceptionHandling.S
+++ b/src/Native/Runtime/arm/ExceptionHandling.S
@@ -109,7 +109,7 @@ NESTED_ENTRY RhpThrowEx, _TEXT, NoHandler
// where the tail-calling thread had saved LR, which may not match where we have saved LR.
ldr r1, [r0, #OFFSETOF__Thread__m_pvHijackedReturnAddress]
- cbz r1, LOCAL_LABEL(NotHijacked)
+ cbz r1, LOCAL_LABEL(NotHiJacked)
ldr r3, [r0, #OFFSETOF__Thread__m_ppvHijackedReturnAddressLocation]
@@ -206,6 +206,7 @@ NESTED_ENTRY RhpRethrow, _TEXT, NoHandler
mov r3, #0
str r3, [r1, #OFFSETOF__ExInfo__m_exception] // init the exception object to null
+ strb r3, [r1, #OFFSETOF__ExInfo__m_kind] // init to a deterministic value (ExKind.None)
mov r3, #0xFFFFFFFF
str r3, [r1, #OFFSETOF__ExInfo__m_idxCurClause]
diff --git a/src/Native/Runtime/arm/ExceptionHandling.asm b/src/Native/Runtime/arm/ExceptionHandling.asm
index bf21df089..39c29992a 100644
--- a/src/Native/Runtime/arm/ExceptionHandling.asm
+++ b/src/Native/Runtime/arm/ExceptionHandling.asm
@@ -211,6 +211,7 @@ NotHijacked
add r1, sp, #rsp_offsetof_ExInfo ;; r1 <- ExInfo*
mov r3, #0
str r3, [r1, #OFFSETOF__ExInfo__m_exception] ;; pExInfo->m_exception = null
+ strb r3, [r1, #OFFSETOF__ExInfo__m_kind] ;; init to a deterministic value (ExKind.None)
mov r3, #1
strb r3, [r1, #OFFSETOF__ExInfo__m_passNumber] ;; pExInfo->m_passNumber = 1
mov r3, #0xFFFFFFFF
diff --git a/src/Native/Runtime/arm64/CallingConventionConverterHelpers.asm b/src/Native/Runtime/arm64/CallingConventionConverterHelpers.asm
index 2d43d5bba..f60e11578 100644
--- a/src/Native/Runtime/arm64/CallingConventionConverterHelpers.asm
+++ b/src/Native/Runtime/arm64/CallingConventionConverterHelpers.asm
@@ -46,7 +46,7 @@ POINTER_SIZE equ 0x08
ldr xip0, [xip0, #POINTER_SIZE] ; get pointer to CallingConventionConverter_CommonCallingStub_PointerData into xip0
ldr x12, [xip0, #POINTER_SIZE] ; get address of UniversalTransitionThunk (which we'll tailcall to later)
ldr xip0, [xip0] ; get address of ManagedCallConverterThunk (target for universal thunk to call)
- ret x12
+ br x12
LEAF_END __jmpstub__CallingConventionConverter_CommonCallingStub
;;
diff --git a/src/Native/Runtime/arm64/ExceptionHandling.asm b/src/Native/Runtime/arm64/ExceptionHandling.asm
index e08118516..5a548279a 100644
--- a/src/Native/Runtime/arm64/ExceptionHandling.asm
+++ b/src/Native/Runtime/arm64/ExceptionHandling.asm
@@ -15,15 +15,16 @@
;; Macro used to create frame of exception throwing helpers (RhpThrowEx, RhpThrowHwEx)
MACRO
ALLOC_THROW_FRAME $exceptionType
-
- PROLOG_NOP mov x3, sp
+ PROLOG_NOP mov x3, sp
+
;; Setup a PAL_LIMITED_CONTEXT on the stack {
- PROLOG_STACK_ALLOC 0x50
IF $exceptionType == HARDWARE_EXCEPTION
+ PROLOG_NOP sub sp,sp,#0x50
PROLOG_NOP stp x3, x1, [sp] ; x3 is the SP and x1 is the IP of the fault site
PROLOG_PUSH_MACHINE_FRAME
ELSE
+ PROLOG_STACK_ALLOC 0x50
PROLOG_NOP stp x3, lr, [sp] ; x3 is the SP and lr is the IP of the fault site
ENDIF
PROLOG_NOP stp d8, d9, [sp, #0x10]
@@ -49,12 +50,18 @@
MACRO
ALLOC_CALL_FUNCLET_FRAME $extraStackSize
- PROLOG_SAVE_REG_PAIR fp, lr, #-0x60!
+ ; Using below prolog instead of PROLOG_SAVE_REG_PAIR fp,lr, #-60!
+ ; is intentional. Above statement would also emit instruction to save
+ ; sp in fp. If sp is saved in fp in prolog then it is not expected that fp can change in the body
+ ; of method. However, this method needs to be able to change fp before calling funclet.
+ ; This is required to access locals in funclet.
+ PROLOG_SAVE_REG_PAIR_NO_FP fp,lr, #-0x60!
PROLOG_SAVE_REG_PAIR x19, x20, #0x10
PROLOG_SAVE_REG_PAIR x21, x22, #0x20
PROLOG_SAVE_REG_PAIR x23, x24, #0x30
PROLOG_SAVE_REG_PAIR x25, x26, #0x40
PROLOG_SAVE_REG_PAIR x27, x28, #0x50
+ PROLOG_NOP mov fp, sp
IF $extraStackSize != 0
PROLOG_STACK_ALLOC $extraStackSize
@@ -353,6 +360,7 @@ NotHijacked
add x1, sp, #rsp_offsetof_ExInfo ;; x1 <- ExInfo*
str xzr, [x1, #OFFSETOF__ExInfo__m_exception] ;; pExInfo->m_exception = null
+ strb wzr, [x1, #OFFSETOF__ExInfo__m_kind] ;; init to a deterministic value (ExKind.None)
mov w3, #1
strb w3, [x1, #OFFSETOF__ExInfo__m_passNumber] ;; pExInfo->m_passNumber = 1
mov w3, #0xFFFFFFFF
@@ -482,7 +490,7 @@ DonePopping
NoAbort
;; reset SP and jump to continuation address
mov sp, x2
- ret x0
+ br x0
NESTED_END RhpCallCatchFunclet
diff --git a/src/Native/Runtime/arm64/GcProbe.asm b/src/Native/Runtime/arm64/GcProbe.asm
index 051b4158d..73d674a5c 100644
--- a/src/Native/Runtime/arm64/GcProbe.asm
+++ b/src/Native/Runtime/arm64/GcProbe.asm
@@ -48,7 +48,7 @@ PROBE_FRAME_SIZE field 0
;; Perform the parts of setting up a probe frame that can occur during the prolog (and indeed this macro
;; can only be called from within the prolog).
MACRO
- ALLOC_PROBE_FRAME $extraStackSpace
+ ALLOC_PROBE_FRAME $extraStackSpace, $saveFPRegisters
;; First create PInvokeTransitionFrame
PROLOG_SAVE_REG_PAIR fp, lr, #-(PROBE_FRAME_SIZE + $extraStackSpace)! ;; Push down stack pointer and store FP and LR
@@ -80,16 +80,18 @@ PROBE_FRAME_SIZE field 0
;; Slot at [sp, #0x118] is reserved for NZCV
- ; Save the floating return registers
- PROLOG_NOP stp d0, d1, [sp, #0x120]
- PROLOG_NOP stp d2, d3, [sp, #0x130]
+ ;; Save the floating return registers
+ IF $saveFPRegisters
+ PROLOG_NOP stp d0, d1, [sp, #0x120]
+ PROLOG_NOP stp d2, d3, [sp, #0x130]
+ ENDIF
MEND
;; Undo the effects of an ALLOC_PROBE_FRAME. This may only be called within an epilog. Note that all
;; registers are restored (apart for sp and pc), even volatiles.
MACRO
- FREE_PROBE_FRAME $extraStackSpace
+ FREE_PROBE_FRAME $extraStackSpace, $restoreFPRegisters
;; Restore the scratch registers
PROLOG_NOP ldr x0, [sp, #0x78]
@@ -105,8 +107,10 @@ PROBE_FRAME_SIZE field 0
PROLOG_NOP ldr lr, [sp, #0x110]
; Restore the floating return registers
- EPILOG_NOP ldp d0, d1, [sp, #0x120]
- EPILOG_NOP ldp d2, d3, [sp, #0x130]
+ IF $restoreFPRegisters
+ EPILOG_NOP ldp d0, d1, [sp, #0x120]
+ EPILOG_NOP ldp d2, d3, [sp, #0x130]
+ ENDIF
;; Restore callee saved registers
EPILOG_RESTORE_REG_PAIR x19, x20, #0x20
@@ -167,7 +171,7 @@ __PPF_ThreadReg SETS "$threadReg"
; Define the method prolog, allocating enough stack space for the PInvokeTransitionFrame and saving
; incoming register values into it.
- ALLOC_PROBE_FRAME 0
+ ALLOC_PROBE_FRAME 0, {true}
; If the caller didn't provide a value for $threadReg then generate code to fetch the Thread* into x2.
; Record that x2 holds the Thread* in our local variable.
@@ -188,58 +192,64 @@ __PPF_ThreadReg SETS "x2"
MACRO
EPILOG_PROBE_FRAME
- FREE_PROBE_FRAME 0
+ FREE_PROBE_FRAME 0, {true}
EPILOG_RETURN
MEND
-;; ALLOC_PROBE_FRAME will save the first 4 vfp registers, in order to avoid trashing VFP registers across the loop
-;; hijack, we must save the rest -- d4-d31 (28).
-EXTRA_SAVE_SIZE equ (28*8)
+;; In order to avoid trashing VFP registers across the loop hijack we must save all user registers, so that
+;; registers used by the loop being hijacked will not be affected. Unlike ARM32 where neon registers (NQ0, ..., NQ15)
+;; are fully covered by the floating point registers D0 ... D31, we have 32 neon registers Q0, ... Q31 on ARM64
+;; which are not fully covered by the register D0 ... D31. Therefore we must explicitly save all Q registers.
+EXTRA_SAVE_SIZE equ (32*16)
MACRO
ALLOC_LOOP_HIJACK_FRAME
PROLOG_STACK_ALLOC EXTRA_SAVE_SIZE
-;; save VFP registers that were not saved by the ALLOC_PROBE_FRAME
- PROLOG_NOP stp d4, d5, [sp]
- PROLOG_NOP stp d6, d7, [sp, #0x10]
- PROLOG_NOP stp d8, d9, [sp, #0x20]
- PROLOG_NOP stp d10, d11, [sp, #0x30]
- PROLOG_NOP stp d12, d13, [sp, #0x40]
- PROLOG_NOP stp d14, d15, [sp, #0x50]
- PROLOG_NOP stp d16, d17, [sp, #0x60]
- PROLOG_NOP stp d18, d19, [sp, #0x70]
- PROLOG_NOP stp d20, d21, [sp, #0x80]
- PROLOG_NOP stp d22, d23, [sp, #0x90]
- PROLOG_NOP stp d24, d25, [sp, #0xA0]
- PROLOG_NOP stp d26, d27, [sp, #0xB0]
- PROLOG_NOP stp d28, d29, [sp, #0xC0]
- PROLOG_NOP stp d30, d31, [sp, #0xD0]
-
- ALLOC_PROBE_FRAME 0
+ ;; Save all neon registers
+ PROLOG_NOP stp q0, q1, [sp]
+ PROLOG_NOP stp q2, q3, [sp, #0x20]
+ PROLOG_NOP stp q4, q5, [sp, #0x40]
+ PROLOG_NOP stp q6, q7, [sp, #0x60]
+ PROLOG_NOP stp q8, q9, [sp, #0x80]
+ PROLOG_NOP stp q10, q11, [sp, #0xA0]
+ PROLOG_NOP stp q12, q13, [sp, #0xC0]
+ PROLOG_NOP stp q14, q15, [sp, #0xE0]
+ PROLOG_NOP stp q16, q17, [sp, #0x100]
+ PROLOG_NOP stp q18, q19, [sp, #0x120]
+ PROLOG_NOP stp q20, q21, [sp, #0x140]
+ PROLOG_NOP stp q22, q23, [sp, #0x160]
+ PROLOG_NOP stp q24, q25, [sp, #0x180]
+ PROLOG_NOP stp q26, q27, [sp, #0x1A0]
+ PROLOG_NOP stp q28, q29, [sp, #0x1C0]
+ PROLOG_NOP stp q30, q31, [sp, #0x1E0]
+
+ ALLOC_PROBE_FRAME 0, {false}
MEND
MACRO
FREE_LOOP_HIJACK_FRAME
- FREE_PROBE_FRAME 0
-
-;; restore VFP registers that will not be restored by the FREE_PROBE_FRAME
- PROLOG_NOP ldp d4, d5, [sp]
- PROLOG_NOP ldp d6, d7, [sp, #0x10]
- PROLOG_NOP ldp d8, d9, [sp, #0x20]
- PROLOG_NOP ldp d10, d11, [sp, #0x30]
- PROLOG_NOP ldp d12, d13, [sp, #0x40]
- PROLOG_NOP ldp d14, d15, [sp, #0x50]
- PROLOG_NOP ldp d16, d17, [sp, #0x60]
- PROLOG_NOP ldp d18, d19, [sp, #0x70]
- PROLOG_NOP ldp d20, d21, [sp, #0x80]
- PROLOG_NOP ldp d22, d23, [sp, #0x90]
- PROLOG_NOP ldp d24, d25, [sp, #0xA0]
- PROLOG_NOP ldp d26, d27, [sp, #0xB0]
- PROLOG_NOP ldp d28, d29, [sp, #0xC0]
- PROLOG_NOP ldp d30, d31, [sp, #0xD0]
+ FREE_PROBE_FRAME 0, {false}
+
+ ;; restore all neon registers
+ PROLOG_NOP ldp q0, q1, [sp]
+ PROLOG_NOP ldp q2, q3, [sp, #0x20]
+ PROLOG_NOP ldp q4, q5, [sp, #0x40]
+ PROLOG_NOP ldp q6, q7, [sp, #0x60]
+ PROLOG_NOP ldp q8, q9, [sp, #0x80]
+ PROLOG_NOP ldp q10, q11, [sp, #0xA0]
+ PROLOG_NOP ldp q12, q13, [sp, #0xC0]
+ PROLOG_NOP ldp q14, q15, [sp, #0xE0]
+ PROLOG_NOP ldp q16, q17, [sp, #0x100]
+ PROLOG_NOP ldp q18, q19, [sp, #0x120]
+ PROLOG_NOP ldp q20, q21, [sp, #0x140]
+ PROLOG_NOP ldp q22, q23, [sp, #0x160]
+ PROLOG_NOP ldp q24, q25, [sp, #0x180]
+ PROLOG_NOP ldp q26, q27, [sp, #0x1A0]
+ PROLOG_NOP ldp q28, q29, [sp, #0x1C0]
+ PROLOG_NOP ldp q30, q31, [sp, #0x1E0]
EPILOG_STACK_FREE EXTRA_SAVE_SIZE
MEND
@@ -311,7 +321,7 @@ EXTRA_SAVE_SIZE equ (28*8)
tst w2, #TSF_SuppressGcStress__OR__TSF_DoNotTriggerGC
bne %ft0
- ldr x2, [x4, #OFFSETOF__Thread__m_pHackPInvokeTunnel]
+ ldr x9, [x4, #OFFSETOF__Thread__m_pHackPInvokeTunnel]
bl RhpWaitForGCNoAbort
0
MEND
@@ -383,7 +393,6 @@ EXTRA_SAVE_SIZE equ (28*8)
#endif ;; FEATURE_GC_STRESS
LEAF_ENTRY RhpGcProbe
- brk 0xf000 ;; TODO: remove after debugging/testing stub
ldr x3, =RhpTrapThreads
ldr w3, [x3]
tbnz x3, #TrapThreadsFlags_TrapThreads_Bit, RhpGcProbeRare
@@ -393,7 +402,6 @@ EXTRA_SAVE_SIZE equ (28*8)
EXTERN RhpThrowHwEx
NESTED_ENTRY RhpGcProbeRare
- brk 0xf000 ;; TODO: remove after debugging/testing stub
PROLOG_PROBE_FRAME x2, x3, x12,
mov x4, x2
@@ -405,7 +413,7 @@ EXTRA_SAVE_SIZE equ (28*8)
EPILOG_PROBE_FRAME
1
- FREE_PROBE_FRAME 0
+ FREE_PROBE_FRAME 0, {true}
EPILOG_NOP mov w0, #STATUS_REDHAWK_THREAD_ABORT
EPILOG_NOP mov x1, lr ;; return address as exception PC
EPILOG_NOP b RhpThrowHwEx
@@ -558,7 +566,7 @@ EXTRA_SAVE_SIZE equ (28*8)
EPILOG_RESTORE_REG_PAIR x27, x28, #0x60
EPILOG_NOP ldr x9, [sp, #0x78]
EPILOG_RESTORE_REG_PAIR fp, lr, #(SIZEOF__PAL_LIMITED_CONTEXT + 0x20)!
- EPILOG_NOP ret x9
+ EPILOG_NOP br x9
NESTED_END RhpHijackForGcStressLeaf
@@ -630,7 +638,7 @@ EXTRA_SAVE_SIZE equ (28*8)
EHJumpProbeProlog
PROLOG_NOP mov x0, x1 ; move the ex object reference into x0 so we can report it
- ALLOC_PROBE_FRAME 0x10
+ ALLOC_PROBE_FRAME 0x10, {true}
str x2, [sp, #PROBE_FRAME_SIZE]
;; x2 <- GetThread(), TRASHES x1
@@ -665,9 +673,9 @@ EXTRA_SAVE_SIZE equ (28*8)
EHJumpProbeEpilog
ldr x2, [sp, #PROBE_FRAME_SIZE]
- FREE_PROBE_FRAME 0x10 ; This restores exception object back into x0
+ FREE_PROBE_FRAME 0x10, {true} ; This restores exception object back into x0
EPILOG_NOP mov x1, x0 ; Move the Exception object back into x1 where the catch handler expects it
- EPILOG_NOP ret x2
+ EPILOG_NOP br x2
MEND
;;
@@ -825,7 +833,7 @@ Success
NoGcStress
#endif ;; FEATURE_GC_STRESS
- add x2, sp, xzr ; sp is address of PInvokeTransitionFrame
+ mov x9, sp ; sp is address of PInvokeTransitionFrame
bl RhpWaitForGCNoAbort
DoneWaitingForGc
@@ -839,7 +847,7 @@ DoneWaitingForGc
EPILOG_NOP ldr x1, [sp, #8] ; hijack target address
EPILOG_STACK_FREE 0x10
- EPILOG_NOP ret x1 ; jump to the hijack target
+ EPILOG_NOP br x1 ; jump to the hijack target
Abort
FREE_LOOP_HIJACK_FRAME
@@ -852,4 +860,123 @@ Abort
INLINE_GETTHREAD_CONSTANT_POOL
+;; Trap to GC.
+;; Set up the P/Invoke transition frame with the return address as the safe point.
+;; All registers, both volatile and non-volatile, are preserved.
+;; The function should be called not jumped because it's expecting the return address
+ NESTED_ENTRY RhpTrapToGC, _TEXT
+;;
+ ;; What we want to get to:
+ ;;
+ ;; [sp + ] -> m_FramePointer -------|
+ ;; [sp + 8] -> m_RIP |
+ ;; [sp + 10] -> m_pThread |
+ ;; [sp + 18] -> m_Flags / m_dwAlignPad2 |
+ ;; [sp + 20] -> x19 save |
+ ;; [sp + 28] -> x20 save |
+ ;; [sp + 30] -> x21 save |
+ ;; [sp + 38] -> x22 save |
+ ;; [sp + 40] -> x23 save |
+ ;; [sp + 48] -> x24 save | PInvokeTransitionFrame
+ ;; [sp + 50] -> x25 save |
+ ;; [sp + 58] -> x26 save |
+ ;; [sp + 60] -> x27 save |
+ ;; [sp + 68] -> x28 save |
+ ;; [sp + 70] -> sp save ;caller sp |
+ ;; [sp + 78] -> x0 save |
+ ;; [sp + 80] -> x1 save |
+ ;; [sp + 88] -> x2 save |
+ ;; [sp + 90] -> x3 save |
+ ;; [sp + 98] -> x4 save |
+ ;; [sp + a0] -> x5 save |
+ ;; [sp + a8] -> x6 save |
+ ;; [sp + b0] -> x7 save |
+ ;; [sp + b8] -> x8 save |
+ ;; [sp + c0] -> x9 save |
+ ;; [sp + c8] -> x10 save |
+ ;; [sp + d0] -> x11 save |
+ ;; [sp + d8] -> x12 save |
+ ;; [sp + e0] -> x13 save |
+ ;; [sp + e8] -> x14 save |
+ ;; [sp + f0] -> x15 save |
+ ;; [sp + f8] -> x16 save |
+ ;; [sp + 100] -> x17 save |
+ ;; [sp + 108] -> x18 save |
+ ;; [sp + 110] -> lr save -------|
+ ;;
+ ;; [sp + 118] -> NZCV
+ ;;
+ ;; [sp + 120] -> not used
+ ;; [sp + 140] -> q0 ... q31
+ ;;
+
+ ALLOC_LOOP_HIJACK_FRAME
+
+ ;; Slot at [sp, #0x118] is reserved for NZCV
+ mrs x1, NZCV
+ str x1, [sp, #m_SavedNZCV]
+
+ ;; x4 <- GetThread(), TRASHES x1
+ INLINE_GETTHREAD x4, x1
+ INIT_PROBE_FRAME x4, x1, #PROBE_SAVE_FLAGS_EVERYTHING, 0, (PROBE_FRAME_SIZE + EXTRA_SAVE_SIZE)
+
+ ; Early out if GC stress is currently suppressed. Do this after we have computed the real address to
+ ; return to but before we link the transition frame onto m_pHackPInvokeTunnel (because hitting this
+ ; condition implies we're running restricted callouts during a GC itself and we could end up
+ ; overwriting a co-op frame set by the code that caused the GC in the first place, e.g. a GC.Collect
+ ; call).
+ ldr w1, [x4, #OFFSETOF__Thread__m_ThreadStateFlags]
+ tst w1, #TSF_SuppressGcStress__OR__TSF_DoNotTriggerGC
+ bne DoNotTriggerGC
+
+ ; link the frame into the Thread
+ add x1, sp, xzr
+ str x1, [x4, #OFFSETOF__Thread__m_pHackPInvokeTunnel]
+
+ ;;
+ ;; Unhijack this thread, if necessary.
+ ;;
+ INLINE_THREAD_UNHIJACK x4, x1, x2 ;; trashes x1, x2
+
+#ifdef FEATURE_GC_STRESS
+
+ ldr x1, =g_fGcStressStarted
+ ldr w1, [x1]
+ cbnz w1, SkipGcStress
+
+ mov x1, x0
+ ldr x0, =$g_pTheRuntimeInstance
+ ldr x0, [x0]
+ bl $RuntimeInstance__ShouldHijackLoopForGcStress
+ cbnz x0, SkipGcStress
+
+ bl $REDHAWKGCINTERFACE__STRESSGC
+SkipGcStress
+#endif ;; FEATURE_GC_STRESS
+
+ mov x9, sp ; sp is address of PInvokeTransitionFrame
+ bl RhpWaitForGCNoAbort
+
+DoNotTriggerGC
+ ldr x1, [sp, #OFFSETOF__PInvokeTransitionFrame__m_Flags]
+ tbnz x1, #PTFF_THREAD_ABORT_BIT, ToAbort
+
+ ; restore condition codes
+ ldr x1, [sp, #m_SavedNZCV]
+ msr NZCV, x1
+
+ FREE_LOOP_HIJACK_FRAME
+ EPILOG_RETURN
+
+ToAbort
+ FREE_LOOP_HIJACK_FRAME
+ EPILOG_NOP mov w0, #STATUS_REDHAWK_THREAD_ABORT
+ EPILOG_NOP mov x1, lr ; hijack target address as exception PC
+ EPILOG_NOP b RhpThrowHwEx
+
+ NESTED_END RhpTrapToGC
+
+ INLINE_GETTHREAD_CONSTANT_POOL
+
end
+
diff --git a/src/Native/Runtime/arm64/InteropThunksHelpers.asm b/src/Native/Runtime/arm64/InteropThunksHelpers.asm
index 88bb7da5d..cc8489ef1 100644
--- a/src/Native/Runtime/arm64/InteropThunksHelpers.asm
+++ b/src/Native/Runtime/arm64/InteropThunksHelpers.asm
@@ -58,7 +58,7 @@ __SECTIONREL_ThunkParamSlot
;; Now load the target address and jump to it.
ldr xip0, [xip0, #POINTER_SIZE]
- ret xip0
+ br xip0
LEAF_END RhCommonStub
diff --git a/src/Native/Runtime/arm64/MiscStubs.asm b/src/Native/Runtime/arm64/MiscStubs.asm
index ba18a93c2..99c05e4a3 100644
--- a/src/Native/Runtime/arm64/MiscStubs.asm
+++ b/src/Native/Runtime/arm64/MiscStubs.asm
@@ -96,7 +96,7 @@ RhpCheckCctor__SlowPath
EPILOG_RESTORE_REG_PAIR fp, lr, #0x20!
;; tail-call the class lib cctor check function. This function is required to return its first
;; argument, so that x0 can be preserved.
- EPILOG_NOP ret x12
+ EPILOG_NOP br x12
NESTED_END RhpCheckCctor__SlowPath2
diff --git a/src/Native/Runtime/arm64/StubDispatch.asm b/src/Native/Runtime/arm64/StubDispatch.asm
index 82a4f861e..8f3b7488c 100644
--- a/src/Native/Runtime/arm64/StubDispatch.asm
+++ b/src/Native/Runtime/arm64/StubDispatch.asm
@@ -55,7 +55,7 @@ SECTIONREL_t_TLS_DispatchCell
cmp x10, x11
bne %ft0 ;; Jump to label '0'
ldr x9, [x9, #(OFFSETOF__InterfaceDispatchCache__m_rgEntries + ($entry * 16) + 8)]
- ret x9
+ br x9
0 ;; Label '0'
MEND
@@ -70,7 +70,7 @@ SECTIONREL_t_TLS_DispatchCell
;; Now load the target address and jump to it.
ldr x9, [xip0, #8]
- ret x9
+ br x9
LEAF_END RhpCastableObjectDispatch_CommonStub
LEAF_ENTRY RhpTailCallTLSDispatchCell
@@ -79,7 +79,7 @@ SECTIONREL_t_TLS_DispatchCell
;; Tail call to the target of the dispatch cell, preserving the cell address in xip1
ldr x9, [xip1]
- ret x9
+ br x9
LEAF_END RhpTailCallTLSDispatchCell
LEAF_ENTRY RhpCastableObjectDispatchHelper_TailCalled
@@ -168,7 +168,7 @@ CurrentEntry SETA CurrentEntry + 1
;; Load the target address of the vtable into x12
ldr x12, [x12]
- ret x12
+ br x12
LEAF_END RhpVTableOffsetDispatch
;;
diff --git a/src/Native/Runtime/arm64/ThunkPoolThunks.asm b/src/Native/Runtime/arm64/ThunkPoolThunks.asm
index ddd2636db..ddf39de36 100644
--- a/src/Native/Runtime/arm64/ThunkPoolThunks.asm
+++ b/src/Native/Runtime/arm64/ThunkPoolThunks.asm
@@ -29,7 +29,6 @@ RO$name % 8
MACRO
LOAD_DATA_ADDRESS $groupIndex, $index, $pageIndex
- ALIGN 0x10 ;; make sure we align to 16-byte boundary for CFG table
;; Set xip0 to the address of the current thunk's data block. This is done using labels.
adr xip0, label_$groupIndex_$index_P$pageIndex
@@ -42,9 +41,9 @@ RO$name % 8
;; fix offset to point to last QWROD in page : xip1 <- [xip0 + PAGE_SIZE - POINTER_SIZE]
;; tailcall to the location pointed at by the last qword in the data page
ldr xip1, [xip0, #(PAGE_SIZE - POINTER_SIZE - ($groupIndex * THUNK_DATASIZE * 10 + THUNK_DATASIZE * $index))]
- ret xip1
+ br xip1
- brk 0xf000 ;; Stubs need to be 16-byte aligned (see comment above). Filling padding with a
+ brk 0xf000 ;; Stubs need to be 16-byte aligned for CFG table. Filling padding with a
;; deterministic brk instruction, instead of having it just filled with zeros.
MEND
diff --git a/src/Native/Runtime/arm64/UniversalTransition.asm b/src/Native/Runtime/arm64/UniversalTransition.asm
index fe4763740..dc699ebed 100644
--- a/src/Native/Runtime/arm64/UniversalTransition.asm
+++ b/src/Native/Runtime/arm64/UniversalTransition.asm
@@ -147,7 +147,7 @@
EPILOG_RESTORE_REG_PAIR fp, lr, #STACK_SIZE!
;; Tailcall to the target address.
- EPILOG_NOP ret x12
+ EPILOG_NOP br x12
NESTED_END Rhp$FunctionName
diff --git a/src/Native/Runtime/i386/ExceptionHandling.asm b/src/Native/Runtime/i386/ExceptionHandling.asm
index 270cb2330..1981279ab 100644
--- a/src/Native/Runtime/i386/ExceptionHandling.asm
+++ b/src/Native/Runtime/i386/ExceptionHandling.asm
@@ -207,6 +207,7 @@ FASTCALL_FUNC RhpRethrow, 0
mov [edx + OFFSETOF__ExInfo__m_exception], esi ;; init the exception object to null
mov byte ptr [edx + OFFSETOF__ExInfo__m_passNumber], 1 ;; init to the first pass
mov dword ptr [edx + OFFSETOF__ExInfo__m_idxCurClause], 0FFFFFFFFh
+ mov byte ptr [edx + OFFSETOF__ExInfo__m_kind], 0 ;; init to a deterministic value (ExKind.None)
;; link the ExInfo into the thread's ExInfo chain
mov ecx, [eax + OFFSETOF__Thread__m_pExInfoStackHead] ;; ecx <- currently active ExInfo
diff --git a/src/Native/Runtime/i386/ThunkPoolThunks.asm b/src/Native/Runtime/i386/ThunkPoolThunks.asm
index 1eb5312a0..848ab3dd1 100644
--- a/src/Native/Runtime/i386/ThunkPoolThunks.asm
+++ b/src/Native/Runtime/i386/ThunkPoolThunks.asm
@@ -1,8 +1,6 @@
-;; ==++==
-;;
-;; Copyright (c) Microsoft Corporation. All rights reserved.
-;;
-;; ==--==
+;; Licensed to the .NET Foundation under one or more agreements.
+;; The .NET Foundation licenses this file to you under the MIT license.
+;; See the LICENSE file in the project root for more information.
.586
.model flat
diff --git a/src/Native/Runtime/inc/eetype.h b/src/Native/Runtime/inc/eetype.h
index 39949b5eb..48431726a 100644
--- a/src/Native/Runtime/inc/eetype.h
+++ b/src/Native/Runtime/inc/eetype.h
@@ -568,23 +568,7 @@ public:
bool HasDynamicallyAllocatedDispatchMap()
{ return (get_RareFlags() & HasDynamicallyAllocatedDispatchMapFlag) != 0; }
- // Retrieve the generic type definition EEType for this generic instance
- void set_GenericDefinition(EEType *pTypeDef);
-
- // Retrieve the generic type definition EEType for this generic instance
- EETypeRef & get_GenericDefinition();
-
inline void set_GenericComposition(GenericComposition *);
- inline GenericComposition *get_GenericComposition();
-
- // Retrieve the number of generic arguments for this generic type instance
- UInt32 get_GenericArity();
-
- // Retrieve the generic arguments to this type
- EETypeRef * get_GenericArguments();
-
- // Retrieve the generic variance associated with this type
- GenericVarianceType* get_GenericVariance();
// Retrieve template used to create the dynamic type
EEType * get_DynamicTemplateType();
diff --git a/src/Native/Runtime/inc/eetype.inl b/src/Native/Runtime/inc/eetype.inl
index e52fed148..38e4ad89a 100644
--- a/src/Native/Runtime/inc/eetype.inl
+++ b/src/Native/Runtime/inc/eetype.inl
@@ -372,65 +372,15 @@ inline UInt8 EEType::GetNullableValueOffset()
return pOptFields->GetNullableValueOffset(0) + 1;
}
-inline void EEType::set_GenericDefinition(EEType *pTypeDef)
-{
- ASSERT(IsGeneric());
-
- UInt32 cbOffset = GetFieldOffset(ETF_GenericDefinition);
-
- *(EEType**)((UInt8*)this + cbOffset) = pTypeDef;
-}
-
-inline EETypeRef & EEType::get_GenericDefinition()
-{
- ASSERT(IsGeneric());
-
- UInt32 cbOffset = GetFieldOffset(ETF_GenericDefinition);
-
- return *(EETypeRef *)((UInt8*)this + cbOffset);
-}
-
inline void EEType::set_GenericComposition(GenericComposition *pGenericComposition)
{
- ASSERT(IsGeneric());
+ ASSERT(IsGeneric() && IsDynamicType());
UInt32 cbOffset = GetFieldOffset(ETF_GenericComposition);
*(GenericComposition **)((UInt8*)this + cbOffset) = pGenericComposition;
}
-inline GenericComposition *EEType::get_GenericComposition()
-{
- ASSERT(IsGeneric());
-
- UInt32 cbOffset = GetFieldOffset(ETF_GenericComposition);
-
- GenericComposition *pGenericComposition = *(GenericComposition **)((UInt8*)this + cbOffset);
-
- return pGenericComposition;
-}
-
-inline UInt32 EEType::get_GenericArity()
-{
- GenericComposition *pGenericComposition = get_GenericComposition();
-
- return pGenericComposition->GetArity();
-}
-
-inline EETypeRef* EEType::get_GenericArguments()
-{
- GenericComposition *pGenericComposition = get_GenericComposition();
-
- return pGenericComposition->GetArguments();
-}
-
-inline GenericVarianceType* EEType::get_GenericVariance()
-{
- GenericComposition *pGenericComposition = get_GenericComposition();
-
- return pGenericComposition->GetVariance();
-}
-
inline EEType * EEType::get_DynamicTemplateType()
{
ASSERT(IsDynamicType());
@@ -570,7 +520,7 @@ inline DynamicModule * EEType::get_DynamicModule()
+ (fRequiresOptionalFields ? sizeof(UIntTarget) : 0)
+ (fRequiresNullableType ? sizeof(UIntTarget) : 0)
+ (fHasSealedVirtuals ? sizeof(Int32) : 0)
- + (fHasGenericInfo ? sizeof(UIntTarget)*2 : 0);
+ + (fHasGenericInfo ? sizeof(UInt32)*2 : 0);
}
#if !defined(BINDER) && !defined(DACCESS_COMPILE)
@@ -578,21 +528,10 @@ inline DynamicModule * EEType::get_DynamicModule()
// represented - instead the classlib has a common one for all arrays
inline EEType * EEType::GetArrayBaseType()
{
- RuntimeInstance * pRuntimeInstance = GetRuntimeInstance();
- Module * pModule = NULL;
- if (pRuntimeInstance->IsInStandaloneExeMode())
- {
- // With dynamically created types, there is no home module to use to find System.Array. That's okay
- // for now, but when we support multi-module, we'll have to do something more clever here.
- pModule = pRuntimeInstance->GetStandaloneExeModule();
- }
- else
- {
- EEType *pEEType = this;
- if (pEEType->IsDynamicType())
- pEEType = pEEType->get_DynamicTemplateType();
- pModule = GetRuntimeInstance()->FindModuleByReadOnlyDataAddress(pEEType);
- }
+ EEType *pEEType = this;
+ if (pEEType->IsDynamicType())
+ pEEType = pEEType->get_DynamicTemplateType();
+ Module * pModule = GetRuntimeInstance()->FindModuleByReadOnlyDataAddress(pEEType);
EEType * pArrayBaseType = pModule->GetArrayBaseType();
return pArrayBaseType;
}
@@ -684,7 +623,7 @@ __forceinline UInt32 EEType::GetFieldOffset(EETypeField eField)
return cbOffset;
}
if (IsGeneric())
- cbOffset += sizeof(UIntTarget);
+ cbOffset += (IsDynamicType() ? sizeof(UIntTarget) : sizeof(UInt32));
if (eField == ETF_GenericComposition)
{
@@ -692,7 +631,7 @@ __forceinline UInt32 EEType::GetFieldOffset(EETypeField eField)
return cbOffset;
}
if (IsGeneric())
- cbOffset += sizeof(UIntTarget);
+ cbOffset += (IsDynamicType() ? sizeof(UIntTarget) : sizeof(UInt32));
if (eField == ETF_DynamicModule)
{
@@ -806,7 +745,7 @@ __forceinline UInt32 EEType::GetFieldOffset(EETypeField eField)
{
return cbOffset;
}
- cbOffset += sizeof(UIntTarget);
+ cbOffset += sizeof(UInt32);
if (eField == ETF_GenericComposition)
{
diff --git a/src/Native/Runtime/thread.cpp b/src/Native/Runtime/thread.cpp
index 994c21dad..aaefff971 100644
--- a/src/Native/Runtime/thread.cpp
+++ b/src/Native/Runtime/thread.cpp
@@ -31,7 +31,8 @@
#ifndef DACCESS_COMPILE
EXTERN_C REDHAWK_API void* REDHAWK_CALLCONV RhpHandleAlloc(void* pObject, int type);
-EXTERN_C REDHAWK_API void REDHAWK_CALLCONV RhHandleFree(void*);
+EXTERN_C REDHAWK_API void REDHAWK_CALLCONV RhHandleSet(void* handle, void* pObject);
+EXTERN_C REDHAWK_API void REDHAWK_CALLCONV RhHandleFree(void* handle);
static int (*g_RuntimeInitializationCallback)();
static Thread* g_RuntimeInitializingThread;
@@ -132,7 +133,7 @@ void Thread::ResetCachedTransitionFrame()
// This function simulates a PInvoke transition using a frame pointer from somewhere further up the stack that
// was passed in via the m_pHackPInvokeTunnel field. It is used to allow us to grandfather-in the set of GC
// code that runs in cooperative mode without having to rewrite it in managed code. The result is that the
-// code that calls into this special mode must spill preserved registeres as if it's going to PInvoke, but
+// code that calls into this special mode must spill preserved registers as if it's going to PInvoke, but
// record its transition frame pointer in m_pHackPInvokeTunnel and leave the thread in the cooperative
// mode. Later on, when this function is called, we effect the state transition to 'unmanaged' using the
// previously setup transition frame.
@@ -727,8 +728,6 @@ bool Thread::InternalHijack(PAL_LIMITED_CONTEXT * pSuspendCtx, void * pvHijackTa
if (frameIterator.IsValid())
{
- CrossThreadUnhijack();
-
frameIterator.CalculateCurrentMethodState();
frameIterator.GetCodeManager()->UnsynchronizedHijackMethodLoops(frameIterator.GetMethodInfo());
@@ -737,10 +736,16 @@ bool Thread::InternalHijack(PAL_LIMITED_CONTEXT * pSuspendCtx, void * pvHijackTa
GCRefKind retValueKind;
if (frameIterator.GetCodeManager()->GetReturnAddressHijackInfo(frameIterator.GetMethodInfo(),
- frameIterator.GetRegisterSet(),
- &ppvRetAddrLocation,
- &retValueKind))
+ frameIterator.GetRegisterSet(),
+ &ppvRetAddrLocation,
+ &retValueKind))
{
+ // ARM64 epilogs have a window between loading the hijackable return address into LR and the RET instruction.
+ // We cannot hijack or unhijack a thread while it is suspended in that window unless we implement hijacking
+ // via LR register modification. Therefore it is important to check our ability to hijack the thread before
+ // unhijacking it.
+ CrossThreadUnhijack();
+
void* pvRetAddr = *ppvRetAddrLocation;
ASSERT(ppvRetAddrLocation != NULL);
ASSERT(pvRetAddr != NULL);
@@ -1318,26 +1323,27 @@ Boolean Thread::SetThreadStaticStorageForModule(Object * pStorage, UInt32 module
m_numThreadLocalModuleStatics = newSize;
}
- void* threadStaticsStorageHandle = RhpHandleAlloc(pStorage, 2 /* Normal */);
- if (threadStaticsStorageHandle == NULL)
+ if (m_pThreadLocalModuleStatics[moduleIndex] != NULL)
{
- return FALSE;
+ RhHandleSet(m_pThreadLocalModuleStatics[moduleIndex], pStorage);
}
-
- // Free the existing storage before assigning a new one
- if (m_pThreadLocalModuleStatics[moduleIndex] != NULL)
+ else
{
- RhHandleFree(m_pThreadLocalModuleStatics[moduleIndex]);
+ void* threadStaticsStorageHandle = RhpHandleAlloc(pStorage, 2 /* Normal */);
+ if (threadStaticsStorageHandle == NULL)
+ {
+ return FALSE;
+ }
+ m_pThreadLocalModuleStatics[moduleIndex] = threadStaticsStorageHandle;
}
- m_pThreadLocalModuleStatics[moduleIndex] = threadStaticsStorageHandle;
return TRUE;
}
-COOP_PINVOKE_HELPER(Array*, RhGetThreadStaticStorageForModule, (UInt32 moduleIndex))
+COOP_PINVOKE_HELPER(Object*, RhGetThreadStaticStorageForModule, (UInt32 moduleIndex))
{
Thread * pCurrentThread = ThreadStore::RawGetCurrentThread();
- return (Array*)pCurrentThread->GetThreadStaticStorageForModule(moduleIndex);
+ return pCurrentThread->GetThreadStaticStorageForModule(moduleIndex);
}
COOP_PINVOKE_HELPER(Boolean, RhSetThreadStaticStorageForModule, (Array * pStorage, UInt32 moduleIndex))
@@ -1357,6 +1363,12 @@ COOP_PINVOKE_HELPER(UInt8*, RhCurrentNativeThreadId, ())
}
#endif // !PROJECTN
+// This function is used to get the OS thread identifier for the current thread.
+COOP_PINVOKE_HELPER(UInt64, RhCurrentOSThreadId, ())
+{
+ return PalGetCurrentThreadIdForLogging();
+}
+
// Standard calling convention variant and actual implementation for RhpReversePInvokeAttachOrTrapThread
EXTERN_C NOINLINE void FASTCALL RhpReversePInvokeAttachOrTrapThread2(ReversePInvokeFrame * pFrame)
{
diff --git a/src/Native/Runtime/thread.h b/src/Native/Runtime/thread.h
index c3934c823..b2143c75d 100644
--- a/src/Native/Runtime/thread.h
+++ b/src/Native/Runtime/thread.h
@@ -46,7 +46,9 @@ struct ExInfo;
typedef DPTR(ExInfo) PTR_ExInfo;
-// also defined in ExceptionHandling.cs, layouts must match
+// Also defined in ExceptionHandling.cs, layouts must match.
+// When adding new fields to this struct, ensure they get properly initialized in the exception handling
+// assembly stubs
struct ExInfo
{
diff --git a/src/Native/Runtime/unix/PalRedhawkInline.h b/src/Native/Runtime/unix/PalRedhawkInline.h
index e46d9ce87..67e197e72 100644
--- a/src/Native/Runtime/unix/PalRedhawkInline.h
+++ b/src/Native/Runtime/unix/PalRedhawkInline.h
@@ -43,7 +43,11 @@ FORCEINLINE Int32 PalInterlockedCompareExchange(_Inout_ _Interlocked_operand_ In
FORCEINLINE Int64 PalInterlockedCompareExchange64(_Inout_ _Interlocked_operand_ Int64 volatile *pDst, Int64 iValue, Int64 iComparand)
{
+#if defined(_WASM_)
+ PORTABILITY_ASSERT("Emscripten does not support 64-bit atomics until version 1.37.33");
+#else // _WASM_
return __sync_val_compare_and_swap(pDst, iComparand, iValue);
+#endif // _WASM_
}
#if defined(_AMD64_)
diff --git a/src/Native/Runtime/unix/PalRedhawkUnix.cpp b/src/Native/Runtime/unix/PalRedhawkUnix.cpp
index 0807d8004..de3d296ae 100644
--- a/src/Native/Runtime/unix/PalRedhawkUnix.cpp
+++ b/src/Native/Runtime/unix/PalRedhawkUnix.cpp
@@ -94,6 +94,14 @@ using std::nullptr_t;
#endif
#endif // __APPLE__
+#if defined(_ARM_) || defined(_ARM64_)
+#define SYSCONF_GET_NUMPROCS _SC_NPROCESSORS_CONF
+#define SYSCONF_GET_NUMPROCS_NAME "_SC_NPROCESSORS_CONF"
+#else
+#define SYSCONF_GET_NUMPROCS _SC_NPROCESSORS_ONLN
+#define SYSCONF_GET_NUMPROCS_NAME "_SC_NPROCESSORS_ONLN"
+#endif
+
#define PalRaiseFailFastException RaiseFailFastException
#define FATAL_ASSERT(e, msg) \
@@ -834,10 +842,10 @@ bool QueryCacheSize()
bool QueryLogicalProcessorCount()
{
#if HAVE_SYSCONF
- g_cLogicalCpus = sysconf(_SC_NPROCESSORS_ONLN);
+ g_cLogicalCpus = sysconf(SYSCONF_GET_NUMPROCS);
if (g_cLogicalCpus < 1)
{
- ASSERT_UNCONDITIONALLY("sysconf failed for _SC_NPROCESSORS_ONLN\n");
+ ASSERT_UNCONDITIONALLY("sysconf failed for " SYSCONF_GET_NUMPROCS_NAME "\n");
return false;
}
#elif HAVE_SYSCTL
@@ -1268,10 +1276,10 @@ bool InitializeSystemInfo()
int nrcpus = 0;
#if HAVE_SYSCONF
- nrcpus = sysconf(_SC_NPROCESSORS_ONLN);
+ nrcpus = sysconf(SYSCONF_GET_NUMPROCS);
if (nrcpus < 1)
{
- ASSERT_UNCONDITIONALLY("sysconf failed for _SC_NPROCESSORS_ONLN\n");
+ ASSERT_UNCONDITIONALLY("sysconf failed for " SYSCONF_GET_NUMPROCS_NAME "\n");
return false;
}
#elif HAVE_SYSCTL
diff --git a/src/Native/Runtime/unix/UnixContext.cpp b/src/Native/Runtime/unix/UnixContext.cpp
index 18fff0ccb..ea538213c 100644
--- a/src/Native/Runtime/unix/UnixContext.cpp
+++ b/src/Native/Runtime/unix/UnixContext.cpp
@@ -232,11 +232,11 @@ int unw_get_save_loc(unw_cursor_t*, int, unw_save_loc_t*)
static void RegDisplayToUnwindCursor(REGDISPLAY* regDisplay, unw_cursor_t *cursor)
{
#define ASSIGN_REG(regName1, regName2) \
- unw_set_reg(cursor, regName1, regDisplay->regName2);
+ unw_set_reg(cursor, regName1, regDisplay->regName2, 0);
#define ASSIGN_REG_PTR(regName1, regName2) \
if (regDisplay->p##regName2 != NULL) \
- unw_set_reg(cursor, regName1, *(regDisplay->p##regName2));
+ unw_set_reg(cursor, regName1, *(regDisplay->p##regName2), 0);
#if defined(_AMD64_)
ASSIGN_REG(UNW_REG_SP, SP)
diff --git a/src/Native/Runtime/unix/UnixNativeCodeManager.cpp b/src/Native/Runtime/unix/UnixNativeCodeManager.cpp
index 480893f97..70b94e752 100644
--- a/src/Native/Runtime/unix/UnixNativeCodeManager.cpp
+++ b/src/Native/Runtime/unix/UnixNativeCodeManager.cpp
@@ -41,8 +41,10 @@ struct UnixNativeMethodInfo
static_assert(sizeof(UnixNativeMethodInfo) <= sizeof(MethodInfo), "UnixNativeMethodInfo too big");
UnixNativeCodeManager::UnixNativeCodeManager(TADDR moduleBase,
+ PTR_VOID pvManagedCodeStartRange, UInt32 cbManagedCodeRange,
PTR_PTR_VOID pClasslibFunctions, UInt32 nClasslibFunctions)
: m_moduleBase(moduleBase),
+ m_pvManagedCodeStartRange(pvManagedCodeStartRange), m_cbManagedCodeRange(cbManagedCodeRange),
m_pClasslibFunctions(pClasslibFunctions), m_nClasslibFunctions(nClasslibFunctions)
{
}
@@ -54,6 +56,13 @@ UnixNativeCodeManager::~UnixNativeCodeManager()
bool UnixNativeCodeManager::FindMethodInfo(PTR_VOID ControlPC,
MethodInfo * pMethodInfoOut)
{
+ // Stackwalker may call this with ControlPC that does not belong to this code manager
+ if (dac_cast<TADDR>(ControlPC) < dac_cast<TADDR>(m_pvManagedCodeStartRange) ||
+ dac_cast<TADDR>(m_pvManagedCodeStartRange) + m_cbManagedCodeRange <= dac_cast<TADDR>(ControlPC))
+ {
+ return false;
+ }
+
UnixNativeMethodInfo * pMethodInfo = (UnixNativeMethodInfo *)pMethodInfoOut;
UIntNative startAddress;
UIntNative lsda;
@@ -396,6 +405,7 @@ bool RhRegisterOSModule(void * pModule,
void ** pClasslibFunctions, UInt32 nClasslibFunctions)
{
NewHolder<UnixNativeCodeManager> pUnixNativeCodeManager = new (nothrow) UnixNativeCodeManager((TADDR)pModule,
+ pvManagedCodeStartRange, cbManagedCodeRange,
pClasslibFunctions, nClasslibFunctions);
if (pUnixNativeCodeManager == nullptr)
diff --git a/src/Native/Runtime/unix/UnixNativeCodeManager.h b/src/Native/Runtime/unix/UnixNativeCodeManager.h
index b8e38fbb0..0b80291b8 100644
--- a/src/Native/Runtime/unix/UnixNativeCodeManager.h
+++ b/src/Native/Runtime/unix/UnixNativeCodeManager.h
@@ -7,12 +7,17 @@
class UnixNativeCodeManager : public ICodeManager
{
TADDR m_moduleBase;
+
+ PTR_VOID m_pvManagedCodeStartRange;
+ UInt32 m_cbManagedCodeRange;
+
PTR_PTR_VOID m_pClasslibFunctions;
UInt32 m_nClasslibFunctions;
public:
UnixNativeCodeManager(TADDR moduleBase,
- PTR_PTR_VOID pClasslibFunctions, UInt32 nClasslibFunctions);
+ PTR_VOID pvManagedCodeStartRange, UInt32 cbManagedCodeRange,
+ PTR_PTR_VOID pClasslibFunctions, UInt32 nClasslibFunctions);
virtual ~UnixNativeCodeManager();
diff --git a/src/Native/Runtime/unix/UnwindHelpers.cpp b/src/Native/Runtime/unix/UnwindHelpers.cpp
index c77de8200..7322e1ab1 100644
--- a/src/Native/Runtime/unix/UnwindHelpers.cpp
+++ b/src/Native/Runtime/unix/UnwindHelpers.cpp
@@ -292,13 +292,152 @@ struct Registers_REGDISPLAY : REGDISPLAY
};
#endif // _TARGET_AMD64_
+#if defined(_TARGET_ARM_)
+
+class Registers_arm_rt: public libunwind::Registers_arm {
+public:
+ Registers_arm_rt() { abort(); };
+ Registers_arm_rt(void *registers) { regs = (REGDISPLAY *)registers; };
+ uint32_t getRegister(int num);
+ void setRegister(int num, uint32_t value, uint32_t location);
+ uint32_t getRegisterLocation(int regNum) const { abort();}
+ unw_fpreg_t getFloatRegister(int num) { abort();}
+ void setFloatRegister(int num, unw_fpreg_t value) {abort();}
+ bool validVectorRegister(int num) const { abort();}
+ uint32_t getVectorRegister(int num) const {abort();};
+ void setVectorRegister(int num, uint32_t value) {abort();};
+ void jumpto() { abort();};
+ uint32_t getSP() const { return regs->SP;}
+ void setSP(uint32_t value, uint32_t location) { regs->SP = value;}
+ uint32_t getIP() const { return regs->IP;}
+ void setIP(uint32_t value, uint32_t location)
+ { regs->IP = value; regs->pIP = (PTR_UIntNative)location; }
+ void saveVFPAsX() {abort();};
+private:
+ REGDISPLAY *regs;
+};
+
+inline uint32_t Registers_arm_rt::getRegister(int regNum) {
+ if (regNum == UNW_REG_SP || regNum == UNW_ARM_SP)
+ return regs->SP;
+
+ if (regNum == UNW_ARM_LR)
+ return *regs->pLR;
+
+ if (regNum == UNW_REG_IP || regNum == UNW_ARM_IP)
+ return regs->IP;
+
+ switch (regNum)
+ {
+ case (UNW_ARM_R0):
+ return *regs->pR0;
+ case (UNW_ARM_R1):
+ return *regs->pR1;
+ case (UNW_ARM_R2):
+ return *regs->pR2;
+ case (UNW_ARM_R3):
+ return *regs->pR3;
+ case (UNW_ARM_R4):
+ return *regs->pR4;
+ case (UNW_ARM_R5):
+ return *regs->pR5;
+ case (UNW_ARM_R6):
+ return *regs->pR6;
+ case (UNW_ARM_R7):
+ return *regs->pR7;
+ case (UNW_ARM_R8):
+ return *regs->pR8;
+ case (UNW_ARM_R9):
+ return *regs->pR9;
+ case (UNW_ARM_R10):
+ return *regs->pR10;
+ case (UNW_ARM_R11):
+ return *regs->pR11;
+ case (UNW_ARM_R12):
+ return *regs->pR12;
+ }
+
+ PORTABILITY_ASSERT("unsupported arm register");
+}
+
+void Registers_arm_rt::setRegister(int num, uint32_t value, uint32_t location)
+{
+
+ if (num == UNW_REG_SP || num == UNW_ARM_SP) {
+ regs->SP = (UIntNative )value;
+ return;
+ }
+
+ if (num == UNW_ARM_LR) {
+ regs->pLR = (PTR_UIntNative)location;
+ return;
+ }
+
+ if (num == UNW_REG_IP || num == UNW_ARM_IP) {
+ regs->IP = value;
+ /* the location could be NULL, we could try to recover
+ pointer to value in stack from pLR */
+ if ((!location) && (regs->pLR) && (*regs->pLR == value))
+ regs->pIP = regs->pLR;
+ else
+ regs->pIP = (PTR_UIntNative)location;
+ return;
+ }
+
+ switch (num)
+ {
+ case (UNW_ARM_R0):
+ regs->pR0 = (PTR_UIntNative)location;
+ break;
+ case (UNW_ARM_R1):
+ regs->pR1 = (PTR_UIntNative)location;
+ break;
+ case (UNW_ARM_R2):
+ regs->pR2 = (PTR_UIntNative)location;
+ break;
+ case (UNW_ARM_R3):
+ regs->pR3 = (PTR_UIntNative)location;
+ break;
+ case (UNW_ARM_R4):
+ regs->pR4 = (PTR_UIntNative)location;
+ break;
+ case (UNW_ARM_R5):
+ regs->pR5 = (PTR_UIntNative)location;
+ break;
+ case (UNW_ARM_R6):
+ regs->pR6 = (PTR_UIntNative)location;
+ break;
+ case (UNW_ARM_R7):
+ regs->pR7 = (PTR_UIntNative)location;
+ break;
+ case (UNW_ARM_R8):
+ regs->pR8 = (PTR_UIntNative)location;
+ break;
+ case (UNW_ARM_R9):
+ regs->pR9 = (PTR_UIntNative)location;
+ break;
+ case (UNW_ARM_R10):
+ regs->pR10 = (PTR_UIntNative)location;
+ break;
+ case (UNW_ARM_R11):
+ regs->pR11 = (PTR_UIntNative)location;
+ break;
+ case (UNW_ARM_R12):
+ regs->pR12 = (PTR_UIntNative)location;
+ break;
+ default:
+ PORTABILITY_ASSERT("unsupported arm register");
+ }
+}
+
+#endif // _TARGET_ARM_
bool DoTheStep(uintptr_t pc, UnwindInfoSections uwInfoSections, REGDISPLAY *regs)
{
#if defined(_TARGET_AMD64_)
libunwind::UnwindCursor<LocalAddressSpace, Registers_x86_64> uc(_addressSpace);
#elif defined(_TARGET_ARM_)
- libunwind::UnwindCursor<LocalAddressSpace, Registers_arm> uc(_addressSpace);
+ libunwind::UnwindCursor<LocalAddressSpace, Registers_arm_rt> uc(_addressSpace, regs);
#else
#error "Unwinding is not implemented for this architecture yet."
#endif
@@ -322,8 +461,13 @@ bool DoTheStep(uintptr_t pc, UnwindInfoSections uwInfoSections, REGDISPLAY *regs
}
regs->pIP = PTR_PCODE(regs->SP - sizeof(TADDR));
-#else
- PORTABILITY_ASSERT("DoTheStep");
+#elif defined(_LIBUNWIND_ARM_EHABI)
+ uc.setInfoBasedOnIPRegister(true);
+ int stepRet = uc.step();
+ if ((stepRet != UNW_STEP_SUCCESS) && (stepRet != UNW_STEP_END))
+ {
+ return false;
+ }
#endif
return true;
@@ -365,18 +509,20 @@ UnwindInfoSections LocateUnwindSections(uintptr_t pc)
bool UnwindHelpers::StepFrame(REGDISPLAY *regs)
{
+#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
uintptr_t pc = regs->GetIP();
-
UnwindInfoSections uwInfoSections = LocateUnwindSections(pc);
-
-#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
if (uwInfoSections.dwarf_section == NULL)
{
return false;
}
+ return DoTheStep(pc, uwInfoSections, regs);
+#elif defined(_LIBUNWIND_ARM_EHABI)
+ // unwind section is located later for ARM
+ // pc will be taked from regs parameter
+ UnwindInfoSections uwInfoSections;
+ return DoTheStep(0, uwInfoSections, regs);
#else
PORTABILITY_ASSERT("StepFrame");
#endif
-
- return DoTheStep(pc, uwInfoSections, regs);
}
diff --git a/src/Native/Runtime/unix/unixasmmacrosamd64.inc b/src/Native/Runtime/unix/unixasmmacrosamd64.inc
index d94fe2d8c..f7fdc26c4 100644
--- a/src/Native/Runtime/unix/unixasmmacrosamd64.inc
+++ b/src/Native/Runtime/unix/unixasmmacrosamd64.inc
@@ -224,12 +224,14 @@ C_FUNC(\Name):
.macro EXPORT_POINTER_TO_ADDRESS Name
-1:
+// NOTE: The label is intentionally left as 2 - otherwise on OSX 0b or 1b will be incorrectly interpreted as binary integers
+
+2:
.data
.align 8
C_FUNC(\Name):
- .quad 1b
+ .quad 2b
.global C_FUNC(\Name)
.text
diff --git a/src/Native/Runtime/windows/CoffNativeCodeManager.cpp b/src/Native/Runtime/windows/CoffNativeCodeManager.cpp
index 22a37bb92..ae8be443f 100644
--- a/src/Native/Runtime/windows/CoffNativeCodeManager.cpp
+++ b/src/Native/Runtime/windows/CoffNativeCodeManager.cpp
@@ -172,9 +172,11 @@ static PTR_VOID GetUnwindDataBlob(TADDR moduleBase, PTR_RUNTIME_FUNCTION pRuntim
CoffNativeCodeManager::CoffNativeCodeManager(TADDR moduleBase,
+ PTR_VOID pvManagedCodeStartRange, UInt32 cbManagedCodeRange,
PTR_RUNTIME_FUNCTION pRuntimeFunctionTable, UInt32 nRuntimeFunctionTable,
PTR_PTR_VOID pClasslibFunctions, UInt32 nClasslibFunctions)
: m_moduleBase(moduleBase),
+ m_pvManagedCodeStartRange(pvManagedCodeStartRange), m_cbManagedCodeRange(cbManagedCodeRange),
m_pRuntimeFunctionTable(pRuntimeFunctionTable), m_nRuntimeFunctionTable(nRuntimeFunctionTable),
m_pClasslibFunctions(pClasslibFunctions), m_nClasslibFunctions(nClasslibFunctions)
{
@@ -193,8 +195,6 @@ static int LookupUnwindInfoForMethod(UInt32 relativePc,
relativePc |= THUMB_CODE;
#endif
- // Entries are sorted and terminated by sentinel value (DWORD)-1
-
// Binary search the RUNTIME_FUNCTION table
// Use linear search once we get down to a small number of elements
// to avoid Binary search overhead.
@@ -213,22 +213,23 @@ static int LookupUnwindInfoForMethod(UInt32 relativePc,
}
}
- for (int i = low; i <= high; ++i)
+ for (int i = low; i < high; i++)
{
- // This is safe because of entries are terminated by sentinel value (DWORD)-1
PTR_RUNTIME_FUNCTION pNextFunctionEntry = pRuntimeFunctionTable + (i + 1);
-
if (relativePc < pNextFunctionEntry->BeginAddress)
{
- PTR_RUNTIME_FUNCTION pFunctionEntry = pRuntimeFunctionTable + i;
- if (relativePc >= pFunctionEntry->BeginAddress)
- {
- return i;
- }
+ high = i;
break;
}
}
+ PTR_RUNTIME_FUNCTION pFunctionEntry = pRuntimeFunctionTable + high;
+ if (relativePc >= pFunctionEntry->BeginAddress)
+ {
+ return high;
+ }
+
+ ASSERT_UNCONDITIONALLY("Invalid code address");
return -1;
}
@@ -245,6 +246,13 @@ static_assert(sizeof(CoffNativeMethodInfo) <= sizeof(MethodInfo), "CoffNativeMet
bool CoffNativeCodeManager::FindMethodInfo(PTR_VOID ControlPC,
MethodInfo * pMethodInfoOut)
{
+ // Stackwalker may call this with ControlPC that does not belong to this code manager
+ if (dac_cast<TADDR>(ControlPC) < dac_cast<TADDR>(m_pvManagedCodeStartRange) ||
+ dac_cast<TADDR>(m_pvManagedCodeStartRange) + m_cbManagedCodeRange <= dac_cast<TADDR>(ControlPC))
+ {
+ return false;
+ }
+
CoffNativeMethodInfo * pMethodInfo = (CoffNativeMethodInfo *)pMethodInfoOut;
TADDR relativePC = dac_cast<TADDR>(ControlPC) - m_moduleBase;
@@ -372,9 +380,81 @@ void CoffNativeCodeManager::EnumGcRefs(MethodInfo * pMethodInfo,
UIntNative CoffNativeCodeManager::GetConservativeUpperBoundForOutgoingArgs(MethodInfo * pMethodInfo, REGDISPLAY * pRegisterSet)
{
- // @TODO: CORERT: GetConservativeUpperBoundForOutgoingArgs
+#if defined(_TARGET_AMD64_)
+
+ // Return value
+ UIntNative upperBound;
+ CoffNativeMethodInfo* pNativeMethodInfo = (CoffNativeMethodInfo *) pMethodInfo;
+
+ size_t unwindDataBlobSize;
+ PTR_VOID pUnwindDataBlob = GetUnwindDataBlob(m_moduleBase, pNativeMethodInfo->runtimeFunction, &unwindDataBlobSize);
+ PTR_UInt8 p = dac_cast<PTR_UInt8>(pUnwindDataBlob) + unwindDataBlobSize;
+ uint8_t unwindBlockFlags = *p++;
+
+ if ((unwindBlockFlags & UBF_FUNC_HAS_ASSOCIATED_DATA) != 0)
+ p += sizeof(int32_t);
+
+ if ((unwindBlockFlags & UBF_FUNC_REVERSE_PINVOKE) != 0)
+ {
+ TADDR basePointer = dac_cast<TADDR>(pRegisterSet->GetFP());
+
+ // Get the method's GC info
+ GcInfoDecoder decoder(GCInfoToken(p), DECODE_REVERSE_PINVOKE_VAR);
+ UINT32 stackBasedRegister = decoder.GetStackBaseRegister();
+
+ if (stackBasedRegister == NO_STACK_BASE_REGISTER)
+ {
+ basePointer = dac_cast<TADDR>(pRegisterSet->GetSP());
+ }
+ else
+ {
+ basePointer = dac_cast<TADDR>(pRegisterSet->GetFP());
+ }
+ // Reverse PInvoke case. The embedded reverse PInvoke frame is guaranteed to reside above
+ // all outgoing arguments.
+ INT32 slot = decoder.GetReversePInvokeFrameStackSlot();
+ upperBound = (UIntNative) dac_cast<TADDR>(basePointer + slot);
+ }
+ else
+ {
+ // Check for a pushed RBP value
+ if (GetFramePointer(pMethodInfo, pRegisterSet) == NULL)
+ {
+ // Unwind the current method context to get the caller's stack pointer
+ // and obtain the upper bound of the callee is the value just below the caller's return address on the stack
+ SIZE_T EstablisherFrame;
+ PVOID HandlerData;
+ CONTEXT context;
+ context.Rsp = pRegisterSet->GetSP();
+ context.Rbp = pRegisterSet->GetFP();
+ context.Rip = pRegisterSet->GetIP();
+
+ RtlVirtualUnwind(NULL,
+ dac_cast<TADDR>(m_moduleBase),
+ pRegisterSet->IP,
+ (PRUNTIME_FUNCTION)pNativeMethodInfo->runtimeFunction,
+ &context,
+ &HandlerData,
+ &EstablisherFrame,
+ NULL);
+
+ upperBound = dac_cast<TADDR>(context.Rsp - sizeof (PVOID));
+ }
+ else
+ {
+ // In amd64, it is guaranteed that if there is a pushed RBP
+ // value at the top of the frame it resides above all outgoing arguments. Unlike x86,
+ // the frame pointer generally points to a location that is separated from the pushed RBP
+ // value by an offset that is recorded in the info header. Recover the address of the
+ // pushed RBP value by subtracting this offset.
+ upperBound = (UIntNative) dac_cast<TADDR>(pRegisterSet->GetFP() - ((PTR_UNWIND_INFO) pUnwindDataBlob)->FrameOffset);
+ }
+ }
+ return upperBound;
+#else
assert(false);
return false;
+#endif
}
bool CoffNativeCodeManager::UnwindStackFrame(MethodInfo * pMethodInfo,
@@ -705,6 +785,12 @@ void * CoffNativeCodeManager::GetClasslibFunction(ClasslibFunctionId functionId)
PTR_VOID CoffNativeCodeManager::GetAssociatedData(PTR_VOID ControlPC)
{
+ if (dac_cast<TADDR>(ControlPC) < dac_cast<TADDR>(m_pvManagedCodeStartRange) ||
+ dac_cast<TADDR>(m_pvManagedCodeStartRange) + m_cbManagedCodeRange <= dac_cast<TADDR>(ControlPC))
+ {
+ return NULL;
+ }
+
TADDR relativePC = dac_cast<TADDR>(ControlPC) - m_moduleBase;
int MethodIndex = LookupUnwindInfoForMethod((UInt32)relativePC, m_pRuntimeFunctionTable, 0, m_nRuntimeFunctionTable - 1);
@@ -742,6 +828,7 @@ bool RhRegisterOSModule(void * pModule,
IMAGE_DATA_DIRECTORY * pRuntimeFunctions = &(pNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION]);
NewHolder<CoffNativeCodeManager> pCoffNativeCodeManager = new (nothrow) CoffNativeCodeManager((TADDR)pModule,
+ pvManagedCodeStartRange, cbManagedCodeRange,
dac_cast<PTR_RUNTIME_FUNCTION>((TADDR)pModule + pRuntimeFunctions->VirtualAddress),
pRuntimeFunctions->Size / sizeof(RUNTIME_FUNCTION),
pClasslibFunctions, nClasslibFunctions);
diff --git a/src/Native/Runtime/windows/CoffNativeCodeManager.h b/src/Native/Runtime/windows/CoffNativeCodeManager.h
index 81b4ee625..ab4a561b7 100644
--- a/src/Native/Runtime/windows/CoffNativeCodeManager.h
+++ b/src/Native/Runtime/windows/CoffNativeCodeManager.h
@@ -40,6 +40,10 @@ typedef DPTR(T_RUNTIME_FUNCTION) PTR_RUNTIME_FUNCTION;
class CoffNativeCodeManager : public ICodeManager
{
TADDR m_moduleBase;
+
+ PTR_VOID m_pvManagedCodeStartRange;
+ UInt32 m_cbManagedCodeRange;
+
PTR_RUNTIME_FUNCTION m_pRuntimeFunctionTable;
UInt32 m_nRuntimeFunctionTable;
@@ -48,6 +52,7 @@ class CoffNativeCodeManager : public ICodeManager
public:
CoffNativeCodeManager(TADDR moduleBase,
+ PTR_VOID pvManagedCodeStartRange, UInt32 cbManagedCodeRange,
PTR_RUNTIME_FUNCTION pRuntimeFunctionTable, UInt32 nRuntimeFunctionTable,
PTR_PTR_VOID pClasslibFunctions, UInt32 nClasslibFunctions);
~CoffNativeCodeManager();
diff --git a/src/Native/Runtime/windows/PalRedhawkCommon.cpp b/src/Native/Runtime/windows/PalRedhawkCommon.cpp
index 7618b24c0..f5783eb6c 100644
--- a/src/Native/Runtime/windows/PalRedhawkCommon.cpp
+++ b/src/Native/Runtime/windows/PalRedhawkCommon.cpp
@@ -143,7 +143,7 @@ REDHAWK_PALEXPORT void REDHAWK_PALAPI PalGetPDBInfo(HANDLE hOsHandle, _Out_ GUID
if (cbDebugData < size_t(&((CV_INFO_PDB70*)0)->magic) + sizeof(((CV_INFO_PDB70*)0)->magic))
{
// raw data too small to contain magic number at expected spot, so its format
- // is not recognizeable. Skip
+ // is not recognizable. Skip
continue;
}
diff --git a/src/Native/Runtime/windows/PalRedhawkMinWin.cpp b/src/Native/Runtime/windows/PalRedhawkMinWin.cpp
index 95095e1db..16ec4d6fe 100644
--- a/src/Native/Runtime/windows/PalRedhawkMinWin.cpp
+++ b/src/Native/Runtime/windows/PalRedhawkMinWin.cpp
@@ -218,21 +218,28 @@ REDHAWK_PALEXPORT UInt32_BOOL REDHAWK_PALAPI PalMarkThunksAsValidCallTargets(
REDHAWK_PALEXPORT UInt32 REDHAWK_PALAPI PalCompatibleWaitAny(UInt32_BOOL alertable, UInt32 timeout, UInt32 handleCount, HANDLE* pHandles, UInt32_BOOL allowReentrantWait)
{
- DWORD index;
- SetLastError(ERROR_SUCCESS); // recommended by MSDN.
- HRESULT hr = CoWaitForMultipleHandles(alertable ? COWAIT_ALERTABLE : 0, timeout, handleCount, pHandles, &index);
-
- switch (hr)
+ if (!allowReentrantWait)
+ {
+ return WaitForMultipleObjectsEx(handleCount, pHandles, FALSE, timeout, alertable);
+ }
+ else
{
- case S_OK:
- return index;
+ DWORD index;
+ SetLastError(ERROR_SUCCESS); // recommended by MSDN.
+ HRESULT hr = CoWaitForMultipleHandles(alertable ? COWAIT_ALERTABLE : 0, timeout, handleCount, pHandles, &index);
+
+ switch (hr)
+ {
+ case S_OK:
+ return index;
- case RPC_S_CALLPENDING:
- return WAIT_TIMEOUT;
+ case RPC_S_CALLPENDING:
+ return WAIT_TIMEOUT;
- default:
- SetLastError(HRESULT_CODE(hr));
- return WAIT_FAILED;
+ default:
+ SetLastError(HRESULT_CODE(hr));
+ return WAIT_FAILED;
+ }
}
}
@@ -1065,7 +1072,7 @@ void DumpCacheTopology(_In_reads_(cRecords) SYSTEM_LOGICAL_PROCESSOR_INFORMATION
switch (pProcInfos[i].Relationship)
{
case RelationProcessorCore:
- printf(" [%2d] Core: %d threads 0x%04zx mask, flags = %d\n",
+ printf(" [%2d] Core: %d threads 0x%04Ix mask, flags = %d\n",
i, CountBits(pProcInfos[i].ProcessorMask), pProcInfos[i].ProcessorMask,
pProcInfos[i].ProcessorCore.Flags);
break;
@@ -1079,16 +1086,16 @@ void DumpCacheTopology(_In_reads_(cRecords) SYSTEM_LOGICAL_PROCESSOR_INFORMATION
case CacheTrace: pszCacheType = "[Trace ]"; break;
default: pszCacheType = "[Unk ]"; break;
}
- printf(" [%2d] Cache: %s 0x%08x bytes 0x%04zx mask\n", i, pszCacheType,
+ printf(" [%2d] Cache: %s 0x%08x bytes 0x%04Ix mask\n", i, pszCacheType,
pProcInfos[i].Cache.Size, pProcInfos[i].ProcessorMask);
break;
case RelationNumaNode:
- printf(" [%2d] NumaNode: #%02d 0x%04zx mask\n",
+ printf(" [%2d] NumaNode: #%02d 0x%04Ix mask\n",
i, pProcInfos[i].NumaNode.NodeNumber, pProcInfos[i].ProcessorMask);
break;
case RelationProcessorPackage:
- printf(" [%2d] Package: 0x%04zx mask\n",
+ printf(" [%2d] Package: 0x%04Ix mask\n",
i, pProcInfos[i].ProcessorMask);
break;
case RelationAll:
@@ -1106,8 +1113,8 @@ void DumpCacheTopologyResults(UInt32 maxCpuId, CpuVendor cpuVendor, _In_reads_(c
DumpCacheTopology(pProcInfos, cRecords);
printf("maxCpuId: %d, %s\n", maxCpuId, (cpuVendor == CpuIntel) ? "CpuIntel" : ((cpuVendor == CpuAMD) ? "CpuAMD" : "CpuUnknown"));
printf(" g_cLogicalCpus: %d %d :CLR_GetLogicalCpuCount\n", g_cLogicalCpus, CLR_GetLogicalCpuCount(pProcInfos, cRecords));
- printf(" g_cbLargestOnDieCache: 0x%08zx 0x%08zx :CLR_LargestOnDieCache(TRUE)\n", g_cbLargestOnDieCache, CLR_GetLargestOnDieCacheSize(TRUE, pProcInfos, cRecords));
- printf("g_cbLargestOnDieCacheAdjusted: 0x%08zx 0x%08zx :CLR_LargestOnDieCache(FALSE)\n", g_cbLargestOnDieCacheAdjusted, CLR_GetLargestOnDieCacheSize(FALSE, pProcInfos, cRecords));
+ printf(" g_cbLargestOnDieCache: 0x%08Ix 0x%08Ix :CLR_LargestOnDieCache(TRUE)\n", g_cbLargestOnDieCache, CLR_GetLargestOnDieCacheSize(TRUE, pProcInfos, cRecords));
+ printf("g_cbLargestOnDieCacheAdjusted: 0x%08Ix 0x%08Ix :CLR_LargestOnDieCache(FALSE)\n", g_cbLargestOnDieCacheAdjusted, CLR_GetLargestOnDieCacheSize(FALSE, pProcInfos, cRecords));
}
#endif // _DEBUG
@@ -1286,12 +1293,18 @@ bool PalQueryProcessorTopology()
#ifdef TRACE_CACHE_TOPOLOGY
DumpCacheTopologyResults(maxCpuId, cpuVendor, pProcInfos, cRecords);
#endif
- if ((CLR_GetLargestOnDieCacheSize(TRUE, pProcInfos, cRecords) != g_cbLargestOnDieCache) ||
- (CLR_GetLargestOnDieCacheSize(FALSE, pProcInfos, cRecords) != g_cbLargestOnDieCacheAdjusted) ||
- (CLR_GetLogicalCpuCount(pProcInfos, cRecords) != g_cLogicalCpus))
+ // CLR_GetLargestOnDieCacheSize is implemented for Intel and AMD processors only
+ if ((cpuVendor == CpuIntel) || (cpuVendor == CpuAMD))
{
- DumpCacheTopologyResults(maxCpuId, cpuVendor, pProcInfos, cRecords);
- assert(!"QueryProcessorTopology doesn't match CLR's results. See stdout for more info.");
+ if ((CLR_GetLargestOnDieCacheSize(TRUE, pProcInfos, cRecords) != g_cbLargestOnDieCache) ||
+ (CLR_GetLargestOnDieCacheSize(FALSE, pProcInfos, cRecords) != g_cbLargestOnDieCacheAdjusted) ||
+ (CLR_GetLogicalCpuCount(pProcInfos, cRecords) != g_cLogicalCpus))
+ {
+#ifndef TRACE_CACHE_TOPOLOGY
+ DumpCacheTopologyResults(maxCpuId, cpuVendor, pProcInfos, cRecords);
+#endif
+ assert(!"QueryProcessorTopology doesn't match CLR's results. See stdout for more info.");
+ }
}
#endif // _DEBUG
}
diff --git a/src/Native/System.Private.CoreLib.Native/CMakeLists.txt b/src/Native/System.Private.CoreLib.Native/CMakeLists.txt
index 760b75e24..d50340e67 100644
--- a/src/Native/System.Private.CoreLib.Native/CMakeLists.txt
+++ b/src/Native/System.Private.CoreLib.Native/CMakeLists.txt
@@ -6,7 +6,6 @@ set(NATIVE_SOURCES
pal_dynamicload.cpp
pal_environment.cpp
pal_errno.cpp
- pal_guid.cpp
pal_memory.cpp
pal_exepath.cpp
pal_threading.cpp
diff --git a/src/Native/System.Private.CoreLib.Native/config.h.in b/src/Native/System.Private.CoreLib.Native/config.h.in
index 3d13262a2..3c3f11298 100644
--- a/src/Native/System.Private.CoreLib.Native/config.h.in
+++ b/src/Native/System.Private.CoreLib.Native/config.h.in
@@ -5,6 +5,5 @@
#cmakedefine01 HAVE_CLOCK_MONOTONIC_COARSE
#cmakedefine01 HAVE_MACH_ABSOLUTE_TIME
#cmakedefine01 HAVE_SCHED_GETCPU
-#cmakedefine01 HAVE_LIBUUID_H
-#cmakedefine01 HAVE_UUID_GENERATE_RANDOM
-#cmakedefine01 HAVE_UUID_GENERATE
+#cmakedefine01 HAVE_GNU_LIBNAMES_H
+#cmakedefine01 HAVE__NSGETENVIRON \ No newline at end of file
diff --git a/src/Native/System.Private.CoreLib.Native/configure.cmake b/src/Native/System.Private.CoreLib.Native/configure.cmake
index c84bf8971..1fbbf9c5e 100644
--- a/src/Native/System.Private.CoreLib.Native/configure.cmake
+++ b/src/Native/System.Private.CoreLib.Native/configure.cmake
@@ -1,18 +1,10 @@
include(CheckCXXSourceCompiles)
include(CheckCXXSourceRuns)
include(CheckLibraryExists)
+include(CheckFunctionExists)
check_library_exists(pthread pthread_condattr_setclock "" HAVE_PTHREAD_CONDATTR_SETCLOCK)
-check_include_files(uuid/uuid.h HAVE_LIBUUID_H)
-
-if(NOT CMAKE_SYSTEM_NAME STREQUAL Darwin)
- set(CMAKE_REQUIRED_LIBRARIES uuid)
-endif()
-check_function_exists(uuid_generate_random HAVE_UUID_GENERATE_RANDOM)
-check_function_exists(uuid_generate HAVE_UUID_GENERATE)
-set(CMAKE_REQUIRED_LIBRARIES)
-
check_cxx_source_runs("
#include <stdlib.h>
#include <time.h>
@@ -69,10 +61,9 @@ int main(void)
}" HAVE_SCHED_GETCPU)
set(CMAKE_REQUIRED_LIBRARIES)
-if(NOT HAVE_LIBUUID_H)
- unset(HAVE_LIBUUID_H CACHE)
- message(FATAL_ERROR "Cannot find libuuid. Try installing uuid-dev or the appropriate packages for your platform")
-endif()
+check_include_files(gnu/lib-names.h HAVE_GNU_LIBNAMES_H)
+
+check_function_exists(_NSGetEnviron HAVE__NSGETENVIRON)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
diff --git a/src/Native/System.Private.CoreLib.Native/pal_dynamicload.cpp b/src/Native/System.Private.CoreLib.Native/pal_dynamicload.cpp
index dfb2917f2..d46e3da95 100644
--- a/src/Native/System.Private.CoreLib.Native/pal_dynamicload.cpp
+++ b/src/Native/System.Private.CoreLib.Native/pal_dynamicload.cpp
@@ -2,10 +2,38 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+#include "pal_common.h"
#include <dlfcn.h>
+#include <string.h>
+
+#if HAVE_GNU_LIBNAMES_H
+#include <gnu/lib-names.h>
+#endif
extern "C" void* CoreLibNative_LoadLibrary(const char* filename)
{
+ // Check whether we have been requested to load 'libc'. If that's the case, then:
+ // * For Linux, use the full name of the library that is defined in <gnu/lib-names.h> by the
+ // LIBC_SO constant. The problem is that calling dlopen("libc.so") will fail for libc even
+ // though it works for other libraries. The reason is that libc.so is just linker script
+ // (i.e. a test file).
+ // As a result, we have to use the full name (i.e. lib.so.6) that is defined by LIBC_SO.
+ // * For macOS, use constant value absolute path "/usr/lib/libc.dylib".
+ // * For FreeBSD, use constant value "libc.so.7".
+ // * For rest of Unices, use constant value "libc.so".
+ if (strcmp(filename, "libc") == 0)
+ {
+#if defined(__APPLE__)
+ filename = "/usr/lib/libc.dylib";
+#elif defined(__FreeBSD__)
+ filename = "libc.so.7";
+#elif defined(LIBC_SO)
+ filename = LIBC_SO;
+#else
+ filename = "libc.so";
+#endif
+ }
+
return dlopen(filename, RTLD_LAZY);
}
diff --git a/src/Native/System.Private.CoreLib.Native/pal_environment.cpp b/src/Native/System.Private.CoreLib.Native/pal_environment.cpp
index 94660baba..15ef90c34 100644
--- a/src/Native/System.Private.CoreLib.Native/pal_environment.cpp
+++ b/src/Native/System.Private.CoreLib.Native/pal_environment.cpp
@@ -10,6 +10,9 @@
#if HAVE_SCHED_GETCPU
#include <sched.h>
#endif
+#if HAVE__NSGETENVIRON
+#include <crt_externs.h>
+#endif
extern "C" char* CoreLibNative_GetEnv(const char* variable)
@@ -30,3 +33,17 @@ extern "C" void CoreLibNative_Exit(int32_t exitCode)
{
exit(exitCode);
}
+
+extern "C" char** CoreLibNative_GetEnviron()
+{
+ char** sysEnviron;
+
+#if HAVE__NSGETENVIRON
+ sysEnviron = *(_NSGetEnviron());
+#else // HAVE__NSGETENVIRON
+ extern char **environ;
+ sysEnviron = environ;
+#endif // HAVE__NSGETENVIRON
+
+ return sysEnviron;
+} \ No newline at end of file
diff --git a/src/Native/System.Private.CoreLib.Native/pal_guid.cpp b/src/Native/System.Private.CoreLib.Native/pal_guid.cpp
deleted file mode 100644
index 8e35d089e..000000000
--- a/src/Native/System.Private.CoreLib.Native/pal_guid.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-#include "pal_common.h"
-
-#if HAVE_LIBUUID_H
-#include <uuid/uuid.h>
-#endif
-
-#include "pal_endian.h"
-
-typedef struct _GUID {
- uint32_t Data1; // NOTE: diff from Win32, for LP64
- uint16_t Data2;
- uint16_t Data3;
- uint8_t Data4[8];
-} GUID;
-
-extern "C" void CoreLibNative_CreateGuid(GUID* pGuid)
-{
-#if HAVE_UUID_GENERATE_RANDOM
- uuid_generate_random(*(uuid_t*)pGuid);
-#elif HAVE_UUID_GENERATE
- uuid_generate(*(uuid_t*)pGuid);
-#else
-#error Don't know how to generate UUID on this platform
-#endif
-
- // Change the byte order of the Data1, 2 and 3, since uuid_generate_random and uuid_generate
- // generates them with big endian while GUIDS need to have them in little endian.
- pGuid->Data1 = SWAP32(pGuid->Data1);
- pGuid->Data2 = SWAP16(pGuid->Data2);
- pGuid->Data3 = SWAP16(pGuid->Data3);
-}
diff --git a/src/Native/System.Private.CoreLib.Native/pal_time.cpp b/src/Native/System.Private.CoreLib.Native/pal_time.cpp
index b0cd1b1ed..136cb03bc 100644
--- a/src/Native/System.Private.CoreLib.Native/pal_time.cpp
+++ b/src/Native/System.Private.CoreLib.Native/pal_time.cpp
@@ -168,7 +168,7 @@ extern "C" int32_t CoreLibNative_GetCpuUtilization(ProcessCpuInformation* previo
{
if (numProcessors <= 0)
{
- numProcessors = sysconf(_SC_NPROCESSORS_ONLN);
+ numProcessors = sysconf(_SC_NPROCESSORS_CONF);
if (numProcessors <= 0)
{
return 0;
diff --git a/src/Native/System.Private.TypeLoader.Native/CMakeLists.txt b/src/Native/System.Private.TypeLoader.Native/CMakeLists.txt
new file mode 100644
index 000000000..d1827372f
--- /dev/null
+++ b/src/Native/System.Private.TypeLoader.Native/CMakeLists.txt
@@ -0,0 +1,45 @@
+if(WIN32)
+ set(ASM_SUFFIX asm)
+
+ if(CLR_CMAKE_PLATFORM_ARCH_AMD64)
+ set(ARCH_SOURCES_DIR amd64)
+ elseif(CLR_CMAKE_PLATFORM_ARCH_I386)
+ set(ARCH_SOURCES_DIR i386)
+ endif()
+
+else()
+
+ set(ASM_SUFFIX S)
+
+ if(CLR_CMAKE_PLATFORM_ARCH_AMD64)
+ set(ARCH_SOURCES_DIR amd64)
+ elseif(CLR_CMAKE_PLATFORM_ARCH_ARM64)
+ set(ARCH_SOURCES_DIR arm64)
+ elseif(CLR_CMAKE_PLATFORM_ARCH_ARM)
+ set(ARCH_SOURCES_DIR arm)
+ elseif(CLR_CMAKE_PLATFORM_ARCH_I386)
+ set(ARCH_SOURCES_DIR i386)
+ elseif(CLR_CMAKE_PLATFORM_ARCH_WASM)
+ set(ARCH_SOURCES_DIR wasm)
+ endif()
+
+endif()
+
+set(RUNTIME_SOURCES_ARCH_ASM
+ ${ARCH_SOURCES_DIR}/ConstrainedCallSupportHelpers.${ASM_SUFFIX}
+ ${ARCH_SOURCES_DIR}/MethodEntrypointStubs.${ASM_SUFFIX}
+ ${ARCH_SOURCES_DIR}/VTableResolver.${ASM_SUFFIX}
+)
+
+convert_to_absolute_path(RUNTIME_SOURCES_ARCH_ASM ${RUNTIME_SOURCES_ARCH_ASM})
+
+add_library(System.Private.TypeLoader.Native
+ STATIC
+ ${RUNTIME_SOURCES_ARCH_ASM}
+)
+
+if (CMAKE_SYSTEM_NAME STREQUAL Linux)
+ target_link_libraries(System.Private.TypeLoader.Native rt)
+endif ()
+
+install (TARGETS System.Private.TypeLoader.Native DESTINATION sdk)
diff --git a/src/Native/System.Private.TypeLoader.Native/amd64/ConstrainedCallSupportHelpers.S b/src/Native/System.Private.TypeLoader.Native/amd64/ConstrainedCallSupportHelpers.S
new file mode 100644
index 000000000..bca35df81
--- /dev/null
+++ b/src/Native/System.Private.TypeLoader.Native/amd64/ConstrainedCallSupportHelpers.S
@@ -0,0 +1,12 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.intel_syntax noprefix
+
+#include <../../Runtime/unix/unixasmmacros.inc>
+
+LEAF_ENTRY ConstrainedCallSupport_GetStubs, _TEXT
+ // TODO: implement
+ ret
+LEAF_END ConstrainedCallSupport_GetStubs, _TEXT
diff --git a/src/Native/System.Private.TypeLoader.Native/amd64/ConstrainedCallSupportHelpers.asm b/src/Native/System.Private.TypeLoader.Native/amd64/ConstrainedCallSupportHelpers.asm
new file mode 100644
index 000000000..4d22d914c
--- /dev/null
+++ b/src/Native/System.Private.TypeLoader.Native/amd64/ConstrainedCallSupportHelpers.asm
@@ -0,0 +1,85 @@
+;; Licensed to the .NET Foundation under one or more agreements.
+;; The .NET Foundation licenses this file to you under the MIT license.
+;; See the LICENSE file in the project root for more information.
+
+;; -----------------------------------------------------------------------------------------------------------
+;; #include "asmmacros.inc"
+;; -----------------------------------------------------------------------------------------------------------
+
+LEAF_ENTRY macro Name, Section
+ Section segment para 'CODE'
+ align 16
+ public Name
+ Name proc
+endm
+
+LEAF_END macro Name, Section
+ Name endp
+ Section ends
+endm
+
+; - TAILCALL_RAX: ("jmp rax") should be used for tailcalls, this emits an instruction
+; sequence which is recognized by the unwinder as a valid epilogue terminator
+TAILJMP_RAX TEXTEQU <DB 048h, 0FFh, 0E0h>
+POINTER_SIZE equ 08h
+
+;;
+;; Note: The "__jmpstub__" prefix is used to indicate to debugger
+;; that it must step-through this stub when it encounters it while
+;; stepping.
+;;
+
+;;
+;; __jmpstub__ConstrainedCallSupport_DerefThisAndCall_CommonCallingStub
+;;
+;; r10 - AddressOfAddressOfFunctionToCallAfterDereferencingThis
+;;
+LEAF_ENTRY __jmpstub__ConstrainedCallSupport_DerefThisAndCall_CommonCallingStub, _TEXT
+ mov rax, [r10] ; Tail jumps go through RAX, so copy function pointer there
+ mov rcx, [rcx] ; Deference this to get real function pointer
+ TAILJMP_RAX
+LEAF_END __jmpstub__ConstrainedCallSupport_DerefThisAndCall_CommonCallingStub, _TEXT
+
+;;
+;; void ConstrainedCallSupport_GetStubs(IntPtr *__jmpstub__ConstrainedCallSupport_DerefThisAndCall_CommonCallingStub,
+;; IntPtr *__jmpstub__ConstrainedCallSupport_DirectConstrainedCallCommonStub)
+;;
+LEAF_ENTRY ConstrainedCallSupport_GetStubs, _TEXT
+ lea rax, [__jmpstub__ConstrainedCallSupport_DerefThisAndCall_CommonCallingStub]
+ mov [rcx], rax
+ lea rax, [__jmpstub__ConstrainedCallSupport_DirectConstrainedCallCommonStub]
+ mov [rdx], rax
+ ret
+LEAF_END ConstrainedCallSupport_GetStubs, _TEXT
+
+;;
+;; __jmpstub__ConstrainedCallSupport_DirectConstrainedCallCommonStub
+;;
+;; struct ConstrainedCallDesc
+;; {
+;; ULONG_PTR ExactTarget;
+;; ULONG_PTR LookupFunc; // Put UniversalThunk here
+;; }
+;;
+;; struct CommonCallingStubInputData
+;; {
+;; ULONG_PTR ConstrainedCallDesc;
+;; ULONG_PTR DirectConstrainedCallResolver;
+;; }
+;;
+;; r10 - Points at CommonCallingStubInputData
+;;
+;;
+LEAF_ENTRY __jmpstub__ConstrainedCallSupport_DirectConstrainedCallCommonStub, _TEXT
+ mov r11, [r10] ; put ConstrainedCallDesc into r11 (Arg to LookupFunc/Temp for getting ExactTarget)
+ mov rax, [r11] ; put ExactTarget into rax
+ test rax, rax ; compare against null
+ jnz JumpToTarget ; if not null, we don't need to call helper to get result. Just jump
+ ; If we reach here, we need to use a universal thunk to call the LookupFunc
+ mov rax, [r11 + POINTER_SIZE] ; Get Universal thunk function pointer into rax
+ mov r10, [r10 + POINTER_SIZE] ; Put DirectConstrainedCallResolver into r10 for UniversalTransitionThunk call
+JumpToTarget:
+ TAILJMP_RAX
+LEAF_END __jmpstub__ConstrainedCallSupport_DirectConstrainedCallCommonStub, _TEXT
+
+end
diff --git a/src/Native/System.Private.TypeLoader.Native/amd64/MethodEntrypointStubs.S b/src/Native/System.Private.TypeLoader.Native/amd64/MethodEntrypointStubs.S
new file mode 100644
index 000000000..4071c4038
--- /dev/null
+++ b/src/Native/System.Private.TypeLoader.Native/amd64/MethodEntrypointStubs.S
@@ -0,0 +1,12 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.intel_syntax noprefix
+
+#include <../../Runtime/unix/unixasmmacros.inc>
+
+LEAF_ENTRY MethodEntrypointStubs_SetupPointers, _TEXT
+ // TODO: implement
+ ret
+LEAF_END MethodEntrypointStubs_SetupPointers, _TEXT
diff --git a/src/Native/System.Private.TypeLoader.Native/amd64/MethodEntrypointStubs.asm b/src/Native/System.Private.TypeLoader.Native/amd64/MethodEntrypointStubs.asm
new file mode 100644
index 000000000..f0c212b12
--- /dev/null
+++ b/src/Native/System.Private.TypeLoader.Native/amd64/MethodEntrypointStubs.asm
@@ -0,0 +1,67 @@
+;; Licensed to the .NET Foundation under one or more agreements.
+;; The .NET Foundation licenses this file to you under the MIT license.
+;; See the LICENSE file in the project root for more information.
+
+LEAF_ENTRY macro Name, Section
+ Section segment para 'CODE'
+ align 16
+ public Name
+ Name proc
+endm
+
+LEAF_END macro Name, Section
+ Name endp
+ Section ends
+endm
+
+.data
+
+g_methodEntrypointThunk qword 0 ; The method which operates on universal transition
+g_universalTransition qword 0 ; The address of Redhawk's UniversalTransition thunk
+
+.code
+
+; - TAILCALL_RAX: ("jmp rax") should be used for tailcalls, this emits an instruction
+; sequence which is recognized by the unwinder as a valid epilogue terminator
+TAILJMP_RAX TEXTEQU <DB 048h, 0FFh, 0E0h>
+
+PointerSize equ 8
+
+;;
+;; __jmpstub__MethodEntrypointStubs_CommonCallingStub(?)
+;; Used when we dynamically need a VTableResolver not pre-generated
+;;
+;; r10 contains a pointer to a VTableResolverStruct
+;; struct MethodEntryPointStubInfo
+;; {
+;; IntPtr targetCodePointer;
+;; IntPtr MethodEntrypointStructPointer;
+;; };
+;;
+LEAF_ENTRY __jmpstub__MethodEntrypointStubs_CommonCallingStub, _TEXT
+ ;; r10 <- stub info
+ mov rax, [r10]
+ cmp rax, 0
+ je SLOW_PATH
+ mov rax, [r10]
+ TAILJMP_RAX
+SLOW_PATH:
+ mov r11, [r10 + 8]
+ mov r10, g_methodEntrypointThunk
+ mov rax, g_universalTransition
+ TAILJMP_RAX
+LEAF_END __jmpstub__MethodEntrypointStubs_CommonCallingStub, _TEXT
+
+;; Returns the size of the pre-generated thunks
+;; IntPtr MethodEntrypointStubs_SetupPointers(
+;; IntPtr universalTransition,
+;; IntPtr methodEntrypointThunk)
+;;
+LEAF_ENTRY MethodEntrypointStubs_SetupPointers, _TEXT
+ mov g_universalTransition, rcx
+ mov g_methodEntrypointThunk, rdx
+ lea rax, [__jmpstub__MethodEntrypointStubs_CommonCallingStub]
+ ret
+LEAF_END MethodEntrypointStubs_SetupPointers, _TEXT
+
+end
diff --git a/src/Native/System.Private.TypeLoader.Native/amd64/VTableResolver.S b/src/Native/System.Private.TypeLoader.Native/amd64/VTableResolver.S
new file mode 100644
index 000000000..cc2d7068b
--- /dev/null
+++ b/src/Native/System.Private.TypeLoader.Native/amd64/VTableResolver.S
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.intel_syntax noprefix
+
+#include <../../Runtime/unix/unixasmmacros.inc>
+
+LEAF_ENTRY VTableResolver_Init, _TEXT
+ // TODO: implement
+ ret
+LEAF_END VTableResolver_Init, _TEXT
+
+LEAF_ENTRY VTableResolver_GetCommonCallingStub, _TEXT
+ // TODO: implement
+ ret
+LEAF_END VTableResolver_GetCommonCallingStub, _TEXT
diff --git a/src/Native/System.Private.TypeLoader.Native/amd64/VTableResolver.asm b/src/Native/System.Private.TypeLoader.Native/amd64/VTableResolver.asm
new file mode 100644
index 000000000..8f540bdcc
--- /dev/null
+++ b/src/Native/System.Private.TypeLoader.Native/amd64/VTableResolver.asm
@@ -0,0 +1,221 @@
+;; Licensed to the .NET Foundation under one or more agreements.
+;; The .NET Foundation licenses this file to you under the MIT license.
+;; See the LICENSE file in the project root for more information.
+
+LEAF_ENTRY macro Name, Section
+ Section segment para 'CODE'
+ align 16
+ public Name
+ Name proc
+endm
+
+LEAF_END macro Name, Section
+ Name endp
+ Section ends
+endm
+
+.data
+
+g_vtableResolveCallback qword 0 ; The vtableresolve method
+g_universalTransition qword 0 ; The address of Redhawk's UniversalTransition thunk
+
+.code
+
+; - TAILCALL_RAX: ("jmp rax") should be used for tailcalls, this emits an instruction
+; sequence which is recognized by the unwinder as a valid epilogue terminator
+TAILJMP_RAX TEXTEQU <DB 048h, 0FFh, 0E0h>
+
+;;
+;; When an EEType is created its vTable entries will be initially filled with calls to the vTableThunk for the appropriate
+;; slot number. When the thunk is invoked it'll check to see if the slot has already been resolved. If so then just call
+;; the universal thunk, otherwise call to do the resolution which will also update the vtable slot and then call
+;; the universal thunk
+;;
+
+VTableThunkSize equ 30h
+;; TODO - do something similar to Redhawk's asmoffsets to compute the value at compile time
+EETypeVTableOffset equ 18h
+PointerSize equ 8
+
+;;
+;; __jmpstub__VTableResolver_CommonCallingStub(?)
+;; Used when we dynamically need a VTableResolver not pre-generated
+;;
+;; r10 contains a pointer to a VTableResolverStruct
+;; struct VTableResolverStruct
+;; {
+;; int offsetFromStartOfEETypePtr;
+;; IntPtr VTableThunkAddress;
+;; };
+;;
+LEAF_ENTRY __jmpstub__VTableResolver_CommonCallingStub, _TEXT
+ ;; r10 <- stub info
+ ;; rcx is the this pointer to the call being made
+ mov rax, [rcx]
+ ;; rax is the EEType pointer add the VTableOffset + slot_number * pointer size to get the vtable entry
+ mov r11, [r10]
+ ;; r11 now has offset from start of EEType to interesting slot
+
+ ;; compare the that value to the address of the thunk being executed and if the values are equal then
+ ;; call to the resolver otherwise call the method
+
+ mov rax, [rax + r11]
+ cmp rax, [r10 + 8]
+ je SLOW_DYNAMIC_STUB
+ TAILJMP_RAX
+SLOW_DYNAMIC_STUB:
+ mov r10, g_vtableResolveCallback
+ mov rax, g_universalTransition
+ TAILJMP_RAX
+LEAF_END __jmpstub__VTableResolver_CommonCallingStub, _TEXT
+
+;; Returns the size of the pre-generated thunks
+;; int VTableResolver_Init(IntPtr *__jmpstub__VTableResolverSlot0,
+;; IntPtr vtableResolveCallback,
+;; IntPtr universalTransition,
+;; int *slotCount)
+;;
+LEAF_ENTRY VTableResolver_Init, _TEXT
+ lea rax, [__jmpstub__VTableSlot0]
+ mov [rcx], rax
+ mov g_vtableResolveCallback, rdx
+ mov g_universalTransition, r8
+ mov rax, 100 ;; 100 Pregenerated Stubs
+ mov [r9], rax
+ mov rax, VTableThunkSize ;; Thunk size
+ ret
+LEAF_END VTableResolver_Init, _TEXT
+
+;; void* VTableResolver_GetCommonCallingStub()
+;; - Get the address of the common calling stub
+LEAF_ENTRY VTableResolver_GetCommonCallingStub, _TEXT
+ lea rax, [__jmpstub__VTableResolver_CommonCallingStub]
+ ret
+LEAF_END VTableResolver_GetCommonCallingStub, _TEXT
+
+VTableThunkDecl macro name, slot_number
+
+LEAF_ENTRY name, _TEXT
+ALIGN 16 ; The alignment here forces the thunks to be the same size which gives all of the macros the same size and allows us to index
+ ;; rcx is the this pointer to the call being made
+ mov rax, [rcx]
+ mov r11, EETypeVTableOffset + slot_number * PointerSize
+ ;; rax is the EEType pointer add the VTableOffset + slot_number * pointer size to get the vtable entry
+ ;; compare the that value to the address of the thunk being executed and if the values are equal then
+ ;; call to the resolver otherwise call the method
+ mov rax, [rax + r11]
+ lea r10, name
+ cmp rax, r10
+ je SLOW
+ TAILJMP_RAX
+SLOW:
+ ;; r11 is already set to the EEType offset
+ mov r10, g_vtableResolveCallback
+ mov rax, g_universalTransition
+ TAILJMP_RAX
+LEAF_END name, _TEXT
+
+ endm
+
+VTableThunkDecl __jmpstub__VTableSlot0,0
+VTableThunkDecl __jmpstub__VTableSlot1,1
+VTableThunkDecl __jmpstub__VTableSlot2,2
+VTableThunkDecl __jmpstub__VTableSlot3,3
+VTableThunkDecl __jmpstub__VTableSlot4,4
+VTableThunkDecl __jmpstub__VTableSlot5,5
+VTableThunkDecl __jmpstub__VTableSlot6,6
+VTableThunkDecl __jmpstub__VTableSlot7,7
+VTableThunkDecl __jmpstub__VTableSlot8,8
+VTableThunkDecl __jmpstub__VTableSlot9,9
+VTableThunkDecl __jmpstub__VTableSlot10,10
+VTableThunkDecl __jmpstub__VTableSlot11,11
+VTableThunkDecl __jmpstub__VTableSlot12,12
+VTableThunkDecl __jmpstub__VTableSlot13,13
+VTableThunkDecl __jmpstub__VTableSlot14,14
+VTableThunkDecl __jmpstub__VTableSlot15,15
+VTableThunkDecl __jmpstub__VTableSlot16,16
+VTableThunkDecl __jmpstub__VTableSlot17,17
+VTableThunkDecl __jmpstub__VTableSlot18,18
+VTableThunkDecl __jmpstub__VTableSlot19,19
+VTableThunkDecl __jmpstub__VTableSlot20,20
+VTableThunkDecl __jmpstub__VTableSlot21,21
+VTableThunkDecl __jmpstub__VTableSlot22,22
+VTableThunkDecl __jmpstub__VTableSlot23,23
+VTableThunkDecl __jmpstub__VTableSlot24,24
+VTableThunkDecl __jmpstub__VTableSlot25,25
+VTableThunkDecl __jmpstub__VTableSlot26,26
+VTableThunkDecl __jmpstub__VTableSlot27,27
+VTableThunkDecl __jmpstub__VTableSlot28,28
+VTableThunkDecl __jmpstub__VTableSlot29,29
+VTableThunkDecl __jmpstub__VTableSlot30,30
+VTableThunkDecl __jmpstub__VTableSlot31,31
+VTableThunkDecl __jmpstub__VTableSlot32,32
+VTableThunkDecl __jmpstub__VTableSlot33,33
+VTableThunkDecl __jmpstub__VTableSlot34,34
+VTableThunkDecl __jmpstub__VTableSlot35,35
+VTableThunkDecl __jmpstub__VTableSlot36,36
+VTableThunkDecl __jmpstub__VTableSlot37,37
+VTableThunkDecl __jmpstub__VTableSlot38,38
+VTableThunkDecl __jmpstub__VTableSlot39,39
+VTableThunkDecl __jmpstub__VTableSlot40,40
+VTableThunkDecl __jmpstub__VTableSlot41,41
+VTableThunkDecl __jmpstub__VTableSlot42,42
+VTableThunkDecl __jmpstub__VTableSlot43,43
+VTableThunkDecl __jmpstub__VTableSlot44,44
+VTableThunkDecl __jmpstub__VTableSlot45,45
+VTableThunkDecl __jmpstub__VTableSlot46,46
+VTableThunkDecl __jmpstub__VTableSlot47,47
+VTableThunkDecl __jmpstub__VTableSlot48,48
+VTableThunkDecl __jmpstub__VTableSlot49,49
+VTableThunkDecl __jmpstub__VTableSlot50,50
+VTableThunkDecl __jmpstub__VTableSlot51,51
+VTableThunkDecl __jmpstub__VTableSlot52,52
+VTableThunkDecl __jmpstub__VTableSlot53,53
+VTableThunkDecl __jmpstub__VTableSlot54,54
+VTableThunkDecl __jmpstub__VTableSlot55,55
+VTableThunkDecl __jmpstub__VTableSlot56,56
+VTableThunkDecl __jmpstub__VTableSlot57,57
+VTableThunkDecl __jmpstub__VTableSlot58,58
+VTableThunkDecl __jmpstub__VTableSlot59,59
+VTableThunkDecl __jmpstub__VTableSlot60,60
+VTableThunkDecl __jmpstub__VTableSlot61,61
+VTableThunkDecl __jmpstub__VTableSlot62,62
+VTableThunkDecl __jmpstub__VTableSlot63,63
+VTableThunkDecl __jmpstub__VTableSlot64,64
+VTableThunkDecl __jmpstub__VTableSlot65,65
+VTableThunkDecl __jmpstub__VTableSlot66,66
+VTableThunkDecl __jmpstub__VTableSlot67,67
+VTableThunkDecl __jmpstub__VTableSlot68,68
+VTableThunkDecl __jmpstub__VTableSlot69,69
+VTableThunkDecl __jmpstub__VTableSlot70,70
+VTableThunkDecl __jmpstub__VTableSlot71,71
+VTableThunkDecl __jmpstub__VTableSlot72,72
+VTableThunkDecl __jmpstub__VTableSlot73,73
+VTableThunkDecl __jmpstub__VTableSlot74,74
+VTableThunkDecl __jmpstub__VTableSlot75,75
+VTableThunkDecl __jmpstub__VTableSlot76,76
+VTableThunkDecl __jmpstub__VTableSlot77,77
+VTableThunkDecl __jmpstub__VTableSlot78,78
+VTableThunkDecl __jmpstub__VTableSlot79,79
+VTableThunkDecl __jmpstub__VTableSlot80,80
+VTableThunkDecl __jmpstub__VTableSlot81,81
+VTableThunkDecl __jmpstub__VTableSlot82,82
+VTableThunkDecl __jmpstub__VTableSlot83,83
+VTableThunkDecl __jmpstub__VTableSlot84,84
+VTableThunkDecl __jmpstub__VTableSlot85,85
+VTableThunkDecl __jmpstub__VTableSlot86,86
+VTableThunkDecl __jmpstub__VTableSlot87,87
+VTableThunkDecl __jmpstub__VTableSlot88,88
+VTableThunkDecl __jmpstub__VTableSlot89,89
+VTableThunkDecl __jmpstub__VTableSlot90,90
+VTableThunkDecl __jmpstub__VTableSlot91,91
+VTableThunkDecl __jmpstub__VTableSlot92,92
+VTableThunkDecl __jmpstub__VTableSlot93,93
+VTableThunkDecl __jmpstub__VTableSlot94,94
+VTableThunkDecl __jmpstub__VTableSlot95,95
+VTableThunkDecl __jmpstub__VTableSlot96,96
+VTableThunkDecl __jmpstub__VTableSlot97,97
+VTableThunkDecl __jmpstub__VTableSlot98,98
+VTableThunkDecl __jmpstub__VTableSlot99,99
+
+end
diff --git a/src/Native/System.Private.TypeLoader.Native/arm/ConstrainedCallSupportHelpers.S b/src/Native/System.Private.TypeLoader.Native/arm/ConstrainedCallSupportHelpers.S
new file mode 100644
index 000000000..71cd483ce
--- /dev/null
+++ b/src/Native/System.Private.TypeLoader.Native/arm/ConstrainedCallSupportHelpers.S
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.syntax unified
+.thumb
+
+#include <../../Runtime/unix/unixasmmacros.inc>
+
+LEAF_ENTRY ConstrainedCallSupport_GetStubs, _TEXT
+ // TODO: implement
+ bx lr
+LEAF_END ConstrainedCallSupport_GetStubs, _TEXT
diff --git a/src/Native/System.Private.TypeLoader.Native/arm/ConstrainedCallSupportHelpers.asm b/src/Native/System.Private.TypeLoader.Native/arm/ConstrainedCallSupportHelpers.asm
new file mode 100644
index 000000000..1f04e2a43
--- /dev/null
+++ b/src/Native/System.Private.TypeLoader.Native/arm/ConstrainedCallSupportHelpers.asm
@@ -0,0 +1,78 @@
+;; Licensed to the .NET Foundation under one or more agreements.
+;; The .NET Foundation licenses this file to you under the MIT license.
+;; See the LICENSE file in the project root for more information.
+
+#include "kxarm.h"
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DATA SECTIONS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ConstrainedCall Support Helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;
+;; Note: The "__jmpstub__" prefix is used to indicate to debugger
+;; that it must step-through this stub when it encounters it while
+;; stepping.
+;;
+ ;;
+ ;; sp-4 - AddressOfAddressOfFunctionToCallAfterDereferencingThis
+ ;;
+ LEAF_ENTRY __jmpstub__ConstrainedCallSupport_DerefThisAndCall_CommonCallingStub
+ ldr r12, [sp, #-4]
+ ldr r12, [r12]
+ ldr r0, [r0]
+ bx r12
+ LEAF_END __jmpstub__ConstrainedCallSupport_DerefThisAndCall_CommonCallingStub
+
+;;
+;; void ConstrainedCallSupport_GetStubs(IntPtr *__jmpstub__ConstrainedCallSupport_DerefThisAndCall_CommonCallingStub,
+;; IntPtr *__jmpstub__ConstrainedCallSupport_DirectConstrainedCallCommonStub)
+;;
+ LEAF_ENTRY ConstrainedCallSupport_GetStubs
+ ldr r12, =__jmpstub__ConstrainedCallSupport_DerefThisAndCall_CommonCallingStub
+ str r12, [r0]
+ ldr r12, =__jmpstub__ConstrainedCallSupport_DirectConstrainedCallCommonStub
+ str r12, [r1]
+ bx lr
+ LEAF_END ConstrainedCallSupport_GetStubs
+
+;;
+;; __jmpstub__ConstrainedCallSupport_DirectConstrainedCallCommonStub
+;;
+;; struct ConstrainedCallDesc
+;; {
+;; ULONG_PTR ExactTarget;
+;; ULONG_PTR LookupFunc; // Put UniversalThunk here
+;; }
+;;
+;; struct CommonCallingStubInputData
+;; {
+;; ULONG_PTR ConstrainedCallDesc;
+;; ULONG_PTR DirectConstrainedCallResolver;
+;; }
+;;
+;; sp-4 - Points at CommonCallingStubInputData
+;;
+;;
+ LEAF_ENTRY __jmpstub__ConstrainedCallSupport_DirectConstrainedCallCommonStub
+ ldr r12, [sp, #-4] ; put CommonCallingStubInputData into r12 (Temp for getting ExactTarget)
+ ldr r12, [r12] ; put ConstrainedCallDesc into r12 (Temp for getting ExactTarget)
+ ldr r12, [r12] ; put ExactTarget into r12
+ cmp r12, 0 ; Is ExactTarget null?
+ beq NeedHelperCall ; if null use a helper call
+ bx r12 ; Otherwise tail-call the ExactTarget
+NeedHelperCall
+ ;; Setup arguments for UniversalThunk and call it.
+ ldr r12, [sp, #-4] ; put CommonCallingStubInputData into r12 (Temp for getting ConstrainedCallDesc)
+ ldr r12, [r12] ; put ConstrainedCallDesc into r12
+ str r12, [sp, #-8] ; put ConstrainedCallDesc into sp-8 (red zone location of custom calling convention for universal thunk)
+
+ ldr r12, [sp, #-4] ; put CommonCallingStubInputData into r12 (Temp for getting DirectConstrainedCallResolver)
+ ldr r12, [r12, #4] ; put DirectConstrainedCallResolver into r12
+ str r12, [sp, #-4] ; put DirectConstrainedCallResolver into sp-4 (red zone location of custom calling convention for universal thunk)
+
+ ldr r12, [sp, #-8] ; put ConstrainedCallDesc into r12 (Temp for getting ExactTarget)
+ ldr r12, [r12, #4] ; put LookupFunc into r12 (This should be universal thunk pointer)
+ bx r12 ; Tail-Call Universal thunk
+ LEAF_END __jmpstub__ConstrainedCallSupport_DirectConstrainedCallCommonStub
+
+ END
diff --git a/src/Native/System.Private.TypeLoader.Native/arm/MethodEntrypointStubs.S b/src/Native/System.Private.TypeLoader.Native/arm/MethodEntrypointStubs.S
new file mode 100644
index 000000000..0df54c492
--- /dev/null
+++ b/src/Native/System.Private.TypeLoader.Native/arm/MethodEntrypointStubs.S
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.syntax unified
+.thumb
+
+#include <../../Runtime/unix/unixasmmacros.inc>
+
+LEAF_ENTRY MethodEntrypointStubs_SetupPointers, _TEXT
+ // TODO: implement
+ bx lr
+LEAF_END MethodEntrypointStubs_SetupPointers, _TEXT
diff --git a/src/Native/System.Private.TypeLoader.Native/arm/MethodEntrypointStubs.asm b/src/Native/System.Private.TypeLoader.Native/arm/MethodEntrypointStubs.asm
new file mode 100644
index 000000000..0e0cdcc5d
--- /dev/null
+++ b/src/Native/System.Private.TypeLoader.Native/arm/MethodEntrypointStubs.asm
@@ -0,0 +1,5 @@
+;; Licensed to the .NET Foundation under one or more agreements.
+;; The .NET Foundation licenses this file to you under the MIT license.
+;; See the LICENSE file in the project root for more information.
+
+ END
diff --git a/src/Native/System.Private.TypeLoader.Native/arm/VTableResolver.S b/src/Native/System.Private.TypeLoader.Native/arm/VTableResolver.S
new file mode 100644
index 000000000..7d6275242
--- /dev/null
+++ b/src/Native/System.Private.TypeLoader.Native/arm/VTableResolver.S
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+.syntax unified
+.thumb
+
+#include <../../Runtime/unix/unixasmmacros.inc>
+
+LEAF_ENTRY VTableResolver_Init, _TEXT
+ // TODO: implement
+ bx lr
+LEAF_END VTableResolver_Init, _TEXT
+
+LEAF_ENTRY VTableResolver_GetCommonCallingStub, _TEXT
+ // TODO: implement
+ bx lr
+LEAF_END VTableResolver_GetCommonCallingStub, _TEXT
diff --git a/src/Native/System.Private.TypeLoader.Native/arm/VTableResolver.asm b/src/Native/System.Private.TypeLoader.Native/arm/VTableResolver.asm
new file mode 100644
index 000000000..36e244e93
--- /dev/null
+++ b/src/Native/System.Private.TypeLoader.Native/arm/VTableResolver.asm
@@ -0,0 +1,163 @@
+;; Licensed to the .NET Foundation under one or more agreements.
+;; The .NET Foundation licenses this file to you under the MIT license.
+;; See the LICENSE file in the project root for more information.
+
+#include "kxarm.h"
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DATA SECTIONS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ DATAAREA
+
+g_vtableResolveCallback DCD 0 ; The vtableresolve method
+ EXPORT g_vtableResolveCallback
+g_universalTransition DCD 0 ; The address of Redhawk's UniversalTransition thunk
+
+#define VTableThunkSize 0x20
+;; TODO - do something similar to Redhawk's asmoffsets to compute the value at compile time
+#define EETypeVTableOffset 0x14
+#define PointerSize 4
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ConstrainedCall Support Helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ TEXTAREA
+;;
+;; Note: The "__jmpstub__" prefix is used to indicate to debugger
+;; that it must step-through this stub when it encounters it while
+;; stepping.
+;;
+
+;; Returns the size of the pre-generated thunks
+;; int VTableResolver_Init(IntPtr *__jmpstub__VTableResolverSlot0,
+;; IntPtr vtableResolveCallback,
+;; IntPtr universalTransition,
+;; int *slotCount)
+;;
+ LEAF_ENTRY VTableResolver_Init
+ ldr r12, __jmpstub__VTableSlot000
+ add r12, r12, 1 ; Add thumb bit
+ str r12, [r0]
+ ldr r12, =g_vtableResolveCallback
+ str r1, [r12]
+ ldr r12, =g_universalTransition
+ str r2, [r12]
+ mov r12, 100 ; This file defines 100 slot helpers
+ str r12, [r3]
+ mov r0, VTableThunkSize ; Each thunk is VTableThunkSize in bytes
+ bx lr
+ LEAF_END VTableResolver_Init
+
+;; void* VTableResolver_GetCommonCallingStub()
+;; - Get the address of the common calling stub
+ LEAF_ENTRY VTableResolver_GetCommonCallingStub
+ ldr r0, __jmpstub__VTableResolver_CommonCallingStub
+ bx lr
+ LEAF_END VTableResolver_GetCommonCallingStub
+
+;;
+;; __jmpstub__VTableResolver_CommonCallingStub(?)
+;; Used when we dynamically need a VTableResolver not pre-generated
+;;
+;; sp-4 contains a pointer to a VTableResolverStruct
+;; struct VTableResolverStruct
+;; {
+;; int offsetFromStartOfEETypePtr;
+;; IntPtr VTableThunkAddress;
+;; };
+;;
+ LEAF_ENTRY __jmpstub__VTableResolver_CommonCallingStub
+ ;; Custom calling convention:
+ ;; red zone has pointer to the VTableResolverStruct
+ ;; Copy red zone value into r12 so that the PROLOG_PUSH doesn't destroy it
+ PROLOG_NOP ldr r12, [sp, #-4]
+ PROLOG_PUSH {r3}
+ PROLOG_PUSH {r1-r2}
+ ldr r2, [r0]
+ ;; r2 is the EEType pointer add the VTableOffset + slot_number * pointer size to get the vtable entry
+ ;; compare the that value to the address of the thunk being executed and if the values are equal then
+ ;; call to the resolver otherwise call the method
+ ldr r1, [r12]
+ ;; r1 is the offset from start of EEType to interesting slot
+ ldr r3, [r2,r1]
+ ;; r3 is now the function pointer in the vtable
+ ldr r2,[r12,#4]
+ ;; is now the address of the function pointer that serves as the entry point for this particular instantiation
+ ;; of __jmpstub__VTableResolver_CommonCallingStub
+ cmp r2,r3
+ beq __jmpstub__JumpToVTableResolver
+ mov r12,r3 ; Move the target function pointer to r12
+ EPILOG_POP {r1,r2}
+ EPILOG_POP {r3}
+ EPILOG_BRANCH_REG r12
+ LEAF_END __jmpstub__VTableResolver_CommonCallingStub
+
+;; stub for dispatch will come in with r1 set to EETypeVTableOffset + ($slot_number * PointerSize),
+;; and r1, r2 and r3 of the function we really want to call pushed on the stack
+ LEAF_ENTRY __jmpstub__JumpToVTableResolver
+ mov r3, r1
+ POP {r1,r2}
+ str r3, [sp, #-4] ; Store slot number into red zone at appropriate spot
+ POP {r3}
+ ldr r12, =g_vtableResolveCallback
+ ldr r12, [r12]
+ str r12, [sp, #-4] ; Store vtable resolve callback into red zone
+ ldr r12, =g_universalTransition
+ ldr r12, [r12]
+ bx r12
+ LEAF_END __jmpstub__VTableResolver_Init
+
+
+ MACRO
+ VTableThunkDecl $name, $slot_number
+ ALIGN 16 ; The alignment here forces the thunks to be the same size which gives all of the macros the same size and allows us to index
+ LEAF_ENTRY __jmpstub__$name
+ ;; rcx is the this pointer to the call being made
+ PUSH {r3}
+ PUSH {r1,r2} ; Push r1,r2
+ ldr r2, [r0]
+ ;; r2 is the EEType pointer add the VTableOffset + slot_number * pointer size to get the vtable entry
+ ;; compare the that value to the address of the thunk being executed and if the values are equal then
+ ;; call to the resolver otherwise call the method
+ mov r1, EETypeVTableOffset + ($slot_number * PointerSize)
+ ldr r3, [r2,r1]
+ ; r3 is now the function pointer in the vtable
+ ldr r2,=__jmpstub__$name
+ cmp r2,r3
+ beq JumpVTableResolver$name
+ mov r12,r3 ; Move the target function pointer to r12 before popping r2 and r3. We used r3 instead of r12 here so that
+ ; we could use the 2 byte thumb instructions and the whole thunk could fit in less than 32 bytes
+ POP {r1,r2,r3}
+ bx r12
+JumpVTableResolver$name
+ b __jmpstub__JumpToVTableResolver
+ LEAF_END __jmpstub__$name
+ MEND
+
+ MACRO
+ VTableThunkDeclTen $slotnumberDecimal
+ VTableThunkDecl VTableSlot$slotnumberDecimal0,$slotnumberDecimal0
+ VTableThunkDecl VTableSlot$slotnumberDecimal1,$slotnumberDecimal1
+ VTableThunkDecl VTableSlot$slotnumberDecimal2,$slotnumberDecimal2
+ VTableThunkDecl VTableSlot$slotnumberDecimal3,$slotnumberDecimal3
+ VTableThunkDecl VTableSlot$slotnumberDecimal4,$slotnumberDecimal4
+ VTableThunkDecl VTableSlot$slotnumberDecimal5,$slotnumberDecimal5
+ VTableThunkDecl VTableSlot$slotnumberDecimal6,$slotnumberDecimal6
+ VTableThunkDecl VTableSlot$slotnumberDecimal7,$slotnumberDecimal7
+ VTableThunkDecl VTableSlot$slotnumberDecimal8,$slotnumberDecimal8
+ VTableThunkDecl VTableSlot$slotnumberDecimal9,$slotnumberDecimal9
+ MEND
+
+ MACRO
+ VTableThunkDeclHundred $slotnumberPerHundred
+ VTableThunkDeclTen $slotnumberPerHundred0
+ VTableThunkDeclTen $slotnumberPerHundred1
+ VTableThunkDeclTen $slotnumberPerHundred2
+ VTableThunkDeclTen $slotnumberPerHundred3
+ VTableThunkDeclTen $slotnumberPerHundred4
+ VTableThunkDeclTen $slotnumberPerHundred5
+ VTableThunkDeclTen $slotnumberPerHundred6
+ VTableThunkDeclTen $slotnumberPerHundred7
+ VTableThunkDeclTen $slotnumberPerHundred8
+ VTableThunkDeclTen $slotnumberPerHundred9
+ MEND
+
+ VTableThunkDeclHundred 0
+
+ END
diff --git a/src/Native/System.Private.TypeLoader.Native/arm64/ConstrainedCallSupportHelpers.asm b/src/Native/System.Private.TypeLoader.Native/arm64/ConstrainedCallSupportHelpers.asm
new file mode 100644
index 000000000..f38b392c4
--- /dev/null
+++ b/src/Native/System.Private.TypeLoader.Native/arm64/ConstrainedCallSupportHelpers.asm
@@ -0,0 +1,67 @@
+;; Licensed to the .NET Foundation under one or more agreements.
+;; The .NET Foundation licenses this file to you under the MIT license.
+;; See the LICENSE file in the project root for more information.
+
+#include "ksarm64.h"
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DATA SECTIONS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+POINTER_SIZE equ 0x08
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ConstrainedCall Support Helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;
+;; Note: The "__jmpstub__" prefix is used to indicate to debugger
+;; that it must step-through this stub when it encounters it while
+;; stepping.
+;;
+;; INPUT: xip0: AddressOfAddressOfFunctionToCallAfterDereferencingThis
+;;
+ LEAF_ENTRY __jmpstub__ConstrainedCallSupport_DerefThisAndCall_CommonCallingStub
+ ldr x12, [xip0] ; Load tail jump target
+ ldr x0, [x0] ; Dereference this to get real function pointer
+ ret x12
+ LEAF_END __jmpstub__ConstrainedCallSupport_DerefThisAndCall_CommonCallingStub
+
+;;
+;; void ConstrainedCallSupport_GetStubs(IntPtr *__jmpstub__ConstrainedCallSupport_DerefThisAndCall_CommonCallingStub,
+;; IntPtr *__jmpstub__ConstrainedCallSupport_DirectConstrainedCallCommonStub)
+;;
+ LEAF_ENTRY ConstrainedCallSupport_GetStubs
+ ldr x12, =__jmpstub__ConstrainedCallSupport_DerefThisAndCall_CommonCallingStub
+ str x12, [x0]
+ ldr x12, =__jmpstub__ConstrainedCallSupport_DirectConstrainedCallCommonStub
+ str x12, [x1]
+ ret
+ LEAF_END ConstrainedCallSupport_GetStubs
+
+;;
+;; __jmpstub__ConstrainedCallSupport_DirectConstrainedCallCommonStub
+;;
+;; struct ConstrainedCallDesc
+;; {
+;; ULONG_PTR ExactTarget;
+;; ULONG_PTR LookupFunc; // Put UniversalThunk here
+;; }
+;;
+;; struct CommonCallingStubInputData
+;; {
+;; ULONG_PTR ConstrainedCallDesc;
+;; ULONG_PTR DirectConstrainedCallResolver;
+;; }
+;;
+;; INPUT: xip0: Points at CommonCallingStubInputData
+;;
+;;
+ LEAF_ENTRY __jmpstub__ConstrainedCallSupport_DirectConstrainedCallCommonStub
+ ldr xip1, [xip0] ; put ConstrainedCallDesc into xip1 (Arg to LookupFunc/Temp for getting ExactTarget)
+ ldr x12, [xip1] ; put ExactTarget into x12
+ cbnz x12, JumpToTarget ; compare against null
+ ; If we reach here, we need to use a universal thunk to call the LookupFunc
+ ldr x12, [xip1, #POINTER_SIZE] ; Get Universal thunk function pointer into x12
+ ldr xip0, [xip0, #POINTER_SIZE] ; Put DirectConstrainedCallResolver into xip0 for UniversalTransitionThunk call
+JumpToTarget
+ ret x12
+ LEAF_END __jmpstub__ConstrainedCallSupport_DirectConstrainedCallCommonStub
+
+ END
diff --git a/src/Native/System.Private.TypeLoader.Native/arm64/MethodEntrypointStubs.asm b/src/Native/System.Private.TypeLoader.Native/arm64/MethodEntrypointStubs.asm
new file mode 100644
index 000000000..0e0cdcc5d
--- /dev/null
+++ b/src/Native/System.Private.TypeLoader.Native/arm64/MethodEntrypointStubs.asm
@@ -0,0 +1,5 @@
+;; Licensed to the .NET Foundation under one or more agreements.
+;; The .NET Foundation licenses this file to you under the MIT license.
+;; See the LICENSE file in the project root for more information.
+
+ END
diff --git a/src/Native/System.Private.TypeLoader.Native/arm64/VTableResolver.asm b/src/Native/System.Private.TypeLoader.Native/arm64/VTableResolver.asm
new file mode 100644
index 000000000..d22395850
--- /dev/null
+++ b/src/Native/System.Private.TypeLoader.Native/arm64/VTableResolver.asm
@@ -0,0 +1,155 @@
+;; Licensed to the .NET Foundation under one or more agreements.
+;; The .NET Foundation licenses this file to you under the MIT license.
+;; See the LICENSE file in the project root for more information.
+
+#include "kxarm64.h"
+
+ DATAAREA
+
+g_vtableResolveCallback DCQ 0 ; Address of virtual dispatch resolution callback
+g_universalTransition DCQ 0 ; Address of RhpUniversalTransition thunk
+
+VTableThunkSize EQU 0x20
+;; TODO - do something similar to Redhawk's asmoffsets to compute the value at compile time
+EETypeVTableOffset EQU 0x18
+PointerSize EQU 8
+
+ TEXTAREA
+
+;;
+;; When an EEType is created, its VTable entries are initially filled with calls to the VTableSlot thunks for the appropriate
+;; slot numbers. When the thunk is invoked, it checks whether the slot has already been resolved. If yes, then it just calls
+;; the universal thunk. Otherwise, it calls the dispatch resolution callback, which will update the VTable slot and then call
+;; the universal thunk.
+;;
+
+;;
+;; Note: The "__jmpstub__" prefix is used to indicate to debugger
+;; that it must step-through this stub when it encounters it while
+;; stepping.
+;;
+
+ ;; int VTableResolver_Init(IntPtr *__jmpstub__VTableResolverSlot0,
+ ;; IntPtr vtableResolveCallback,
+ ;; IntPtr universalTransition,
+ ;; int *slotCount)
+ ;; Returns the size of the pre-generated thunks.
+ ;;
+ LEAF_ENTRY VTableResolver_Init
+ adr x9, __jmpstub__VTableSlot00
+ str x9, [x0]
+ ADDROF x10, g_vtableResolveCallback
+ str x1, [x10]
+ ADDROF x11, g_universalTransition
+ str x2, [x11]
+ mov x12, 100 ; This file defines 100 slot helpers
+ str x12, [x3]
+ mov x0, VTableThunkSize ; Each thunk is VTableThunkSize in bytes
+ ret
+ LEAF_END VTableResolver_Init
+
+ ;; void* VTableResolver_GetCommonCallingStub()
+ ;; Returns the address of the common calling stub.
+ ;;
+ LEAF_ENTRY VTableResolver_GetCommonCallingStub
+ adr x0, __jmpstub__VTableResolver_CommonCallingStub
+ ret
+ LEAF_END VTableResolver_GetCommonCallingStub
+
+ ;; __jmpstub__VTableResolver_CommonCallingStub(?)
+ ;; Used when we dynamically need a VTableResolver not pre-generated.
+ ;;
+ ;; xip0 contains a pointer to a VTableResolverStruct
+ ;; struct VTableResolverStruct
+ ;; {
+ ;; IntPtr offsetFromStartOfEETypePtr;
+ ;; IntPtr VTableThunkAddress;
+ ;; };
+ ;;
+ LEAF_ENTRY __jmpstub__VTableResolver_CommonCallingStub
+ ;; Load the EEType pointer and add (EETypeVTableOffset + $slot_number * PointerSize) to calculate the VTable slot
+ ;; address. Compare the pointer stored in the slot to the address of the thunk being executed. If the values are
+ ;; equal, call the dispatch resolution callback; otherwise, call the function pointer stored in the slot.
+
+ ;; x9 = EEType pointer (x0 is the "this" pointer for the call being made)
+ ldr x9, [x0]
+ ;; xip1 = slot offset relative to EEType
+ ldr xip1, [xip0]
+ ;; x10 = function pointer stored in the slot
+ ldr x10, [x9,xip1]
+ ;; x11 = address of this thunk
+ ldr x11, [xip0,#PointerSize]
+ ;; Compare two pointers
+ cmp x10, x11
+ ;; If the method is not resolved yet, resolve it first
+ beq __jmpstub__JumpToVTableResolver
+ ;; Otherwise, just call it
+ br x10
+ LEAF_END __jmpstub__VTableResolver_CommonCallingStub
+
+ ;; Calls the dispatch resolution callback with xip1 set to EETypeVTableOffset + ($slot_number * PointerSize)
+ LEAF_ENTRY __jmpstub__JumpToVTableResolver
+ ADDROF xip0, g_vtableResolveCallback
+ ldr xip0, [xip0]
+ ADDROF x9, g_universalTransition
+ ldr x9, [x9]
+ br x9
+ LEAF_END __jmpstub__VTableResolver_Init
+
+ MACRO
+ VTableThunkDecl $name, $slot_number
+ ;; Force all thunks to be the same size, which allows us to index
+ ALIGN 16
+ LEAF_ENTRY __jmpstub__$name
+ ;; Load the EEType pointer and add (EETypeVTableOffset + $slot_number * PointerSize) to calculate the VTable slot
+ ;; address. Compare the pointer stored in the slot to the address of the thunk being executed. If the values are
+ ;; equal, call the dispatch resolution callback; otherwise, call the function pointer stored in the slot.
+
+ ;; x9 = EEType pointer (x0 is the "this" pointer for the call being made)
+ ldr x9, [x0]
+ ;; xip1 = slot offset relative to EEType
+ mov xip1, EETypeVTableOffset + ($slot_number * PointerSize)
+ ;; x10 = function pointer stored in the slot
+ ldr x10, [x9,xip1]
+ ;; x11 = address of this thunk
+ adr x11, __jmpstub__$name
+ ;; Compare two pointers
+ cmp x10, x11
+ ;; If the method is not resolved yet, resolve it first
+ beq __jmpstub__JumpToVTableResolver
+ ;; Otherwise, just call it
+ br x10
+ LEAF_END __jmpstub__$name
+ MEND
+
+ MACRO
+ VTableThunkDeclTen $slotnumberDecimal
+ VTableThunkDecl VTableSlot$slotnumberDecimal0,$slotnumberDecimal0
+ VTableThunkDecl VTableSlot$slotnumberDecimal1,$slotnumberDecimal1
+ VTableThunkDecl VTableSlot$slotnumberDecimal2,$slotnumberDecimal2
+ VTableThunkDecl VTableSlot$slotnumberDecimal3,$slotnumberDecimal3
+ VTableThunkDecl VTableSlot$slotnumberDecimal4,$slotnumberDecimal4
+ VTableThunkDecl VTableSlot$slotnumberDecimal5,$slotnumberDecimal5
+ VTableThunkDecl VTableSlot$slotnumberDecimal6,$slotnumberDecimal6
+ VTableThunkDecl VTableSlot$slotnumberDecimal7,$slotnumberDecimal7
+ VTableThunkDecl VTableSlot$slotnumberDecimal8,$slotnumberDecimal8
+ VTableThunkDecl VTableSlot$slotnumberDecimal9,$slotnumberDecimal9
+ MEND
+
+ MACRO
+ VTableThunkDeclHundred $slotnumberPerHundred
+ VTableThunkDeclTen $slotnumberPerHundred0
+ VTableThunkDeclTen $slotnumberPerHundred1
+ VTableThunkDeclTen $slotnumberPerHundred2
+ VTableThunkDeclTen $slotnumberPerHundred3
+ VTableThunkDeclTen $slotnumberPerHundred4
+ VTableThunkDeclTen $slotnumberPerHundred5
+ VTableThunkDeclTen $slotnumberPerHundred6
+ VTableThunkDeclTen $slotnumberPerHundred7
+ VTableThunkDeclTen $slotnumberPerHundred8
+ VTableThunkDeclTen $slotnumberPerHundred9
+ MEND
+
+ VTableThunkDeclHundred ""
+
+ END
diff --git a/src/Native/System.Private.TypeLoader.Native/i386/ConstrainedCallSupportHelpers.asm b/src/Native/System.Private.TypeLoader.Native/i386/ConstrainedCallSupportHelpers.asm
new file mode 100644
index 000000000..8b3298180
--- /dev/null
+++ b/src/Native/System.Private.TypeLoader.Native/i386/ConstrainedCallSupportHelpers.asm
@@ -0,0 +1,100 @@
+;; Licensed to the .NET Foundation under one or more agreements.
+;; The .NET Foundation licenses this file to you under the MIT license.
+;; See the LICENSE file in the project root for more information.
+
+.586
+.model flat
+option casemap:none
+.code
+
+;; -----------------------------------------------------------------------------------------------------------
+;; standard macros
+;; -----------------------------------------------------------------------------------------------------------
+LEAF_ENTRY macro Name, Section
+ Section segment para 'CODE'
+ public Name
+ Name proc
+endm
+
+LEAF_END macro Name, Section
+ Name endp
+ Section ends
+endm
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DATA SECTIONS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ConstrainedCall Support Helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+;;
+;; Note: The "__jmpstub__" prefix is used to indicate to debugger
+;; that it must step-through this stub when it encounters it while
+;; stepping.
+;;
+
+;;
+;; __jmpstub__ConstrainedCallSupport_DerefThisAndCall_CommonCallingStub
+;;
+;; eax - AddressOfAddressOfFunctionToCallAfterDereferencingThis
+;;
+LEAF_ENTRY __jmpstub__ConstrainedCallSupport_DerefThisAndCall_CommonCallingStub, _TEXT
+ mov eax, [eax] ; Get function pointer to call
+ mov ecx, [ecx] ; Deference this to get real this pointer
+ jmp eax
+LEAF_END __jmpstub__ConstrainedCallSupport_DerefThisAndCall_CommonCallingStub, _TEXT
+
+;;
+;; void ConstrainedCallSupport_GetStubs(IntPtr *__jmpstub__ConstrainedCallSupport_DerefThisAndCall_CommonCallingStub,
+;; IntPtr *__jmpstub__ConstrainedCallSupport_DirectConstrainedCallCommonStub)
+;;
+LEAF_ENTRY ConstrainedCallSupport_GetStubs, _TEXT
+ lea eax, [__jmpstub__ConstrainedCallSupport_DerefThisAndCall_CommonCallingStub]
+ mov ecx, [esp+04h]
+ mov [ecx], eax
+ lea eax, [__jmpstub__ConstrainedCallSupport_DirectConstrainedCallCommonStub]
+ mov ecx, [esp+08h]
+ mov [ecx], eax
+ retn 8h
+LEAF_END ConstrainedCallSupport_GetStubs, _TEXT
+
+;;
+;; __jmpstub__ConstrainedCallSupport_DirectConstrainedCallCommonStub
+;;
+;; struct ConstrainedCallDesc
+;; {
+;; ULONG_PTR ExactTarget;
+;; ULONG_PTR LookupFunc; // Put UniversalThunk here
+;; }
+;;
+;; struct CommonCallingStubInputData
+;; {
+;; ULONG_PTR ConstrainedCallDesc;
+;; ULONG_PTR DirectConstrainedCallResolver;
+;; }
+;;
+;; eax - Points at CommonCallingStubInputData
+;;
+;;
+LEAF_ENTRY __jmpstub__ConstrainedCallSupport_DirectConstrainedCallCommonStub, _TEXT
+;; eax points at CommonCallingStubInputData
+ push eax ; save eax
+ mov eax,[eax] ; put ConstrainedCallDesc in eax
+ mov eax,[eax] ; Load ExactTarget into eax
+ test eax,eax ; Check ExactTarget for null
+ jz NeedsHelperCall
+ add esp,4 ; Adjust eax back to what it was before the first instruction push
+ jmp eax ; TailCall exact target
+NeedsHelperCall:
+ pop eax ; Restore back to exact state that was present at start of function
+;; eax points at CommonCallingStubInputData
+ push ebp
+ mov ebp, esp
+ push [eax] ; First argument (ConstrainedCallDesc)
+ push [eax+4] ; Second argument (DirectConstrainedCallResolver)
+ mov eax,[eax] ; Load ConstrainedCallDesc into eax
+ mov eax,[eax+4] ; Load Universal Thunk address into eax
+ jmp eax
+LEAF_END __jmpstub__ConstrainedCallSupport_DirectConstrainedCallCommonStub, _TEXT
+
+end
diff --git a/src/Native/System.Private.TypeLoader.Native/i386/MethodEntrypointStubs.asm b/src/Native/System.Private.TypeLoader.Native/i386/MethodEntrypointStubs.asm
new file mode 100644
index 000000000..026e0aa6d
--- /dev/null
+++ b/src/Native/System.Private.TypeLoader.Native/i386/MethodEntrypointStubs.asm
@@ -0,0 +1,5 @@
+;; Licensed to the .NET Foundation under one or more agreements.
+;; The .NET Foundation licenses this file to you under the MIT license.
+;; See the LICENSE file in the project root for more information.
+
+end \ No newline at end of file
diff --git a/src/Native/System.Private.TypeLoader.Native/i386/VTableResolver.asm b/src/Native/System.Private.TypeLoader.Native/i386/VTableResolver.asm
new file mode 100644
index 000000000..d81948578
--- /dev/null
+++ b/src/Native/System.Private.TypeLoader.Native/i386/VTableResolver.asm
@@ -0,0 +1,246 @@
+;; Licensed to the .NET Foundation under one or more agreements.
+;; The .NET Foundation licenses this file to you under the MIT license.
+;; See the LICENSE file in the project root for more information.
+
+.586
+.model flat
+option casemap:none
+
+;; -----------------------------------------------------------------------------------------------------------
+;; standard macros
+;; -----------------------------------------------------------------------------------------------------------
+LEAF_ENTRY macro Name, Section
+ Section segment para 'CODE'
+ public Name
+ Name proc
+endm
+
+LEAF_END macro Name, Section
+ Name endp
+ Section ends
+endm
+
+;;
+;; When an EEType is created its vTable entries will be initially filled with calls to the vTableThunk for the appropriate
+;; slot number. When the thunk is invoked it'll check to see if the slot has already been resolved. If so then just call
+;; the universal thunk, otherwise call to do the resolution which will also update the vtable slot and then call
+;; the universal thunk
+;;
+
+VTableThunkSize equ 20h
+;; TODO - do something similar to Redhawk's asmoffsets to compute the value at compile time
+EETypeVTableOffset equ 14h
+PointerSize equ 4
+
+.data
+
+g_vtableResolveCallback dword 0 ; The vtableresolve method
+g_universalTransition dword 0 ; The address of Redhawk's UniversalTransition thunk
+
+.code
+
+;;
+;; __jmpstub__VTableResolver_CommonCallingStub(?)
+;; Used when we dynamically need a VTableResolver not pre-generated
+;;
+;; eax contains a pointer to a VTableResolverStruct
+;; struct VTableResolverStruct
+;; {
+;; int offsetFromStartOfEETypePtr;
+;; IntPtr VTableThunkAddress;
+;; };
+;;
+LEAF_ENTRY __jmpstub__VTableResolver_CommonCallingStub, _TEXT
+ ;; eax <- stub info
+ push esi
+ push edi
+ mov esi, [eax] ; Get EEType offset into esi
+
+ mov edi, [eax + 4]
+ ;; edi now has specific address of the exact thunk being processed here
+
+ ;; ecx is the this pointer to the call being made
+ mov eax, [ecx]
+ ;; eax is the EEType pointer add the VTableOffset + slot_number * pointer size to get the vtable entry
+
+ ;; compare the that value to the address of the thunk being executed and if the values are equal then
+ ;; call to the resolver otherwise call the method
+
+ mov eax, [eax + esi]
+ cmp eax, edi
+ je SLOW_DYNAMIC_STUB
+ pop edi
+ pop esi
+ jmp eax
+SLOW_DYNAMIC_STUB:
+ ;; Capture EEType offset into eax
+ mov eax,esi
+
+ ;; Restore edi and esi so that we can set up the call into the universal transition thunk
+ pop edi
+ pop esi
+
+ jmp __jmpstub__JumpToVTableResolver
+LEAF_END __jmpstub__VTableResolver_CommonCallingStub, _TEXT
+
+;; Returns the size of the pre-generated thunks
+;; int VTableResolver_Init(IntPtr *__jmpstub__VTableResolverSlot0,
+;; IntPtr vtableResolveCallback,
+;; IntPtr universalTransition,
+;; int *slotCount)
+;;
+LEAF_ENTRY VTableResolver_Init, _TEXT
+ lea eax, dword ptr [__jmpstub__VTableSlot0]
+ mov ecx, [esp+04h]
+ mov [ecx], eax
+ mov ecx, [esp+08h]
+ mov g_vtableResolveCallback, ecx
+ mov ecx, [esp+0Ch]
+ mov g_universalTransition, ecx
+ mov ecx, [esp+10h]
+ mov eax, 100 ;; 100 Pregenerated thunks
+ mov [ecx], eax
+ mov eax, VTableThunkSize
+ ret
+LEAF_END VTableResolver_Init, _TEXT
+
+;; void* VTableResolver_GetCommonCallingStub()
+;; - Get the address of the common calling stub
+LEAF_ENTRY VTableResolver_GetCommonCallingStub, _TEXT
+ lea eax, [__jmpstub__VTableResolver_CommonCallingStub]
+ ret
+LEAF_END VTableResolver_GetCommonCallingStub, _TEXT
+
+
+;; stub for dispatch will come in with eax set to EETypeVTableOffset + ($slot_number * PointerSize),
+LEAF_ENTRY __jmpstub__JumpToVTableResolver, _TEXT
+ push ebp
+ mov ebp, esp
+ push eax ; First argument
+ push g_vtableResolveCallback
+ jmp g_universalTransition
+LEAF_END __jmpstub__JumpToVTableResolver, _TEXT
+
+
+VTableThunkDecl macro name, slot_number
+
+ALIGN 16 ; The alignment here forces the thunks to be the same size which gives all of the macros the same size and allows us to index
+LEAF_ENTRY name, _TEXT
+ ;; rcx is the this pointer to the call being made
+ mov eax, [ecx]
+ ;; eax is the EEType pointer add the VTableOffset + slot_number * pointer size to get the vtable entry
+ ;; compare the that value to the address of the thunk being executed and if the values are equal then
+ ;; call to the resolver otherwise call the method
+ mov eax, [eax + EETypeVTableOffset + slot_number * PointerSize]
+ cmp eax, name
+ je SLOW
+ jmp eax
+SLOW:
+ mov eax, EETypeVTableOffset + slot_number * PointerSize
+ jmp __jmpstub__JumpToVTableResolver
+LEAF_END name, _TEXT
+
+ endm
+
+VTableThunkDecl __jmpstub__VTableSlot0,0
+VTableThunkDecl __jmpstub__VTableSlot1,1
+VTableThunkDecl __jmpstub__VTableSlot2,2
+VTableThunkDecl __jmpstub__VTableSlot3,3
+VTableThunkDecl __jmpstub__VTableSlot4,4
+VTableThunkDecl __jmpstub__VTableSlot5,5
+VTableThunkDecl __jmpstub__VTableSlot6,6
+VTableThunkDecl __jmpstub__VTableSlot7,7
+VTableThunkDecl __jmpstub__VTableSlot8,8
+VTableThunkDecl __jmpstub__VTableSlot9,9
+VTableThunkDecl __jmpstub__VTableSlot10,10
+VTableThunkDecl __jmpstub__VTableSlot11,11
+VTableThunkDecl __jmpstub__VTableSlot12,12
+VTableThunkDecl __jmpstub__VTableSlot13,13
+VTableThunkDecl __jmpstub__VTableSlot14,14
+VTableThunkDecl __jmpstub__VTableSlot15,15
+VTableThunkDecl __jmpstub__VTableSlot16,16
+VTableThunkDecl __jmpstub__VTableSlot17,17
+VTableThunkDecl __jmpstub__VTableSlot18,18
+VTableThunkDecl __jmpstub__VTableSlot19,19
+VTableThunkDecl __jmpstub__VTableSlot20,20
+VTableThunkDecl __jmpstub__VTableSlot21,21
+VTableThunkDecl __jmpstub__VTableSlot22,22
+VTableThunkDecl __jmpstub__VTableSlot23,23
+VTableThunkDecl __jmpstub__VTableSlot24,24
+VTableThunkDecl __jmpstub__VTableSlot25,25
+VTableThunkDecl __jmpstub__VTableSlot26,26
+VTableThunkDecl __jmpstub__VTableSlot27,27
+VTableThunkDecl __jmpstub__VTableSlot28,28
+VTableThunkDecl __jmpstub__VTableSlot29,29
+VTableThunkDecl __jmpstub__VTableSlot30,30
+VTableThunkDecl __jmpstub__VTableSlot31,31
+VTableThunkDecl __jmpstub__VTableSlot32,32
+VTableThunkDecl __jmpstub__VTableSlot33,33
+VTableThunkDecl __jmpstub__VTableSlot34,34
+VTableThunkDecl __jmpstub__VTableSlot35,35
+VTableThunkDecl __jmpstub__VTableSlot36,36
+VTableThunkDecl __jmpstub__VTableSlot37,37
+VTableThunkDecl __jmpstub__VTableSlot38,38
+VTableThunkDecl __jmpstub__VTableSlot39,39
+VTableThunkDecl __jmpstub__VTableSlot40,40
+VTableThunkDecl __jmpstub__VTableSlot41,41
+VTableThunkDecl __jmpstub__VTableSlot42,42
+VTableThunkDecl __jmpstub__VTableSlot43,43
+VTableThunkDecl __jmpstub__VTableSlot44,44
+VTableThunkDecl __jmpstub__VTableSlot45,45
+VTableThunkDecl __jmpstub__VTableSlot46,46
+VTableThunkDecl __jmpstub__VTableSlot47,47
+VTableThunkDecl __jmpstub__VTableSlot48,48
+VTableThunkDecl __jmpstub__VTableSlot49,49
+VTableThunkDecl __jmpstub__VTableSlot50,50
+VTableThunkDecl __jmpstub__VTableSlot51,51
+VTableThunkDecl __jmpstub__VTableSlot52,52
+VTableThunkDecl __jmpstub__VTableSlot53,53
+VTableThunkDecl __jmpstub__VTableSlot54,54
+VTableThunkDecl __jmpstub__VTableSlot55,55
+VTableThunkDecl __jmpstub__VTableSlot56,56
+VTableThunkDecl __jmpstub__VTableSlot57,57
+VTableThunkDecl __jmpstub__VTableSlot58,58
+VTableThunkDecl __jmpstub__VTableSlot59,59
+VTableThunkDecl __jmpstub__VTableSlot60,60
+VTableThunkDecl __jmpstub__VTableSlot61,61
+VTableThunkDecl __jmpstub__VTableSlot62,62
+VTableThunkDecl __jmpstub__VTableSlot63,63
+VTableThunkDecl __jmpstub__VTableSlot64,64
+VTableThunkDecl __jmpstub__VTableSlot65,65
+VTableThunkDecl __jmpstub__VTableSlot66,66
+VTableThunkDecl __jmpstub__VTableSlot67,67
+VTableThunkDecl __jmpstub__VTableSlot68,68
+VTableThunkDecl __jmpstub__VTableSlot69,69
+VTableThunkDecl __jmpstub__VTableSlot70,70
+VTableThunkDecl __jmpstub__VTableSlot71,71
+VTableThunkDecl __jmpstub__VTableSlot72,72
+VTableThunkDecl __jmpstub__VTableSlot73,73
+VTableThunkDecl __jmpstub__VTableSlot74,74
+VTableThunkDecl __jmpstub__VTableSlot75,75
+VTableThunkDecl __jmpstub__VTableSlot76,76
+VTableThunkDecl __jmpstub__VTableSlot77,77
+VTableThunkDecl __jmpstub__VTableSlot78,78
+VTableThunkDecl __jmpstub__VTableSlot79,79
+VTableThunkDecl __jmpstub__VTableSlot80,80
+VTableThunkDecl __jmpstub__VTableSlot81,81
+VTableThunkDecl __jmpstub__VTableSlot82,82
+VTableThunkDecl __jmpstub__VTableSlot83,83
+VTableThunkDecl __jmpstub__VTableSlot84,84
+VTableThunkDecl __jmpstub__VTableSlot85,85
+VTableThunkDecl __jmpstub__VTableSlot86,86
+VTableThunkDecl __jmpstub__VTableSlot87,87
+VTableThunkDecl __jmpstub__VTableSlot88,88
+VTableThunkDecl __jmpstub__VTableSlot89,89
+VTableThunkDecl __jmpstub__VTableSlot90,90
+VTableThunkDecl __jmpstub__VTableSlot91,91
+VTableThunkDecl __jmpstub__VTableSlot92,92
+VTableThunkDecl __jmpstub__VTableSlot93,93
+VTableThunkDecl __jmpstub__VTableSlot94,94
+VTableThunkDecl __jmpstub__VTableSlot95,95
+VTableThunkDecl __jmpstub__VTableSlot96,96
+VTableThunkDecl __jmpstub__VTableSlot97,97
+VTableThunkDecl __jmpstub__VTableSlot98,98
+VTableThunkDecl __jmpstub__VTableSlot99,99
+
+end
diff --git a/src/Native/gc/gc.cpp b/src/Native/gc/gc.cpp
index 5c673c0be..b48b4f71b 100644
--- a/src/Native/gc/gc.cpp
+++ b/src/Native/gc/gc.cpp
@@ -2909,7 +2909,7 @@ void gc_heap::fire_pevents()
gc_data_global.condemned_generation,
gc_data_global.gen0_reduction_count,
gc_data_global.reason,
- gc_data_global.global_mechanims_p,
+ gc_data_global.global_mechanisms_p,
GetClrInstanceId(),
gc_data_global.pause_mode,
gc_data_global.mem_pressure);
@@ -5693,7 +5693,7 @@ void gc_mechanisms::record (gc_history_global* history)
history->reason = reason;
history->pause_mode = (int)pause_mode;
history->mem_pressure = entry_memory_load;
- history->global_mechanims_p = 0;
+ history->global_mechanisms_p = 0;
// start setting the boolean values.
if (concurrent)
@@ -9617,7 +9617,7 @@ void gc_heap::restart_vm()
{
//assert (generation_allocation_pointer (youngest_generation) == 0);
dprintf (3, ("Restarting EE"));
- STRESS_LOG0(LF_GC, LL_INFO10000, "Concurrent GC: Retarting EE\n");
+ STRESS_LOG0(LF_GC, LL_INFO10000, "Concurrent GC: Restarting EE\n");
ee_proceed_event.Set();
}
@@ -26667,7 +26667,7 @@ BOOL gc_heap::prepare_bgc_thread(gc_heap* gh)
gh->bgc_threads_timeout_cs.Enter();
if (!(gh->bgc_thread_running))
{
- dprintf (2, ("GC thread not runnning"));
+ dprintf (2, ("GC thread not running"));
if ((gh->bgc_thread == 0) && create_bgc_thread(gh))
{
success = TRUE;
@@ -36708,7 +36708,7 @@ inline void testGCShadow(Object** ptr)
if (*ptr != 0 && (uint8_t*) shadow < g_GCShadowEnd && *ptr != *shadow)
{
- // If you get this assertion, someone updated a GC poitner in the heap without
+ // If you get this assertion, someone updated a GC pointer in the heap without
// using the write barrier. To find out who, check the value of
// dd_collection_count (dynamic_data_of (0)). Also
// note the value of 'ptr'. Rerun the App that the previous GC just occurred.
diff --git a/src/Native/gc/gcrecord.h b/src/Native/gc/gcrecord.h
index fff1fc5c8..5fa1ef88c 100644
--- a/src/Native/gc/gcrecord.h
+++ b/src/Native/gc/gcrecord.h
@@ -407,16 +407,16 @@ struct gc_history_global
gc_reason reason;
int pause_mode;
uint32_t mem_pressure;
- uint32_t global_mechanims_p;
+ uint32_t global_mechanisms_p;
void set_mechanism_p (gc_global_mechanism_p mechanism)
{
- global_mechanims_p |= (1 << mechanism);
+ global_mechanisms_p |= (1 << mechanism);
}
BOOL get_mechanism_p (gc_global_mechanism_p mechanism)
{
- return (global_mechanims_p & (1 << mechanism));
+ return (global_mechanisms_p & (1 << mechanism));
}
void print();
diff --git a/src/Native/gc/handletable.cpp b/src/Native/gc/handletable.cpp
index 2b598528c..1b685ab44 100644
--- a/src/Native/gc/handletable.cpp
+++ b/src/Native/gc/handletable.cpp
@@ -933,7 +933,7 @@ void HndEnumHandles(HHANDLETABLE hTable, const uint32_t *puType, uint32_t uTypeC
*
* Multiple type scanning entrypoint for GC.
*
- * This entrypoint is provided for GC-time scnas of the handle table ONLY. It
+ * This entrypoint is provided for GC-time scans of the handle table ONLY. It
* enables ephemeral scanning of the table, and optionally ages the write barrier
* as it scans.
*
diff --git a/src/Native/gc/unix/gcenv.unix.cpp b/src/Native/gc/unix/gcenv.unix.cpp
index 07259c0f2..819049b42 100644
--- a/src/Native/gc/unix/gcenv.unix.cpp
+++ b/src/Native/gc/unix/gcenv.unix.cpp
@@ -57,6 +57,12 @@ static_assert(sizeof(uint64_t) == 8, "unsigned long isn't 8 bytes");
#include <errno.h>
#include <unistd.h> // sysconf
+#if defined(_ARM_) || defined(_ARM64_)
+#define SYSCONF_GET_NUMPROCS _SC_NPROCESSORS_CONF
+#else
+#define SYSCONF_GET_NUMPROCS _SC_NPROCESSORS_ONLN
+#endif
+
// The number of milliseconds in a second.
static const int tccSecondsToMilliSeconds = 1000;
@@ -84,7 +90,7 @@ static pthread_mutex_t g_flushProcessWriteBuffersMutex;
bool GCToOSInterface::Initialize()
{
// Calculate and cache the number of processors on this machine
- int cpuCount = sysconf(_SC_NPROCESSORS_ONLN);
+ int cpuCount = sysconf(SYSCONF_GET_NUMPROCS);
if (cpuCount == -1)
{
return false;
diff --git a/src/Native/gen-buildsys-clang.sh b/src/Native/gen-buildsys-clang.sh
index fed57d122..38c31c064 100755
--- a/src/Native/gen-buildsys-clang.sh
+++ b/src/Native/gen-buildsys-clang.sh
@@ -109,8 +109,12 @@ if [[ -n "$CROSSCOMPILE" ]]; then
echo "ROOTFS_DIR not set for crosscompile"
exit 1
fi
- cmake_extra_defines="$cmake_extra_defines -C $1/cross/$build_arch/tryrun.cmake"
- cmake_extra_defines="$cmake_extra_defines -DCMAKE_TOOLCHAIN_FILE=$1/cross/$build_arch/toolchain.cmake"
+ if [[ -z $CONFIG_DIR ]]; then
+ CONFIG_DIR="$1/cross"
+ fi
+ export TARGET_BUILD_ARCH=$build_arch
+ cmake_extra_defines="$cmake_extra_defines -C $CONFIG_DIR/tryrun.cmake"
+ cmake_extra_defines="$cmake_extra_defines -DCMAKE_TOOLCHAIN_FILE=$CONFIG_DIR/toolchain.cmake"
fi
if [ $build_arch == "wasm" ]; then
diff --git a/src/Native/gen-buildsys-win.bat b/src/Native/gen-buildsys-win.bat
index fa10ef0a4..60fa962e5 100644
--- a/src/Native/gen-buildsys-win.bat
+++ b/src/Native/gen-buildsys-win.bat
@@ -25,7 +25,7 @@ for /f "delims=" %%a in ('powershell -NoProfile -ExecutionPolicy ByPass "& %~dp0
if "%3" == "wasm" (
emcmake "%CMakePath%" "-DEMSCRIPTEN_GENERATE_BITCODE_STATIC_LIBRARIES=1" "-DCMAKE_TOOLCHAIN_FILE=%EMSCRIPTEN%/cmake/Modules/Platform/Emscripten.cmake" "-DCLR_CMAKE_TARGET_ARCH=%3" "-DCMAKE_BUILD_TYPE=%4" -G "NMake Makefiles" %1
) else (
- "%CMakePath%" "-DCLR_CMAKE_TARGET_ARCH=%3" -G "%__CmakeGenerator%" %1
+ "%CMakePath%" "-DCLR_CMAKE_TARGET_ARCH=%3" "-DOBJWRITER_BUILD=%__ObjWriterBuild%" -G "%__CmakeGenerator%" %1
)
endlocal
GOTO :DONE
diff --git a/src/Native/jitinterface/CMakeLists.txt b/src/Native/jitinterface/CMakeLists.txt
index 46c071c8a..5262e0d8c 100644
--- a/src/Native/jitinterface/CMakeLists.txt
+++ b/src/Native/jitinterface/CMakeLists.txt
@@ -7,15 +7,23 @@ set(NATIVE_SOURCES
corinfoexception.cpp
)
+set (JIT_SOURCES
+ CodeHeap.cpp
+ JITCodeManager.cpp
+ ../Runtime/coreclr/GCInfoDecoder.cpp
+)
+
if(WIN32 AND CLR_CMAKE_PLATFORM_ARCH_AMD64)
- set(NATIVE_SOURCES ${NATIVE_SOURCES}
- CodeHeap.cpp
- JITCodeManager.cpp
- ../Runtime/coreclr/GCInfoDecoder.cpp
- )
add_definitions(-DGCINFODECODER_NO_EE)
add_definitions(-DFEATURE_REDHAWK)
+ add_definitions(-DFEATURE_SINGLE_MODULE_RUNTIME)
+
+ add_library(System.Private.Jit.Native
+ STATIC
+ ${NATIVE_SOURCES}
+ ${JIT_SOURCES}
+ )
endif(WIN32 AND CLR_CMAKE_PLATFORM_ARCH_AMD64)
add_library(jitinterface
@@ -27,4 +35,5 @@ install (TARGETS jitinterface DESTINATION tools)
if(WIN32)
target_link_libraries(jitinterface ntdll.lib)
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>/jitinterface.pdb DESTINATION tools)
+ install (TARGETS System.Private.Jit.Native DESTINATION sdk)
endif(WIN32)
diff --git a/src/Native/jitinterface/CodeHeap.cpp b/src/Native/jitinterface/CodeHeap.cpp
index 1adc206ea..468bd2588 100644
--- a/src/Native/jitinterface/CodeHeap.cpp
+++ b/src/Native/jitinterface/CodeHeap.cpp
@@ -18,13 +18,23 @@ static void *s_topAddress = nullptr;
static DWORD s_pageSize = 0;
extern HMODULE s_hRuntime;
+#if FEATURE_SINGLE_MODULE_RUNTIME
+extern "C" void RhpNewArray();
+#endif
+
void InitMemoryStatics()
{
std::call_once(s_staticInit, []()
{
HMODULE module = s_hRuntime;
if (module != NULL)
+ {
+#if FEATURE_SINGLE_MODULE_RUNTIME
+ s_mrtAddr = &RhpNewArray;
+#else
s_mrtAddr = GetProcAddress(module, "RhpNewArray");
+#endif
+ }
assert(s_mrtAddr != nullptr);
diff --git a/src/Native/jitinterface/JITCodeManager.cpp b/src/Native/jitinterface/JITCodeManager.cpp
index 198671f14..11a1088be 100644
--- a/src/Native/jitinterface/JITCodeManager.cpp
+++ b/src/Native/jitinterface/JITCodeManager.cpp
@@ -46,14 +46,24 @@ HMODULE s_hRuntime = NULL;
pfnRegisterCodeManager s_pfnRegisterCodeManager;
pfnUnregisterCodeManager s_pfnUnregisterCodeManager;
+#if FEATURE_SINGLE_MODULE_RUNTIME
+extern "C" bool RegisterCodeManager(ICodeManager * pCodeManager, PTR_VOID pvStartRange, UInt32 cbRange);
+extern "C" void UnregisterCodeManager(ICodeManager * pCodeManager);
+#endif
+
bool InitializeCodeManagerRuntime()
{
std::call_once(s_RuntimeInit, []()
{
if (s_hRuntime != NULL)
{
+#if FEATURE_SINGLE_MODULE_RUNTIME
+ s_pfnRegisterCodeManager = &RegisterCodeManager;
+ s_pfnUnregisterCodeManager = &UnregisterCodeManager;
+#else
s_pfnRegisterCodeManager = (pfnRegisterCodeManager)GetProcAddress(s_hRuntime, "RegisterCodeManager");
s_pfnUnregisterCodeManager = (pfnUnregisterCodeManager)GetProcAddress(s_hRuntime, "UnregisterCodeManager");
+#endif
}
});
@@ -259,7 +269,7 @@ bool JITCodeManager::Initialize()
// Note that main method bodies will not have an entry in the map.
PTR_RUNTIME_FUNCTION JITCodeManager::AllocRuntimeFunction(PTR_RUNTIME_FUNCTION mainMethod, DWORD beginAddr, DWORD endAddr, DWORD unwindData)
{
- ReaderWriterLock::WriteHolder lh(&m_lock);
+ SlimReaderWriterLock::WriteHolder lh(&m_lock);
m_runtimeFunctions.push_back(RUNTIME_FUNCTION());
PTR_RUNTIME_FUNCTION method = &m_runtimeFunctions.back();
@@ -278,7 +288,7 @@ PTR_RUNTIME_FUNCTION JITCodeManager::AllocRuntimeFunction(PTR_RUNTIME_FUNCTION m
void JITCodeManager::UpdateRuntimeFunctionTable()
{
- ReaderWriterLock::WriteHolder lh(&m_lock);
+ SlimReaderWriterLock::WriteHolder lh(&m_lock);
PTR_RUNTIME_FUNCTION pFunctionTable = &m_runtimeFunctions[0];
DWORD nEntryCount = (DWORD)m_runtimeFunctions.size();
@@ -381,7 +391,7 @@ bool JITCodeManager::FindMethodInfo(PTR_VOID ControlPC,
if (RelativePC >= m_cbRange)
return false;
- ReaderWriterLock::ReadHolder lh(&m_lock);
+ SlimReaderWriterLock::ReadHolder lh(&m_lock);
int MethodIndex = LookupUnwindInfoForMethod((UInt32)RelativePC, m_pRuntimeFunctionTable,
0, m_nRuntimeFunctionTable - 1);
@@ -420,7 +430,7 @@ bool JITCodeManager::IsFunclet(MethodInfo * pMethInfo)
JITMethodInfo * pMethodInfo = (JITMethodInfo *)pMethInfo;
// A funclet will have an entry in funclet to main method map
- ReaderWriterLock::ReadHolder lh(&m_lock);
+ SlimReaderWriterLock::ReadHolder lh(&m_lock);
return m_FuncletToMainMethodMap.find(pMethodInfo->runtimeFunction.BeginAddress) != m_FuncletToMainMethodMap.end();
}
diff --git a/src/Native/jitinterface/JITCodeManager.h b/src/Native/jitinterface/JITCodeManager.h
index aeff8bc89..991cb0d65 100644
--- a/src/Native/jitinterface/JITCodeManager.h
+++ b/src/Native/jitinterface/JITCodeManager.h
@@ -51,19 +51,19 @@ typedef DPTR(struct _UNWIND_INFO) PTR_UNWIND_INFO;
typedef DPTR(union _UNWIND_CODE) PTR_UNWIND_CODE;
#endif // target_amd64
-class ReaderWriterLock : private SRWLOCK
+class SlimReaderWriterLock : private SRWLOCK
{
public:
- ReaderWriterLock()
+ SlimReaderWriterLock()
{
::InitializeSRWLock(this);
}
class ReadHolder
{
- ReaderWriterLock * m_pLock;
+ SlimReaderWriterLock * m_pLock;
public:
- ReadHolder(ReaderWriterLock * pLock)
+ ReadHolder(SlimReaderWriterLock * pLock)
: m_pLock(pLock)
{
::AcquireSRWLockShared(m_pLock);
@@ -77,10 +77,10 @@ public:
class WriteHolder
{
- ReaderWriterLock * m_pLock;
+ SlimReaderWriterLock * m_pLock;
public:
- WriteHolder(ReaderWriterLock * pLock)
+ WriteHolder(SlimReaderWriterLock * pLock)
: m_pLock(pLock)
{
::AcquireSRWLockExclusive(m_pLock);
@@ -167,7 +167,7 @@ class JITCodeManager : ICodeManager
UInt32 m_cbRange;
// lock to protect m_runtimeFunctions and m_FuncletToMainMethodMap
- ReaderWriterLock m_lock;
+ SlimReaderWriterLock m_lock;
std::vector<RUNTIME_FUNCTION> m_runtimeFunctions;
PTR_RUNTIME_FUNCTION m_pRuntimeFunctionTable;
diff --git a/src/Native/jitinterface/dllexport.h b/src/Native/jitinterface/dllexport.h
index 4b28b7ba1..eac5f387f 100644
--- a/src/Native/jitinterface/dllexport.h
+++ b/src/Native/jitinterface/dllexport.h
@@ -2,22 +2,39 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+
+// ***
+// Define default C export attributes
+// ***
#ifdef _WIN32
-#define DLL_EXPORT extern "C" __declspec(dllexport)
+#define DLL_EXPORT extern "C" __declspec(dllexport)
#else
-#define DLL_EXPORT extern "C" __attribute((visibility("default")))
-#endif
-
-#ifdef __i386__
+#define DLL_EXPORT extern "C" __attribute((visibility("default")))
+#endif // _WIN32
-#if !defined(__stdcall)
-#define __stdcall __attribute__((stdcall))
-#endif
-#else
+// ***
+// Define default call conventions
+// ***
+#ifndef _X86_
-#if !defined(__stdcall)
+#define DEFAULT_CALL_CONV
+#define __cdecl
#define __stdcall
+
+#else // _X86_
+
+#ifndef __stdcall
+#define __stdcall __attribute__((stdcall))
#endif
+#ifdef PLATFORM_UNIX
+#define DEFAULT_CALL_CONV
+#else
+#define DEFAULT_CALL_CONV __stdcall
#endif
+
+#endif // _X86_
+
+
+#define STDMETHODCALLTYPE DEFAULT_CALL_CONV
diff --git a/src/Native/jitinterface/jithost.cpp b/src/Native/jitinterface/jithost.cpp
index 62770ddca..f433cf5b1 100644
--- a/src/Native/jitinterface/jithost.cpp
+++ b/src/Native/jitinterface/jithost.cpp
@@ -6,27 +6,15 @@
#include "dllexport.h"
-#ifdef _X86_
-#ifdef PLATFORM_UNIX
-#define DEFAULT_CALL_CONV __cdecl
-#else
-#define DEFAULT_CALL_CONV __stdcall
-#endif
-#else
-#define DEFAULT_CALL_CONV
-#define __cdecl
-#define __stdcall
-#endif
-
class JitConfigProvider
{
public:
- virtual int DEFAULT_CALL_CONV getIntConfigValue(
+ virtual int getIntConfigValue(
const wchar_t* name,
int defaultValue
) = 0;
- virtual int DEFAULT_CALL_CONV getStringConfigValue(
+ virtual int getStringConfigValue(
const wchar_t* name,
wchar_t* retBuffer,
int retBufferLength
@@ -48,12 +36,12 @@ public:
JitHost(JitConfigProvider* pConfigProvider)
: pConfigProvider(pConfigProvider) { }
- virtual void* allocateMemory(size_t size, bool usePageAllocator = false)
+ virtual void* allocateMemory(size_t size)
{
return malloc(size);
}
- virtual void freeMemory(void* block, bool usePageAllocator = false)
+ virtual void freeMemory(void* block)
{
free(block);
}
@@ -88,6 +76,17 @@ public:
{
free(value);
}
+
+ virtual void* allocateSlab(size_t size, size_t* pActualSize)
+ {
+ *pActualSize = size;
+ return allocateMemory(size);
+ }
+
+ virtual void freeSlab(void* slab, size_t actualSize)
+ {
+ freeMemory(slab);
+ }
};
DLL_EXPORT void* GetJitHost(JitConfigProvider* pConfigProvider)
diff --git a/src/Native/jitinterface/jitinterface.cpp b/src/Native/jitinterface/jitinterface.cpp
index acdcfa39e..e18036465 100644
--- a/src/Native/jitinterface/jitinterface.cpp
+++ b/src/Native/jitinterface/jitinterface.cpp
@@ -67,32 +67,32 @@ public:
{
}
- virtual void __stdcall QueryInterface() { NotImplemented(); }
- virtual void __stdcall AddRef() { NotImplemented(); }
- virtual void __stdcall Release() { NotImplemented(); }
+ virtual void STDMETHODCALLTYPE QueryInterface() { NotImplemented(); }
+ virtual void STDMETHODCALLTYPE AddRef() { NotImplemented(); }
+ virtual void STDMETHODCALLTYPE Release() { NotImplemented(); }
// JIT only ever uses IEEMemoryManager::ClrVirtualAlloc/IEEMemoryManager::ClrVirtualFree
- virtual void * __stdcall ClrVirtualAlloc(void * lpAddress, size_t dwSize, uint32_t flAllocationType, uint32_t flProtect)
+ virtual void * STDMETHODCALLTYPE ClrVirtualAlloc(void * lpAddress, size_t dwSize, uint32_t flAllocationType, uint32_t flProtect)
{
return malloc(dwSize);
}
- virtual uint32_t __stdcall ClrVirtualFree(void * lpAddress, size_t dwSize, uint32_t dwFreeType)
+ virtual uint32_t STDMETHODCALLTYPE ClrVirtualFree(void * lpAddress, size_t dwSize, uint32_t dwFreeType)
{
free(lpAddress);
return 1;
}
- virtual void __stdcall ClrVirtualQuery() { NotImplemented(); }
- virtual void __stdcall ClrVirtualProtect() { NotImplemented(); }
- virtual void __stdcall ClrGetProcessHeap() { NotImplemented(); }
- virtual void __stdcall ClrHeapCreate() { NotImplemented(); }
- virtual void __stdcall ClrHeapDestroy() { NotImplemented(); }
- virtual void __stdcall ClrHeapAlloc() { NotImplemented(); }
- virtual void __stdcall ClrHeapFree() { NotImplemented(); }
- virtual void __stdcall ClrHeapValidate() { NotImplemented(); }
- virtual void __stdcall ClrGetProcessExecutableHeap() { NotImplemented(); }
+ virtual void STDMETHODCALLTYPE ClrVirtualQuery() { NotImplemented(); }
+ virtual void STDMETHODCALLTYPE ClrVirtualProtect() { NotImplemented(); }
+ virtual void STDMETHODCALLTYPE ClrGetProcessHeap() { NotImplemented(); }
+ virtual void STDMETHODCALLTYPE ClrHeapCreate() { NotImplemented(); }
+ virtual void STDMETHODCALLTYPE ClrHeapDestroy() { NotImplemented(); }
+ virtual void STDMETHODCALLTYPE ClrHeapAlloc() { NotImplemented(); }
+ virtual void STDMETHODCALLTYPE ClrHeapFree() { NotImplemented(); }
+ virtual void STDMETHODCALLTYPE ClrHeapValidate() { NotImplemented(); }
+ virtual void STDMETHODCALLTYPE ClrGetProcessExecutableHeap() { NotImplemented(); }
};
static EEMemoryManager eeMemoryManager;
diff --git a/src/Native/jitinterface/jitinterface.h b/src/Native/jitinterface/jitinterface.h
index 9902df650..5d115bde5 100644
--- a/src/Native/jitinterface/jitinterface.h
+++ b/src/Native/jitinterface/jitinterface.h
@@ -164,6 +164,7 @@ struct JitInterfaceCallbacks
void* (* GetDelegateCtor)(void * thisHandle, CorInfoException** ppException, void* methHnd, void* clsHnd, void* targetMethodHnd, void* pCtorData);
void (* MethodCompileComplete)(void * thisHandle, CorInfoException** ppException, void* methHnd);
void* (* getTailCallCopyArgsThunk)(void * thisHandle, CorInfoException** ppException, void* pSig, int flags);
+ bool (* convertPInvokeCalliToCall)(void * thisHandle, CorInfoException** ppException, void* pResolvedToken, bool mustConvert);
void* (* getMemoryManager)(void * thisHandle, CorInfoException** ppException);
void (* allocMem)(void * thisHandle, CorInfoException** ppException, unsigned int hotCodeSize, unsigned int coldCodeSize, unsigned int roDataSize, unsigned int xcptnsCount, int flag, void** hotCodeBlock, void** coldCodeBlock, void** roDataBlock);
void (* reserveUnwindInfo)(void * thisHandle, CorInfoException** ppException, int isFunclet, int isColdCode, unsigned int unwindSize);
@@ -1516,6 +1517,15 @@ public:
return _ret;
}
+ virtual bool convertPInvokeCalliToCall(void* pResolvedToken, bool mustConvert)
+ {
+ CorInfoException* pException = nullptr;
+ bool _ret = _callbacks->convertPInvokeCalliToCall(_thisHandle, &pException, pResolvedToken, mustConvert);
+ if (pException != nullptr)
+ throw pException;
+ return _ret;
+ }
+
virtual void* getMemoryManager();
virtual void allocMem(unsigned int hotCodeSize, unsigned int coldCodeSize, unsigned int roDataSize, unsigned int xcptnsCount, int flag, void** hotCodeBlock, void** coldCodeBlock, void** roDataBlock)
{
diff --git a/src/Native/jitinterface/jitwrapper.cpp b/src/Native/jitinterface/jitwrapper.cpp
index ac5264b7d..069ef0739 100644
--- a/src/Native/jitinterface/jitwrapper.cpp
+++ b/src/Native/jitinterface/jitwrapper.cpp
@@ -27,11 +27,11 @@ private:
unsigned __int64 corJitFlags;
};
-static const GUID JITEEVersionIdentifier = { /* 0ba106c8-81a0-407f-99a1-928448c1eb62 */
- 0x0ba106c8,
- 0x81a0,
- 0x407f,
- {0x99, 0xa1, 0x92, 0x84, 0x48, 0xc1, 0xeb, 0x62}
+static const GUID JITEEVersionIdentifier = { /* 45aafd4d-1d23-4647-9ce1-cf09a2677ca0 */
+ 0x45aafd4d,
+ 0x1d23,
+ 0x4647,
+ {0x9c, 0xe1, 0xcf, 0x09, 0xa2, 0x67, 0x7c, 0xa0}
};
class Jit
diff --git a/src/Native/libunwind/include/libunwind.h b/src/Native/libunwind/include/libunwind.h
index 59187798d..2e11f48d9 100644
--- a/src/Native/libunwind/include/libunwind.h
+++ b/src/Native/libunwind/include/libunwind.h
@@ -124,7 +124,7 @@ extern int unw_init_local(unw_cursor_t *, unw_context_t *) LIBUNWIND_AVAIL;
extern int unw_step(unw_cursor_t *) LIBUNWIND_AVAIL;
extern int unw_get_reg(unw_cursor_t *, unw_regnum_t, unw_word_t *) LIBUNWIND_AVAIL;
extern int unw_get_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t *) LIBUNWIND_AVAIL;
-extern int unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t) LIBUNWIND_AVAIL;
+extern int unw_set_reg(unw_cursor_t *, unw_regnum_t, unw_word_t, unw_word_t *) LIBUNWIND_AVAIL;
extern int unw_set_fpreg(unw_cursor_t *, unw_regnum_t, unw_fpreg_t) LIBUNWIND_AVAIL;
extern int unw_resume(unw_cursor_t *) LIBUNWIND_AVAIL;
diff --git a/src/Native/libunwind/include/unwind.h b/src/Native/libunwind/include/unwind.h
index 1d163ca9a..a350f51ad 100644
--- a/src/Native/libunwind/include/unwind.h
+++ b/src/Native/libunwind/include/unwind.h
@@ -200,7 +200,7 @@ _Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
extern _Unwind_VRS_Result
_Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
uint32_t regno, _Unwind_VRS_DataRepresentation representation,
- void *valuep);
+ void *valuep, uint32_t *pos);
extern _Unwind_VRS_Result
_Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
@@ -212,7 +212,7 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
extern uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index);
extern void _Unwind_SetGR(struct _Unwind_Context *context, int index,
- uintptr_t new_value);
+ uintptr_t new_value, uintptr_t *pos);
extern uintptr_t _Unwind_GetIP(struct _Unwind_Context *context);
extern void _Unwind_SetIP(struct _Unwind_Context *, uintptr_t new_value);
@@ -240,8 +240,8 @@ uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) {
_LIBUNWIND_EXPORT_UNWIND_LEVEL1
void _Unwind_SetGR(struct _Unwind_Context *context, int index,
- uintptr_t value) {
- _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value);
+ uintptr_t value,uintptr_t *pos) {
+ _Unwind_VRS_Set(context, _UVRSC_CORE, (uint32_t)index, _UVRSD_UINT32, &value, pos);
}
_LIBUNWIND_EXPORT_UNWIND_LEVEL1
@@ -253,7 +253,7 @@ uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
_LIBUNWIND_EXPORT_UNWIND_LEVEL1
void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t value) {
uintptr_t thumb_bit = _Unwind_GetGR(context, 15) & ((uintptr_t)0x1);
- _Unwind_SetGR(context, 15, value | thumb_bit);
+ _Unwind_SetGR(context, 15, value | thumb_bit, NULL);
}
#endif // _LIBUNWIND_ARM_EHABI
diff --git a/src/Native/libunwind/src/Unwind-EHABI.cpp b/src/Native/libunwind/src/Unwind-EHABI.cpp
index 18b82f8c8..31da198c4 100644
--- a/src/Native/libunwind/src/Unwind-EHABI.cpp
+++ b/src/Native/libunwind/src/Unwind-EHABI.cpp
@@ -217,7 +217,7 @@ decode_eht_entry(const uint32_t* data, size_t* off, size_t* len) {
// only by the personality routine. Fortunately, all existing assembler
// implementations, including GNU assembler, LLVM integrated assembler,
// and ARM assembler, assume that the unwind opcodes come after the
- // personality rountine address.
+ // personality routine address.
*off = 1; // First byte is size data.
*len = (((data[1] >> 24) & 0xff) + 1) * 4;
data++; // Skip the first word, which is the prel31 offset.
@@ -259,7 +259,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data,
sp -= (((uint32_t)byte & 0x3f) << 2) + 4;
else
sp += ((uint32_t)byte << 2) + 4;
- _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);
+ _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp, NULL);
} else {
switch (byte & 0xf0) {
case 0x80: {
@@ -283,7 +283,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data,
_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_R0 + reg,
_UVRSD_UINT32, &sp);
_Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,
- &sp);
+ &sp, NULL);
break;
}
case 0xa0: {
@@ -325,7 +325,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data,
&sp);
sp += 0x204 + (addend << 2);
_Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,
- &sp);
+ &sp, NULL);
break;
}
case 0xb3: {
@@ -411,7 +411,7 @@ _Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data,
if (!wrotePC) {
uint32_t lr;
_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_LR, _UVRSD_UINT32, &lr);
- _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr);
+ _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr, NULL);
}
return _URC_CONTINUE_UNWIND;
}
@@ -559,7 +559,7 @@ static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor
//
// See #7.4.6 for details.
unw_set_reg(cursor, UNW_REG_IP,
- exception_object->unwinder_cache.reserved2);
+ exception_object->unwinder_cache.reserved2, NULL);
resume = false;
}
@@ -753,7 +753,7 @@ static uint64_t ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation,
_LIBUNWIND_EXPORT _Unwind_VRS_Result
_Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
uint32_t regno, _Unwind_VRS_DataRepresentation representation,
- void *valuep) {
+ void *valuep, unw_word_t *pos) {
_LIBUNWIND_TRACE_API("_Unwind_VRS_Set(context=%p, regclass=%d, reg=%d, "
"rep=%d, value=0x%llX)",
static_cast<void *>(context), regclass, regno,
@@ -765,7 +765,7 @@ _Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
if (representation != _UVRSD_UINT32 || regno > 15)
return _UVRSR_FAILED;
return unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_R0 + regno),
- *(unw_word_t *)valuep) == UNW_ESUCCESS
+ *(unw_word_t *)valuep,(unw_word_t *)pos) == UNW_ESUCCESS
? _UVRSR_OK
: _UVRSR_FAILED;
case _UVRSC_VFP:
@@ -897,6 +897,7 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
// computed new stack location. See EHABI #7.5.4 table 3.
bool poppedSP = false;
uint32_t* sp;
+ uint32_t* pos;
if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP,
_UVRSD_UINT32, &sp) != _UVRSR_OK) {
return _UVRSR_FAILED;
@@ -904,17 +905,18 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
for (uint32_t i = 0; i < 16; ++i) {
if (!(discriminator & static_cast<uint32_t>(1 << i)))
continue;
+ pos = sp;
uint32_t value = *sp++;
if (regclass == _UVRSC_CORE && i == 13)
poppedSP = true;
if (_Unwind_VRS_Set(context, regclass, i,
- _UVRSD_UINT32, &value) != _UVRSR_OK) {
+ _UVRSD_UINT32, &value, pos) != _UVRSR_OK) {
return _UVRSR_FAILED;
}
}
if (!poppedSP) {
return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP,
- _UVRSD_UINT32, &sp);
+ _UVRSD_UINT32, &sp, NULL);
}
return _UVRSR_OK;
}
@@ -939,14 +941,14 @@ _Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
// SP is only 32-bit aligned so don't copy 64-bit at a time.
uint64_t value = *sp++;
value |= ((uint64_t)(*sp++)) << 32;
- if (_Unwind_VRS_Set(context, regclass, i, representation, &value) !=
+ if (_Unwind_VRS_Set(context, regclass, i, representation, &value, NULL) !=
_UVRSR_OK)
return _UVRSR_FAILED;
}
if (representation == _UVRSD_VFPX)
++sp;
return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,
- &sp);
+ &sp, NULL);
}
}
_LIBUNWIND_ABORT("unsupported register class");
diff --git a/src/Native/libunwind/src/UnwindCursor.hpp b/src/Native/libunwind/src/UnwindCursor.hpp
index f68eee18e..17cd33c47 100644
--- a/src/Native/libunwind/src/UnwindCursor.hpp
+++ b/src/Native/libunwind/src/UnwindCursor.hpp
@@ -628,9 +628,11 @@ UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
}
template <typename A, typename R>
-UnwindCursor<A, R>::UnwindCursor(A &as, void *)
- : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) {
+UnwindCursor<A, R>::UnwindCursor(A &as, void *arg)
+ : _addressSpace(as),_registers(arg), _unwindInfoMissing(false),
+ _isSignalFrame(false) {
memset(&_info, 0, sizeof(_info));
+
// FIXME
// fill in _registers from thread arg
}
diff --git a/src/Native/libunwind/src/config.h b/src/Native/libunwind/src/config.h
index bba0f9c9f..d8bcac882 100644
--- a/src/Native/libunwind/src/config.h
+++ b/src/Native/libunwind/src/config.h
@@ -42,13 +42,8 @@
#endif
#else
#if defined(__ARM_DWARF_EH__) || !defined(__arm__)
- #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 0
#define _LIBUNWIND_SUPPORT_DWARF_UNWIND 1
#define _LIBUNWIND_SUPPORT_DWARF_INDEX 1
- #else
- #define _LIBUNWIND_SUPPORT_COMPACT_UNWIND 0
- #define _LIBUNWIND_SUPPORT_DWARF_UNWIND 0
- #define _LIBUNWIND_SUPPORT_DWARF_INDEX 0
#endif
#endif
diff --git a/src/Native/libunwind/src/libunwind.cpp b/src/Native/libunwind/src/libunwind.cpp
index c9e3ba15a..00c0fc377 100644
--- a/src/Native/libunwind/src/libunwind.cpp
+++ b/src/Native/libunwind/src/libunwind.cpp
@@ -171,14 +171,14 @@ _LIBUNWIND_EXPORT int unw_get_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
/// Set value of specified register at cursor position in stack frame.
_LIBUNWIND_EXPORT int unw_set_reg(unw_cursor_t *cursor, unw_regnum_t regNum,
- unw_word_t value) {
+ unw_word_t value, unw_word_t *pos) {
_LIBUNWIND_TRACE_API("unw_set_reg(cursor=%p, regNum=%d, value=0x%llX)",
static_cast<void *>(cursor), regNum, (long long)value);
typedef LocalAddressSpace::pint_t pint_t;
AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
if (co->validReg(regNum)) {
- co->setReg(regNum, (pint_t)value, 0);
- // specical case altering IP to re-find info (being called by personality
+ co->setReg(regNum, (pint_t)value, (pint_t)pos);
+ // special case altering IP to re-find info (being called by personality
// function)
if (regNum == UNW_REG_IP)
co->setInfoBasedOnIPRegister(false);
diff --git a/src/Runtime.Base/src/Internal/Runtime/CompilerServices/Unsafe.cs b/src/Runtime.Base/src/Internal/Runtime/CompilerServices/Unsafe.cs
index 705193a3c..c63760b39 100644
--- a/src/Runtime.Base/src/Internal/Runtime/CompilerServices/Unsafe.cs
+++ b/src/Runtime.Base/src/Internal/Runtime/CompilerServices/Unsafe.cs
@@ -21,8 +21,22 @@ namespace Internal.Runtime.CompilerServices
/// <summary>
/// Contains generic, low-level functionality for manipulating pointers.
/// </summary>
- public static class Unsafe
+ public static unsafe class Unsafe
{
+ /// <summary>
+ /// Returns a pointer to the given by-ref parameter.
+ /// </summary>
+ [Intrinsic]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void* AsPointer<T>(ref T value)
+ {
+ throw new PlatformNotSupportedException();
+
+ // ldarg.0
+ // conv.u
+ // ret
+ }
+
[Intrinsic]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int SizeOf<T>()
@@ -83,5 +97,15 @@ namespace Internal.Runtime.CompilerServices
{
return ref AddByteOffset(ref source, (IntPtr)(elementOffset * (nint)SizeOf<T>()));
}
+
+ /// <summary>
+ /// Reinterprets the given location as a reference to a value of type <typeparamref name="T"/>.
+ /// </summary>
+ [Intrinsic]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ref T AsRef<T>(in T source)
+ {
+ throw new PlatformNotSupportedException();
+ }
}
}
diff --git a/src/Runtime.Base/src/Runtime.Base.csproj b/src/Runtime.Base/src/Runtime.Base.csproj
index daa602215..58d17c3b9 100644
--- a/src/Runtime.Base/src/Runtime.Base.csproj
+++ b/src/Runtime.Base/src/Runtime.Base.csproj
@@ -77,6 +77,7 @@
<Compile Include="System\Runtime\CompilerServices\MethodImplAttribute.cs" />
<Compile Include="System\Runtime\CompilerServices\RuntimeHelpers.cs" />
<Compile Include="System\Runtime\CompilerServices\UnsafeValueTypeAttribute.cs" />
+ <Compile Include="System\Runtime\InteropServices\UnmanagedType.cs" />
<Compile Include="System\Runtime\InteropServices\CallingConvention.cs" />
<Compile Include="System\Runtime\InteropServices\CharSet.cs" />
<Compile Include="System\Runtime\InteropServices\DllImportAttribute.cs" />
diff --git a/src/Runtime.Base/src/System/Runtime/CachedInterfaceDispatch.cs b/src/Runtime.Base/src/System/Runtime/CachedInterfaceDispatch.cs
index 6ca1646c7..e4adb402e 100644
--- a/src/Runtime.Base/src/System/Runtime/CachedInterfaceDispatch.cs
+++ b/src/Runtime.Base/src/System/Runtime/CachedInterfaceDispatch.cs
@@ -17,7 +17,7 @@ namespace System.Runtime
unsafe private static IntPtr RhpCidResolve(IntPtr callerTransitionBlockParam, IntPtr pCell)
{
IntPtr locationOfThisPointer = callerTransitionBlockParam + TransitionBlock.GetThisOffset();
- object pObject = Unsafe.As<IntPtr, Object>(ref *(IntPtr*)locationOfThisPointer);
+ object pObject = Unsafe.As<IntPtr, object>(ref *(IntPtr*)locationOfThisPointer);
IntPtr dispatchResolveTarget = RhpCidResolve_Worker(pObject, pCell);
if (dispatchResolveTarget == InternalCalls.RhpGetCastableObjectDispatchHelper())
diff --git a/src/Runtime.Base/src/System/Runtime/CastableObjectSupport.cs b/src/Runtime.Base/src/System/Runtime/CastableObjectSupport.cs
index 20f0ce285..5ed1679c5 100644
--- a/src/Runtime.Base/src/System/Runtime/CastableObjectSupport.cs
+++ b/src/Runtime.Base/src/System/Runtime/CastableObjectSupport.cs
@@ -324,7 +324,7 @@ namespace System.Runtime
unsafe private static IntPtr RhpCastableObjectResolve(IntPtr callerTransitionBlockParam, IntPtr pCell)
{
IntPtr locationOfThisPointer = callerTransitionBlockParam + TransitionBlock.GetThisOffset();
- object pObject = Unsafe.As<IntPtr, Object>(ref *(IntPtr*)locationOfThisPointer);
+ object pObject = Unsafe.As<IntPtr, object>(ref *(IntPtr*)locationOfThisPointer);
DispatchCellInfo cellInfo;
InternalCalls.RhpGetDispatchCellInfo(pCell, out cellInfo);
@@ -343,7 +343,7 @@ namespace System.Runtime
if (targetObject == null)
EH.FailFastViaClasslib(RhFailFastReason.InternalError, null, pObject.EEType->GetAssociatedModuleAddress());
- Unsafe.As<IntPtr, Object>(ref *(IntPtr*)locationOfThisPointer) = targetObject;
+ Unsafe.As<IntPtr, object>(ref *(IntPtr*)locationOfThisPointer) = targetObject;
InternalCalls.RhpSetTLSDispatchCell(pCell);
return InternalCalls.RhpGetTailCallTLSDispatchCell();
diff --git a/src/Runtime.Base/src/System/Runtime/DispatchResolve.cs b/src/Runtime.Base/src/System/Runtime/DispatchResolve.cs
index c609d878b..83d5571c0 100644
--- a/src/Runtime.Base/src/System/Runtime/DispatchResolve.cs
+++ b/src/Runtime.Base/src/System/Runtime/DispatchResolve.cs
@@ -47,7 +47,7 @@ namespace System.Runtime
while (pCur != null)
{
- UInt16 implSlotNumber;
+ ushort implSlotNumber;
if (FindImplSlotForCurrentType(
pCur, pItfType, itfSlotNumber, &implSlotNumber))
{
@@ -76,8 +76,8 @@ namespace System.Runtime
private static bool FindImplSlotForCurrentType(EEType* pTgtType,
EEType* pItfType,
- UInt16 itfSlotNumber,
- UInt16* pImplSlotNumber)
+ ushort itfSlotNumber,
+ ushort* pImplSlotNumber)
{
bool fRes = false;
@@ -117,8 +117,8 @@ namespace System.Runtime
private static bool FindImplSlotInSimpleMap(EEType* pTgtType,
EEType* pItfType,
- UInt32 itfSlotNumber,
- UInt16* pImplSlotNumber,
+ uint itfSlotNumber,
+ ushort* pImplSlotNumber,
bool actuallyCheckVariance)
{
Debug.Assert(pTgtType->HasDispatchMap, "Missing dispatch map");
@@ -226,7 +226,7 @@ namespace System.Runtime
// arity of both had better be the same.
Debug.Assert(itfArity == (int)pCurEntryType->GenericArity, "arity mismatch betweeen generic instantiations");
- if (TypeCast.TypeParametersAreCompatible(itfArity, pCurEntryInstantiation, pItfInstantiation, pItfVarianceInfo, fArrayCovariance))
+ if (TypeCast.TypeParametersAreCompatible(itfArity, pCurEntryInstantiation, pItfInstantiation, pItfVarianceInfo, fArrayCovariance, null))
{
*pImplSlotNumber = i->_usImplMethodSlot;
return true;
diff --git a/src/Runtime.Base/src/System/Runtime/ExceptionHandling.cs b/src/Runtime.Base/src/System/Runtime/ExceptionHandling.cs
index 4d3cdf674..b4e58dbad 100644
--- a/src/Runtime.Base/src/System/Runtime/ExceptionHandling.cs
+++ b/src/Runtime.Base/src/System/Runtime/ExceptionHandling.cs
@@ -728,7 +728,11 @@ namespace System.Runtime
Debug.Assert(isValid, "second-pass EH unwind failed unexpectedly");
DebugScanCallFrame(exInfo._passNumber, frameIter.ControlPC, frameIter.SP);
- if (frameIter.SP == handlingFrameSP)
+ if ((frameIter.SP == handlingFrameSP)
+#if ARM64
+ && (frameIter.ControlPC == prevControlPC)
+#endif
+ )
{
// invoke only a partial second-pass here...
InvokeSecondPass(ref exInfo, startIdx, catchingTryRegionIdx);
diff --git a/src/Runtime.Base/src/System/Runtime/InternalCalls.cs b/src/Runtime.Base/src/System/Runtime/InternalCalls.cs
index e647e3ab0..866247ac2 100644
--- a/src/Runtime.Base/src/System/Runtime/InternalCalls.cs
+++ b/src/Runtime.Base/src/System/Runtime/InternalCalls.cs
@@ -72,13 +72,13 @@ namespace System.Runtime
private static extern long RhpGetGcTotalMemory();
[RuntimeExport("RhStartNoGCRegion")]
- internal static Int32 RhStartNoGCRegion(Int64 totalSize, bool hasLohSize, Int64 lohSize, bool disallowFullBlockingGC)
+ internal static int RhStartNoGCRegion(long totalSize, bool hasLohSize, long lohSize, bool disallowFullBlockingGC)
{
return RhpStartNoGCRegion(totalSize, hasLohSize, lohSize, disallowFullBlockingGC);
}
[RuntimeExport("RhEndNoGCRegion")]
- internal static Int32 RhEndNoGCRegion()
+ internal static int RhEndNoGCRegion()
{
return RhpEndNoGCRegion();
}
@@ -91,7 +91,7 @@ namespace System.Runtime
[RuntimeImport(Redhawk.BaseName, "RhpGetNextFinalizableObject")]
[MethodImpl(MethodImplOptions.InternalCall)]
[ManuallyManaged(GcPollPolicy.Never)]
- internal static extern Object RhpGetNextFinalizableObject();
+ internal static extern object RhpGetNextFinalizableObject();
//
// internalcalls for System.Runtime.InteropServices.GCHandle.
@@ -101,29 +101,29 @@ namespace System.Runtime
[RuntimeImport(Redhawk.BaseName, "RhpHandleAlloc")]
[MethodImpl(MethodImplOptions.InternalCall)]
[ManuallyManaged(GcPollPolicy.Never)]
- internal static extern IntPtr RhpHandleAlloc(Object value, GCHandleType type);
+ internal static extern IntPtr RhpHandleAlloc(object value, GCHandleType type);
// Allocate dependent handle.
[RuntimeImport(Redhawk.BaseName, "RhpHandleAllocDependent")]
[MethodImpl(MethodImplOptions.InternalCall)]
[ManuallyManaged(GcPollPolicy.Never)]
- internal static extern IntPtr RhpHandleAllocDependent(Object primary, Object secondary);
+ internal static extern IntPtr RhpHandleAllocDependent(object primary, object secondary);
// Allocate variable handle.
[RuntimeImport(Redhawk.BaseName, "RhpHandleAllocVariable")]
[MethodImpl(MethodImplOptions.InternalCall)]
[ManuallyManaged(GcPollPolicy.Never)]
- internal static extern IntPtr RhpHandleAllocVariable(Object value, uint type);
+ internal static extern IntPtr RhpHandleAllocVariable(object value, uint type);
[RuntimeImport(Redhawk.BaseName, "RhHandleGet")]
[MethodImpl(MethodImplOptions.InternalCall)]
[ManuallyManaged(GcPollPolicy.Never)]
- internal static extern Object RhHandleGet(IntPtr handle);
+ internal static extern object RhHandleGet(IntPtr handle);
[RuntimeImport(Redhawk.BaseName, "RhHandleSet")]
[MethodImpl(MethodImplOptions.InternalCall)]
[ManuallyManaged(GcPollPolicy.Never)]
- internal static extern IntPtr RhHandleSet(IntPtr handle, Object value);
+ internal static extern IntPtr RhHandleSet(IntPtr handle, object value);
//
// internal calls for allocation
@@ -188,7 +188,7 @@ namespace System.Runtime
[RuntimeImport(Redhawk.BaseName, "RhpAssignRef")]
[MethodImpl(MethodImplOptions.InternalCall)]
[ManuallyManaged(GcPollPolicy.Never)]
- internal extern static unsafe void RhpAssignRef(ref Object address, object obj);
+ internal extern static unsafe void RhpAssignRef(ref object address, object obj);
#if FEATURE_GC_STRESS
//
@@ -289,7 +289,7 @@ namespace System.Runtime
[RuntimeImport(Redhawk.BaseName, "RhpGetEETypeRareFlags")]
[MethodImpl(MethodImplOptions.InternalCall)]
[ManuallyManaged(GcPollPolicy.Never)]
- internal extern static unsafe UInt32 RhpGetEETypeRareFlags(EEType* pEEType);
+ internal extern static unsafe uint RhpGetEETypeRareFlags(EEType* pEEType);
// Retrieve the offset of the value embedded in a Nullable<T>.
[RuntimeImport(Redhawk.BaseName, "RhpGetNullableEETypeValueOffset")]
@@ -428,7 +428,7 @@ namespace System.Runtime
// Block the current thread until at least one object needs to be finalized (returns true) or
// memory is low (returns false and the finalizer thread should initiate a garbage collection).
[DllImport(Redhawk.BaseName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern UInt32 RhpWaitForFinalizerRequest();
+ internal static extern uint RhpWaitForFinalizerRequest();
// Indicate that the current round of finalizations is complete.
[DllImport(Redhawk.BaseName, CallingConvention = CallingConvention.Cdecl)]
@@ -455,11 +455,11 @@ namespace System.Runtime
// Enters a no GC region, possibly doing a blocking GC if there is not enough
// memory available to satisfy the caller's request.
[DllImport(Redhawk.BaseName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern Int32 RhpStartNoGCRegion(Int64 totalSize, bool hasLohSize, Int64 lohSize, bool disallowFullBlockingGC);
+ internal static extern int RhpStartNoGCRegion(long totalSize, bool hasLohSize, long lohSize, bool disallowFullBlockingGC);
// Exits a no GC region, possibly doing a GC to clean up the garbage that
// the caller allocated.
[DllImport(Redhawk.BaseName, CallingConvention = CallingConvention.Cdecl)]
- internal static extern Int32 RhpEndNoGCRegion();
+ internal static extern int RhpEndNoGCRegion();
}
}
diff --git a/src/Runtime.Base/src/System/Runtime/InteropServices/UnmanagedType.cs b/src/Runtime.Base/src/System/Runtime/InteropServices/UnmanagedType.cs
new file mode 100644
index 000000000..143ed33c0
--- /dev/null
+++ b/src/Runtime.Base/src/System/Runtime/InteropServices/UnmanagedType.cs
@@ -0,0 +1,8 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices
+{
+ internal class UnmanagedType { }
+}
diff --git a/src/Runtime.Base/src/System/Runtime/RuntimeExports.cs b/src/Runtime.Base/src/System/Runtime/RuntimeExports.cs
index db9b5de74..0c84e7c1f 100644
--- a/src/Runtime.Base/src/System/Runtime/RuntimeExports.cs
+++ b/src/Runtime.Base/src/System/Runtime/RuntimeExports.cs
@@ -121,7 +121,7 @@ namespace System.Runtime
}
else
{
- return Unsafe.As<byte, Object>(ref data);
+ return Unsafe.As<byte, object>(ref data);
}
}
@@ -189,7 +189,7 @@ namespace System.Runtime
throw ptrUnboxToEEType->GetClasslibException(ExceptionIDs.InvalidCast);
}
- Unsafe.As<byte, Object>(ref data) = o;
+ Unsafe.As<byte, object>(ref data) = o;
}
}
@@ -197,7 +197,7 @@ namespace System.Runtime
// Unbox helpers with RyuJIT conventions
//
[RuntimeExport("RhUnbox2")]
- public static unsafe ref byte RhUnbox2(EETypePtr pUnboxToEEType, Object obj)
+ public static unsafe ref byte RhUnbox2(EETypePtr pUnboxToEEType, object obj)
{
EEType* ptrUnboxToEEType = (EEType*)pUnboxToEEType.ToPointer();
if ((obj == null) || !UnboxAnyTypeCompare(obj.EEType, ptrUnboxToEEType))
@@ -209,7 +209,7 @@ namespace System.Runtime
}
[RuntimeExport("RhUnboxNullable")]
- public static unsafe void RhUnboxNullable(ref byte data, EETypePtr pUnboxToEEType, Object obj)
+ public static unsafe void RhUnboxNullable(ref byte data, EETypePtr pUnboxToEEType, object obj)
{
EEType* ptrUnboxToEEType = (EEType*)pUnboxToEEType.ToPointer();
if ((obj != null) && !TypeCast.AreTypesEquivalentInternal(obj.EEType, ptrUnboxToEEType->NullableType))
@@ -235,7 +235,7 @@ namespace System.Runtime
return;
}
- TypeCast.CheckArrayStore(array, Unsafe.As<byte, Object>(ref data));
+ TypeCast.CheckArrayStore(array, Unsafe.As<byte, object>(ref data));
}
[RuntimeExport("RhBoxAndNullCheck")]
@@ -245,13 +245,13 @@ namespace System.Runtime
if (ptrEEType->IsValueType)
return true;
else
- return Unsafe.As<byte, Object>(ref data) != null;
+ return Unsafe.As<byte, object>(ref data) != null;
}
#pragma warning disable 169 // The field 'System.Runtime.RuntimeExports.Wrapper.o' is never used.
private class Wrapper
{
- private Object _o;
+ private object _o;
}
#pragma warning restore 169
diff --git a/src/Runtime.Base/src/System/Runtime/TypeCast.cs b/src/Runtime.Base/src/System/Runtime/TypeCast.cs
index 568892a65..5d6ad5386 100644
--- a/src/Runtime.Base/src/System/Runtime/TypeCast.cs
+++ b/src/Runtime.Base/src/System/Runtime/TypeCast.cs
@@ -111,7 +111,7 @@ namespace System.Runtime
// parameters are compatible.
// NOTE: using general assignable path for the cache because of the cost of the variance checks
- if (CastCache.AreTypesAssignableInternal(pObjType, pTargetType, AssignmentVariation.BoxedSource))
+ if (CastCache.AreTypesAssignableInternal(pObjType, pTargetType, AssignmentVariation.BoxedSource, null))
return obj;
return null;
}
@@ -154,7 +154,7 @@ namespace System.Runtime
}
[RuntimeExport("RhTypeCast_CheckCastClass")]
- public static unsafe object CheckCastClass(Object obj, void* pvTargetEEType)
+ public static unsafe object CheckCastClass(object obj, void* pvTargetEEType)
{
// a null value can be cast to anything
if (obj == null)
@@ -174,7 +174,7 @@ namespace System.Runtime
}
[RuntimeExport("RhTypeCast_CheckUnbox")]
- public static unsafe void CheckUnbox(Object obj, byte expectedCorElementType)
+ public static unsafe void CheckUnbox(object obj, byte expectedCorElementType)
{
if (obj == null)
{
@@ -230,7 +230,7 @@ namespace System.Runtime
}
if (CastCache.AreTypesAssignableInternal(pObjType->RelatedParameterType, pTargetType->RelatedParameterType,
- AssignmentVariation.AllowSizeEquivalence))
+ AssignmentVariation.AllowSizeEquivalence, null))
{
return obj;
}
@@ -239,7 +239,7 @@ namespace System.Runtime
}
[RuntimeExport("RhTypeCast_CheckCastArray")]
- public static unsafe object CheckCastArray(Object obj, void* pvTargetEEType)
+ public static unsafe object CheckCastArray(object obj, void* pvTargetEEType)
{
// a null value can be cast to anything
if (obj == null)
@@ -269,7 +269,7 @@ namespace System.Runtime
EEType* pTargetType = (EEType*)pvTargetType;
EEType* pObjType = obj.EEType;
- if (CastCache.AreTypesAssignableInternal_SourceNotTarget_BoxedSource(pObjType, pTargetType))
+ if (CastCache.AreTypesAssignableInternal_SourceNotTarget_BoxedSource(pObjType, pTargetType, null))
return obj;
// If object type implements ICastable then there's one more way to check whether it implements
@@ -333,7 +333,7 @@ namespace System.Runtime
// TODO!! END REMOVE THIS CODE WHEN WE REMOVE ICASTABLE
}
- internal static unsafe bool ImplementsInterface(EEType* pObjType, EEType* pTargetType)
+ internal static unsafe bool ImplementsInterface(EEType* pObjType, EEType* pTargetType, EETypePairList* pVisited)
{
Debug.Assert(!pTargetType->IsParameterizedType, "did not expect paramterized type");
Debug.Assert(pTargetType->IsInterface, "IsInstanceOfInterface called with non-interface EEType");
@@ -413,7 +413,8 @@ namespace System.Runtime
pInterfaceInstantiation,
pTargetInstantiation,
pTargetVarianceInfo,
- fArrayCovariance))
+ fArrayCovariance,
+ pVisited))
return true;
}
}
@@ -435,7 +436,7 @@ namespace System.Runtime
}
// Compare two types to see if they are compatible via generic variance.
- private static unsafe bool TypesAreCompatibleViaGenericVariance(EEType* pSourceType, EEType* pTargetType)
+ private static unsafe bool TypesAreCompatibleViaGenericVariance(EEType* pSourceType, EEType* pTargetType, EETypePairList* pVisited)
{
EEType* pTargetGenericType = pTargetType->GenericDefinition;
EEType* pSourceGenericType = pSourceType->GenericDefinition;
@@ -466,7 +467,8 @@ namespace System.Runtime
pSourceInstantiation,
pTargetInstantiation,
pTargetVarianceInfo,
- false))
+ false,
+ pVisited))
{
return true;
}
@@ -484,7 +486,8 @@ namespace System.Runtime
EETypeRef* pSourceInstantiation,
EETypeRef* pTargetInstantiation,
GenericVariance* pVarianceInfo,
- bool fForceCovariance)
+ bool fForceCovariance,
+ EETypePairList* pVisited)
{
// Walk through the instantiations comparing the cast compatibility of each pair
// of type args.
@@ -519,7 +522,7 @@ namespace System.Runtime
// class Foo : ICovariant<Bar> is ICovariant<IBar>
// class Foo : ICovariant<IBar> is ICovariant<Object>
- if (!CastCache.AreTypesAssignableInternal(pSourceArgType, pTargetArgType, AssignmentVariation.Normal))
+ if (!CastCache.AreTypesAssignableInternal(pSourceArgType, pTargetArgType, AssignmentVariation.Normal, pVisited))
return false;
break;
@@ -534,7 +537,7 @@ namespace System.Runtime
// This call is just like the call for Covariance above except true is passed
// to the fAllowSizeEquivalence parameter to allow the int/uint matching to work
- if (!CastCache.AreTypesAssignableInternal(pSourceArgType, pTargetArgType, AssignmentVariation.AllowSizeEquivalence))
+ if (!CastCache.AreTypesAssignableInternal(pSourceArgType, pTargetArgType, AssignmentVariation.AllowSizeEquivalence, pVisited))
return false;
break;
@@ -549,7 +552,7 @@ namespace System.Runtime
// class Foo : IContravariant<IBar> is IContravariant<Bar>
// class Foo : IContravariant<Object> is IContravariant<IBar>
- if (!CastCache.AreTypesAssignableInternal(pTargetArgType, pSourceArgType, AssignmentVariation.Normal))
+ if (!CastCache.AreTypesAssignableInternal(pTargetArgType, pSourceArgType, AssignmentVariation.Normal, pVisited))
return false;
break;
@@ -594,7 +597,7 @@ namespace System.Runtime
return AreTypesEquivalentInternal(pSourceType, pNullableType);
}
- return CastCache.AreTypesAssignableInternal(pSourceType, pTargetType, AssignmentVariation.BoxedSource);
+ return CastCache.AreTypesAssignableInternal(pSourceType, pTargetType, AssignmentVariation.BoxedSource, null);
}
// Internally callable version of the export method above. Has two additional flags:
@@ -602,7 +605,7 @@ namespace System.Runtime
// compatible with Object, ValueType and Enum (if applicable)
// fAllowSizeEquivalence : allow identically sized integral types and enums to be considered
// equivalent (currently used only for array element types)
- internal static unsafe bool AreTypesAssignableInternal(EEType* pSourceType, EEType* pTargetType, AssignmentVariation variation)
+ internal static unsafe bool AreTypesAssignableInternal(EEType* pSourceType, EEType* pTargetType, AssignmentVariation variation, EETypePairList* pVisited)
{
bool fBoxedSource = ((variation & AssignmentVariation.BoxedSource) == AssignmentVariation.BoxedSource);
bool fAllowSizeEquivalence = ((variation & AssignmentVariation.AllowSizeEquivalence) == AssignmentVariation.AllowSizeEquivalence);
@@ -622,12 +625,12 @@ namespace System.Runtime
if (!fBoxedSource && pSourceType->IsValueType)
return false;
- if (ImplementsInterface(pSourceType, pTargetType))
+ if (ImplementsInterface(pSourceType, pTargetType, pVisited))
return true;
// Are the types compatible due to generic variance?
if (pTargetType->HasGenericVariance && pSourceType->HasGenericVariance)
- return TypesAreCompatibleViaGenericVariance(pSourceType, pTargetType);
+ return TypesAreCompatibleViaGenericVariance(pSourceType, pTargetType, pVisited);
return false;
}
@@ -667,7 +670,7 @@ namespace System.Runtime
// here handles array covariance as well as IFoo[] -> Foo[] etc. We are not using
// AssignmentVariation.BoxedSource because int[] is not assignable to object[].
return CastCache.AreTypesAssignableInternal(pSourceType->RelatedParameterType,
- pTargetType->RelatedParameterType, AssignmentVariation.AllowSizeEquivalence);
+ pTargetType->RelatedParameterType, AssignmentVariation.AllowSizeEquivalence, pVisited);
}
}
@@ -723,7 +726,7 @@ namespace System.Runtime
// deriving from user delegate classes any further all we have to check here is that the
// uninstantiated generic delegate definitions are the same and the type parameters are
// compatible.
- return TypesAreCompatibleViaGenericVariance(pSourceType, pTargetType);
+ return TypesAreCompatibleViaGenericVariance(pSourceType, pTargetType, pVisited);
}
// Is the source type derived from the target type?
@@ -734,7 +737,7 @@ namespace System.Runtime
}
[RuntimeExport("RhTypeCast_CheckCastInterface")]
- public static unsafe object CheckCastInterface(Object obj, void* pvTargetEEType)
+ public static unsafe object CheckCastInterface(object obj, void* pvTargetEEType)
{
// a null value can be cast to anything
if (obj == null)
@@ -745,7 +748,7 @@ namespace System.Runtime
EEType* pTargetType = (EEType*)pvTargetEEType;
EEType* pObjType = obj.EEType;
- if (CastCache.AreTypesAssignableInternal_SourceNotTarget_BoxedSource(pObjType, pTargetType))
+ if (CastCache.AreTypesAssignableInternal_SourceNotTarget_BoxedSource(pObjType, pTargetType, null))
return obj;
Exception castError = null;
@@ -779,7 +782,7 @@ namespace System.Runtime
Debug.Assert(array.EEType->IsArray, "first argument must be an array");
EEType* arrayElemType = array.EEType->RelatedParameterType;
- if (CastCache.AreTypesAssignableInternal(obj.EEType, arrayElemType, AssignmentVariation.BoxedSource))
+ if (CastCache.AreTypesAssignableInternal(obj.EEType, arrayElemType, AssignmentVariation.BoxedSource, null))
return;
// If object type implements ICastable then there's one more way to check whether it implements
@@ -842,7 +845,7 @@ namespace System.Runtime
{
EEType* arrayElemType = array.EEType->RelatedParameterType;
- if (!CastCache.AreTypesAssignableInternal(obj.EEType, arrayElemType, AssignmentVariation.BoxedSource))
+ if (!CastCache.AreTypesAssignableInternal(obj.EEType, arrayElemType, AssignmentVariation.BoxedSource, null))
{
// If object type implements ICastable then there's one more way to check whether it implements
// the interface.
@@ -858,7 +861,7 @@ namespace System.Runtime
// Both bounds and type check are ok.
// Call write barrier directly. Assigning object reference would call slower checked write barrier.
- ref Object rawData = ref Unsafe.As<byte, Object>(ref array.GetRawSzArrayData());
+ ref object rawData = ref Unsafe.As<byte, object>(ref array.GetRawSzArrayData());
InternalCalls.RhpAssignRef(ref Unsafe.Add(ref rawData, index), obj);
}
else
@@ -870,7 +873,7 @@ namespace System.Runtime
}
[RuntimeExport("RhpLdelemaRef")]
- public static unsafe ref Object LdelemaRef(Array array, int index, IntPtr elementType)
+ public static unsafe ref object LdelemaRef(Array array, int index, IntPtr elementType)
{
Debug.Assert(array.EEType->IsArray, "first argument must be an array");
@@ -885,7 +888,7 @@ namespace System.Runtime
throw array.EEType->GetClasslibException(ExceptionIDs.ArrayTypeMismatch);
}
- ref Object rawData = ref Unsafe.As<byte, Object>(ref array.GetRawSzArrayData());
+ ref object rawData = ref Unsafe.As<byte, object>(ref array.GetRawSzArrayData());
return ref Unsafe.Add(ref rawData, index);
}
@@ -976,13 +979,13 @@ namespace System.Runtime
}
[RuntimeExport("RhTypeCast_CheckCast2")] // Helper with RyuJIT calling convention
- public static unsafe object CheckCast2(void* pvTargetType, Object obj)
+ public static unsafe object CheckCast2(void* pvTargetType, object obj)
{
return CheckCast(obj, pvTargetType);
}
[RuntimeExport("RhTypeCast_CheckCast")]
- public static unsafe object CheckCast(Object obj, void* pvTargetType)
+ public static unsafe object CheckCast(object obj, void* pvTargetType)
{
// @TODO: consider using the cache directly, but beware of ICastable in the interface case
EEType* pTargetType = (EEType*)pvTargetType;
@@ -1034,6 +1037,33 @@ namespace System.Runtime
}
}
+ internal unsafe struct EETypePairList
+ {
+ private EEType* _eetype1;
+ private EEType* _eetype2;
+ private EETypePairList* _next;
+
+ public EETypePairList(EEType* pEEType1, EEType* pEEType2, EETypePairList* pNext)
+ {
+ _eetype1 = pEEType1;
+ _eetype2 = pEEType2;
+ _next = pNext;
+ }
+
+ public static bool Exists(EETypePairList* pList, EEType* pEEType1, EEType* pEEType2)
+ {
+ while (pList != null)
+ {
+ if (pList->_eetype1 == pEEType1 && pList->_eetype2 == pEEType2)
+ return true;
+ if (pList->_eetype1 == pEEType2 && pList->_eetype2 == pEEType1)
+ return true;
+ pList = pList->_next;
+ }
+ return false;
+ }
+ }
+
// source type + target type + assignment variation -> true/false
[System.Runtime.CompilerServices.EagerStaticClassConstructionAttribute]
private static class CastCache
@@ -1103,7 +1133,7 @@ namespace System.Runtime
public EEType* TargetType { get { return (EEType*)_targetType; } }
}
- public static unsafe bool AreTypesAssignableInternal(EEType* pSourceType, EEType* pTargetType, AssignmentVariation variation)
+ public static unsafe bool AreTypesAssignableInternal(EEType* pSourceType, EEType* pTargetType, AssignmentVariation variation, EETypePairList* pVisited)
{
// Important special case -- it breaks infinite recursion in CastCache itself!
if (pSourceType == pTargetType)
@@ -1112,7 +1142,7 @@ namespace System.Runtime
Key key = new Key(pSourceType, pTargetType, variation);
Entry entry = LookupInCache(s_cache, ref key);
if (entry == null)
- return CacheMiss(ref key);
+ return CacheMiss(ref key, pVisited);
return entry.Result;
}
@@ -1124,13 +1154,13 @@ namespace System.Runtime
// 2. Force inlining (This particular variant is only used in a small number of dispatch scenarios that are particularly
// high in performance impact.)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static unsafe bool AreTypesAssignableInternal_SourceNotTarget_BoxedSource(EEType* pSourceType, EEType* pTargetType)
+ public static unsafe bool AreTypesAssignableInternal_SourceNotTarget_BoxedSource(EEType* pSourceType, EEType* pTargetType, EETypePairList* pVisited)
{
Debug.Assert(pSourceType != pTargetType, "target is source");
Key key = new Key(pSourceType, pTargetType, AssignmentVariation.BoxedSource);
Entry entry = LookupInCache(s_cache, ref key);
if (entry == null)
- return CacheMiss(ref key);
+ return CacheMiss(ref key, pVisited);
return entry.Result;
}
@@ -1149,8 +1179,14 @@ namespace System.Runtime
return entry;
}
- private static unsafe bool CacheMiss(ref Key key)
+ private static unsafe bool CacheMiss(ref Key key, EETypePairList* pVisited)
{
+ //
+ // First, check if we previously visited the input types pair, to avoid infinite recursions
+ //
+ if (EETypePairList.Exists(pVisited, key.SourceType, key.TargetType))
+ return false;
+
bool result = false;
bool previouslyCached = false;
@@ -1177,7 +1213,8 @@ namespace System.Runtime
//
if (!previouslyCached)
{
- result = TypeCast.AreTypesAssignableInternal(key.SourceType, key.TargetType, key.Variation);
+ EETypePairList newList = new EETypePairList(key.SourceType, key.TargetType, pVisited);
+ result = TypeCast.AreTypesAssignableInternal(key.SourceType, key.TargetType, key.Variation, &newList);
}
//
diff --git a/src/Runtime.Base/src/System/Runtime/__Finalizer.cs b/src/Runtime.Base/src/System/Runtime/__Finalizer.cs
index 6fd7d7ea3..0dbc18de4 100644
--- a/src/Runtime.Base/src/System/Runtime/__Finalizer.cs
+++ b/src/Runtime.Base/src/System/Runtime/__Finalizer.cs
@@ -58,7 +58,7 @@ namespace System.Runtime
// Drain the queue of finalizable objects.
while (true)
{
- Object target = InternalCalls.RhpGetNextFinalizableObject();
+ object target = InternalCalls.RhpGetNextFinalizableObject();
if (target == null)
return;
diff --git a/src/System.Private.CoreLib/shared/Internal/Padding.cs b/src/System.Private.CoreLib/shared/Internal/Padding.cs
new file mode 100644
index 000000000..14bf998ba
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/Internal/Padding.cs
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+
+namespace Internal
+{
+ /// <summary>A class for common padding constants and eventually routines.</summary>
+ internal static class PaddingHelpers
+ {
+ /// <summary>A size greater than or equal to the size of the most common CPU cache lines.</summary>
+#if ARM64
+ internal const int CACHE_LINE_SIZE = 128;
+#else
+ internal const int CACHE_LINE_SIZE = 64;
+#endif
+ }
+
+ /// <summary>Padding structure used to minimize false sharing</summary>
+ [StructLayout(LayoutKind.Explicit, Size = PaddingHelpers.CACHE_LINE_SIZE - sizeof(int))]
+ internal struct PaddingFor32
+ {
+ }
+}
+
diff --git a/src/System.Private.CoreLib/shared/Internal/Runtime/CompilerServices/Unsafe.cs b/src/System.Private.CoreLib/shared/Internal/Runtime/CompilerServices/Unsafe.cs
index aeff3ce2c..03d3f8521 100644
--- a/src/System.Private.CoreLib/shared/Internal/Runtime/CompilerServices/Unsafe.cs
+++ b/src/System.Private.CoreLib/shared/Internal/Runtime/CompilerServices/Unsafe.cs
@@ -358,6 +358,17 @@ namespace Internal.Runtime.CompilerServices
}
/// <summary>
+ /// Reinterprets the given location as a reference to a value of type <typeparamref name="T"/>.
+ /// </summary>
+ [Intrinsic]
+ [NonVersionable]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ref T AsRef<T>(in T source)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ /// <summary>
/// Determines the byte offset from origin to target from the given references.
/// </summary>
[Intrinsic]
diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/Interop.Errors.cs b/src/System.Private.CoreLib/shared/Interop/Unix/Interop.Errors.cs
index 4248434db..9cb05809d 100644
--- a/src/System.Private.CoreLib/shared/Interop/Unix/Interop.Errors.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Unix/Interop.Errors.cs
@@ -75,11 +75,13 @@ internal static partial class Interop
ENOTCONN = 0x10038, // The socket is not connected.
ENOTDIR = 0x10039, // Not a directory or a symbolic link to a directory.
ENOTEMPTY = 0x1003A, // Directory not empty.
+ ENOTRECOVERABLE = 0x1003B, // State not recoverable.
ENOTSOCK = 0x1003C, // Not a socket.
ENOTSUP = 0x1003D, // Not supported (same value as EOPNOTSUP).
ENOTTY = 0x1003E, // Inappropriate I/O control operation.
ENXIO = 0x1003F, // No such device or address.
EOVERFLOW = 0x10040, // Value too large to be stored in data type.
+ EOWNERDEAD = 0x10041, // Previous owner died.
EPERM = 0x10042, // Operation not permitted.
EPIPE = 0x10043, // Broken pipe.
EPROTO = 0x10044, // Protocol error.
@@ -186,7 +188,7 @@ internal static partial class Interop
internal static extern int ConvertErrorPalToPlatform(Error error);
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_StrErrorR")]
- private static unsafe extern byte* StrErrorR(int platformErrno, byte* buffer, int bufferSize);
+ private static extern unsafe byte* StrErrorR(int platformErrno, byte* buffer, int bufferSize);
}
}
diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Casing.cs b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Casing.cs
index 25536d483..503a864d6 100644
--- a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Casing.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Casing.cs
@@ -12,12 +12,12 @@ internal static partial class Interop
internal static partial class Globalization
{
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_ChangeCase")]
- internal unsafe static extern void ChangeCase(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper);
+ internal static extern unsafe void ChangeCase(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_ChangeCaseInvariant")]
- internal unsafe static extern void ChangeCaseInvariant(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper);
+ internal static extern unsafe void ChangeCaseInvariant(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_ChangeCaseTurkish")]
- internal unsafe static extern void ChangeCaseTurkish(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper);
+ internal static extern unsafe void ChangeCaseTurkish(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper);
}
}
diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Collation.cs b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Collation.cs
index 08aa6113d..aeeb60ff7 100644
--- a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Collation.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Collation.cs
@@ -12,48 +12,46 @@ internal static partial class Interop
internal static partial class Globalization
{
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetSortHandle")]
- internal unsafe static extern ResultCode GetSortHandle(byte[] localeName, out SafeSortHandle sortHandle);
+ internal static extern unsafe ResultCode GetSortHandle(byte[] localeName, out SafeSortHandle sortHandle);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_CloseSortHandle")]
- internal unsafe static extern void CloseSortHandle(IntPtr handle);
+ internal static extern unsafe void CloseSortHandle(IntPtr handle);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_CompareString")]
- internal unsafe static extern int CompareString(SafeSortHandle sortHandle, char* lpStr1, int cwStr1Len, char* lpStr2, int cwStr2Len, CompareOptions options);
+ internal static extern unsafe int CompareString(SafeSortHandle sortHandle, char* lpStr1, int cwStr1Len, char* lpStr2, int cwStr2Len, CompareOptions options);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_IndexOf")]
- internal unsafe static extern int IndexOf(SafeSortHandle sortHandle, string target, int cwTargetLength, char* pSource, int cwSourceLength, CompareOptions options, int* matchLengthPtr);
- [DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_IndexOf")]
- internal unsafe static extern int IndexOf(SafeSortHandle sortHandle, char* target, int cwTargetLength, char* pSource, int cwSourceLength, CompareOptions options, int* matchLengthPtr);
+ internal static extern unsafe int IndexOf(SafeSortHandle sortHandle, char* target, int cwTargetLength, char* pSource, int cwSourceLength, CompareOptions options, int* matchLengthPtr);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_LastIndexOf")]
- internal unsafe static extern int LastIndexOf(SafeSortHandle sortHandle, string target, int cwTargetLength, char* pSource, int cwSourceLength, CompareOptions options);
+ internal static extern unsafe int LastIndexOf(SafeSortHandle sortHandle, char* target, int cwTargetLength, char* pSource, int cwSourceLength, CompareOptions options);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_IndexOfOrdinalIgnoreCase")]
- internal unsafe static extern int IndexOfOrdinalIgnoreCase(string target, int cwTargetLength, char* pSource, int cwSourceLength, bool findLast);
+ internal static extern unsafe int IndexOfOrdinalIgnoreCase(string target, int cwTargetLength, char* pSource, int cwSourceLength, bool findLast);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_IndexOfOrdinalIgnoreCase")]
- internal unsafe static extern int IndexOfOrdinalIgnoreCase(char* target, int cwTargetLength, char* pSource, int cwSourceLength, bool findLast);
+ internal static extern unsafe int IndexOfOrdinalIgnoreCase(char* target, int cwTargetLength, char* pSource, int cwSourceLength, bool findLast);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_StartsWith")]
[return: MarshalAs(UnmanagedType.Bool)]
- internal unsafe static extern bool StartsWith(SafeSortHandle sortHandle, char* target, int cwTargetLength, char* source, int cwSourceLength, CompareOptions options);
+ internal static extern unsafe bool StartsWith(SafeSortHandle sortHandle, char* target, int cwTargetLength, char* source, int cwSourceLength, CompareOptions options);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_EndsWith")]
[return: MarshalAs(UnmanagedType.Bool)]
- internal unsafe static extern bool EndsWith(SafeSortHandle sortHandle, char* target, int cwTargetLength, char* source, int cwSourceLength, CompareOptions options);
+ internal static extern unsafe bool EndsWith(SafeSortHandle sortHandle, char* target, int cwTargetLength, char* source, int cwSourceLength, CompareOptions options);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_StartsWith")]
[return: MarshalAs(UnmanagedType.Bool)]
- internal unsafe static extern bool StartsWith(SafeSortHandle sortHandle, string target, int cwTargetLength, string source, int cwSourceLength, CompareOptions options);
+ internal static extern unsafe bool StartsWith(SafeSortHandle sortHandle, string target, int cwTargetLength, string source, int cwSourceLength, CompareOptions options);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_EndsWith")]
[return: MarshalAs(UnmanagedType.Bool)]
- internal unsafe static extern bool EndsWith(SafeSortHandle sortHandle, string target, int cwTargetLength, string source, int cwSourceLength, CompareOptions options);
+ internal static extern unsafe bool EndsWith(SafeSortHandle sortHandle, string target, int cwTargetLength, string source, int cwSourceLength, CompareOptions options);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetSortKey")]
- internal unsafe static extern int GetSortKey(SafeSortHandle sortHandle, string str, int strLength, byte* sortKey, int sortKeyLength, CompareOptions options);
+ internal static extern unsafe int GetSortKey(SafeSortHandle sortHandle, string str, int strLength, byte* sortKey, int sortKeyLength, CompareOptions options);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_CompareStringOrdinalIgnoreCase")]
- internal unsafe static extern int CompareStringOrdinalIgnoreCase(char* lpStr1, int cwStr1Len, char* lpStr2, int cwStr2Len);
+ internal static extern unsafe int CompareStringOrdinalIgnoreCase(char* lpStr1, int cwStr1Len, char* lpStr2, int cwStr2Len);
[DllImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetSortVersion")]
internal static extern int GetSortVersion(SafeSortHandle sortHandle);
diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Idna.cs b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Idna.cs
index af2373946..89b6c3ceb 100644
--- a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Idna.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Idna.cs
@@ -13,9 +13,9 @@ internal static partial class Interop
internal const int UseStd3AsciiRules = 0x2;
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_ToAscii")]
- internal static unsafe extern int ToAscii(uint flags, char* src, int srcLen, char* dstBuffer, int dstBufferCapacity);
+ internal static extern unsafe int ToAscii(uint flags, char* src, int srcLen, char* dstBuffer, int dstBufferCapacity);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_ToUnicode")]
- internal static unsafe extern int ToUnicode(uint flags, char* src, int srcLen, char* dstBuffer, int dstBufferCapacity);
+ internal static extern unsafe int ToUnicode(uint flags, char* src, int srcLen, char* dstBuffer, int dstBufferCapacity);
}
}
diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Locale.cs b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Locale.cs
index 09527f0a0..b6f5fbec1 100644
--- a/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Locale.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Unix/System.Globalization.Native/Interop.Locale.cs
@@ -12,29 +12,29 @@ internal static partial class Interop
{
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetLocaleName")]
[return: MarshalAs(UnmanagedType.Bool)]
- internal unsafe static extern bool GetLocaleName(string localeName, [Out] StringBuilder value, int valueLength);
+ internal static extern unsafe bool GetLocaleName(string localeName, [Out] StringBuilder value, int valueLength);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetLocaleInfoString")]
[return: MarshalAs(UnmanagedType.Bool)]
- internal unsafe static extern bool GetLocaleInfoString(string localeName, uint localeStringData, [Out] StringBuilder value, int valueLength);
+ internal static extern unsafe bool GetLocaleInfoString(string localeName, uint localeStringData, [Out] StringBuilder value, int valueLength);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetDefaultLocaleName")]
[return: MarshalAs(UnmanagedType.Bool)]
- internal unsafe static extern bool GetDefaultLocaleName([Out] StringBuilder value, int valueLength);
+ internal static extern unsafe bool GetDefaultLocaleName([Out] StringBuilder value, int valueLength);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetLocaleTimeFormat")]
[return: MarshalAs(UnmanagedType.Bool)]
- internal unsafe static extern bool GetLocaleTimeFormat(string localeName, bool shortFormat, [Out] StringBuilder value, int valueLength);
+ internal static extern unsafe bool GetLocaleTimeFormat(string localeName, bool shortFormat, [Out] StringBuilder value, int valueLength);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetLocaleInfoInt")]
[return: MarshalAs(UnmanagedType.Bool)]
- internal unsafe static extern bool GetLocaleInfoInt(string localeName, uint localeNumberData, ref int value);
+ internal static extern unsafe bool GetLocaleInfoInt(string localeName, uint localeNumberData, ref int value);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetLocaleInfoGroupingSizes")]
[return: MarshalAs(UnmanagedType.Bool)]
- internal unsafe static extern bool GetLocaleInfoGroupingSizes(string localeName, uint localeGroupingData, ref int primaryGroupSize, ref int secondaryGroupSize);
+ internal static extern unsafe bool GetLocaleInfoGroupingSizes(string localeName, uint localeGroupingData, ref int primaryGroupSize, ref int secondaryGroupSize);
[DllImport(Libraries.GlobalizationNative, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetLocales")]
- internal unsafe static extern int GetLocales([Out] Char[] value, int valueLength);
+ internal static extern unsafe int GetLocales([Out] char[] value, int valueLength);
}
}
diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.GetRandomBytes.cs b/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.GetRandomBytes.cs
index 62156e8d8..e911b1358 100644
--- a/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.GetRandomBytes.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.GetRandomBytes.cs
@@ -11,7 +11,7 @@ internal partial class Interop
internal unsafe partial class Sys
{
[DllImport(Interop.Libraries.SystemNative, EntryPoint = "SystemNative_GetNonCryptographicallySecureRandomBytes")]
- internal static unsafe extern void GetNonCryptographicallySecureRandomBytes(byte* buffer, int length);
+ internal static extern unsafe void GetNonCryptographicallySecureRandomBytes(byte* buffer, int length);
}
internal static unsafe void GetRandomBytes(byte* buffer, int length)
diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.Read.cs b/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.Read.cs
index 812ae348d..1be5e789c 100644
--- a/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.Read.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.Read.cs
@@ -20,6 +20,6 @@ internal static partial class Interop
/// Note - on fail. the position of the stream may change depending on the platform; consult man 2 read for more info
/// </returns>
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Read", SetLastError = true)]
- internal static unsafe extern int Read(SafeFileHandle fd, byte* buffer, int count);
+ internal static extern unsafe int Read(SafeFileHandle fd, byte* buffer, int count);
}
}
diff --git a/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.Write.cs b/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.Write.cs
index c14fc2626..0636615a8 100644
--- a/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.Write.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Unix/System.Native/Interop.Write.cs
@@ -19,9 +19,9 @@ internal static partial class Interop
/// Returns the number of bytes written on success; otherwise, returns -1 and sets errno
/// </returns>
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Write", SetLastError = true)]
- internal static unsafe extern int Write(SafeFileHandle fd, byte* buffer, int bufferSize);
+ internal static extern unsafe int Write(SafeFileHandle fd, byte* buffer, int bufferSize);
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Write", SetLastError = true)]
- internal static unsafe extern int Write(int fd, byte* buffer, int bufferSize);
+ internal static extern unsafe int Write(int fd, byte* buffer, int bufferSize);
}
}
diff --git a/src/Common/src/Interop/Windows/mincore/Interop.RegCloseKey.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegCloseKey.cs
index 2b55f9781..375376d52 100644
--- a/src/Common/src/Interop/Windows/mincore/Interop.RegCloseKey.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegCloseKey.cs
@@ -2,15 +2,14 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.InteropServices;
internal partial class Interop
{
- internal partial class mincore
+ internal partial class Advapi32
{
- [DllImport(Libraries.Registry_L1)]
- internal extern static int RegCloseKey(IntPtr hKey);
+ [DllImport(Libraries.Advapi32)]
+ internal static extern int RegCloseKey(IntPtr hKey);
}
}
diff --git a/src/Common/src/Interop/Windows/mincore/Interop.RegCreateKeyEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegCreateKeyEx.cs
index 8f9d3eed3..e5219064b 100644
--- a/src/Common/src/Interop/Windows/mincore/Interop.RegCreateKeyEx.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegCreateKeyEx.cs
@@ -8,19 +8,19 @@ using System.Runtime.InteropServices;
internal partial class Interop
{
- internal partial class mincore
+ internal partial class Advapi32
{
// Note: RegCreateKeyEx won't set the last error on failure - it returns
// an error code if it fails.
- [DllImport(Libraries.Registry_L1, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegCreateKeyExW")]
+ [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegCreateKeyExW")]
internal static extern int RegCreateKeyEx(
SafeRegistryHandle hKey,
- String lpSubKey,
+ string lpSubKey,
int Reserved,
- String lpClass,
+ string lpClass,
int dwOptions,
int samDesired,
- ref Kernel32.SECURITY_ATTRIBUTES secAttrs,
+ ref Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs,
out SafeRegistryHandle hkResult,
out int lpdwDisposition);
}
diff --git a/src/Common/src/Interop/Windows/advapi32/Interop.RegSetValueEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegDeleteKeyEx.cs
index 59e038d95..4429515cd 100644
--- a/src/Common/src/Interop/Windows/advapi32/Interop.RegSetValueEx.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegDeleteKeyEx.cs
@@ -2,16 +2,15 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.InteropServices;
-using Microsoft.Win32;
-using Microsoft.Win32.SafeHandles;
internal partial class Interop
{
internal partial class Advapi32
{
- [DllImport("advapi32.dll", CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")]
- internal static extern int RegSetValueEx(SafeRegistryHandle hKey, string lpValueName, int Reserved, RegistryValueKind dwType, string lpData, int cbData);
+ [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegDeleteKeyExW")]
+ internal static extern int RegDeleteKeyEx(SafeRegistryHandle hKey, string lpSubKey, int samDesired, int Reserved);
}
}
diff --git a/src/Common/src/Interop/Windows/advapi32/Interop.RegDeleteValue.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegDeleteValue.cs
index 91369a01f..b8044bc79 100644
--- a/src/Common/src/Interop/Windows/advapi32/Interop.RegDeleteValue.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegDeleteValue.cs
@@ -2,15 +2,15 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.InteropServices;
-using Microsoft.Win32.SafeHandles;
internal partial class Interop
{
internal partial class Advapi32
{
- [DllImport("advapi32.dll", CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegDeleteValueW")]
- internal static extern int RegDeleteValue(SafeRegistryHandle hKey, String lpValueName);
+ [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegDeleteValueW")]
+ internal static extern int RegDeleteValue(SafeRegistryHandle hKey, string lpValueName);
}
}
diff --git a/src/Common/src/Interop/Windows/mincore/Interop.RegEnumKeyEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegEnumKeyEx.cs
index 6196c98b0..bedf28277 100644
--- a/src/Common/src/Interop/Windows/mincore/Interop.RegEnumKeyEx.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegEnumKeyEx.cs
@@ -9,13 +9,13 @@ using System.Text;
internal partial class Interop
{
- internal partial class mincore
+ internal partial class Advapi32
{
- [DllImport(Libraries.Registry_L1, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegEnumKeyExW")]
+ [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegEnumKeyExW")]
internal static extern unsafe int RegEnumKeyEx(
SafeRegistryHandle hKey,
int dwIndex,
- char* lpName,
+ char[] lpName,
ref int lpcbName,
int[] lpReserved,
[Out]StringBuilder lpClass,
diff --git a/src/Common/src/Interop/Windows/mincore/Interop.RegEnumValue.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegEnumValue.cs
index 6d88c517c..e02ba98fe 100644
--- a/src/Common/src/Interop/Windows/mincore/Interop.RegEnumValue.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegEnumValue.cs
@@ -8,13 +8,13 @@ using System.Runtime.InteropServices;
internal partial class Interop
{
- internal partial class mincore
+ internal partial class Advapi32
{
- [DllImport(Libraries.Registry_L1, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegEnumValueW")]
+ [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegEnumValueW")]
internal static extern unsafe int RegEnumValue(
SafeRegistryHandle hKey,
int dwIndex,
- char* lpValueName,
+ char[] lpValueName,
ref int lpcbValueName,
IntPtr lpReserved_MustBeZero,
int[] lpType,
diff --git a/src/Common/src/Interop/Windows/mincore/Interop.RegFlushKey.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegFlushKey.cs
index 25f8ff240..8f72798f8 100644
--- a/src/Common/src/Interop/Windows/mincore/Interop.RegFlushKey.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegFlushKey.cs
@@ -7,9 +7,9 @@ using System.Runtime.InteropServices;
internal partial class Interop
{
- internal partial class mincore
+ internal partial class Advapi32
{
- [DllImport(Libraries.Registry_L1)]
+ [DllImport(Libraries.Advapi32)]
internal static extern int RegFlushKey(SafeRegistryHandle hKey);
}
}
diff --git a/src/Common/src/Interop/Windows/mincore/Interop.RegOpenKeyEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegOpenKeyEx.cs
index 9e8d9382f..86b6bcae2 100644
--- a/src/Common/src/Interop/Windows/mincore/Interop.RegOpenKeyEx.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegOpenKeyEx.cs
@@ -8,9 +8,9 @@ using System.Runtime.InteropServices;
internal partial class Interop
{
- internal partial class mincore
+ internal partial class Advapi32
{
- [DllImport(Libraries.Registry_L1, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegOpenKeyExW")]
+ [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegOpenKeyExW")]
internal static extern int RegOpenKeyEx(
SafeRegistryHandle hKey,
string lpSubKey,
@@ -19,7 +19,7 @@ internal partial class Interop
out SafeRegistryHandle hkResult);
- [DllImport(Libraries.Registry_L1, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegOpenKeyExW")]
+ [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegOpenKeyExW")]
internal static extern int RegOpenKeyEx(
IntPtr hKey,
string lpSubKey,
diff --git a/src/Common/src/Interop/Windows/mincore/Interop.RegQueryInfoKey.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegQueryInfoKey.cs
index 19a688440..2df209288 100644
--- a/src/Common/src/Interop/Windows/mincore/Interop.RegQueryInfoKey.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegQueryInfoKey.cs
@@ -9,9 +9,9 @@ using System.Text;
internal partial class Interop
{
- internal partial class mincore
+ internal partial class Advapi32
{
- [DllImport(Libraries.Registry_L1, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryInfoKeyW")]
+ [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryInfoKeyW")]
internal static extern int RegQueryInfoKey(
SafeRegistryHandle hKey,
[Out]StringBuilder lpClass,
diff --git a/src/Common/src/Interop/Windows/mincore/Interop.RegQueryValueEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegQueryValueEx.cs
index 10e5c430f..c6a879817 100644
--- a/src/Common/src/Interop/Windows/mincore/Interop.RegQueryValueEx.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegQueryValueEx.cs
@@ -9,9 +9,9 @@ using System.Text;
internal partial class Interop
{
- internal partial class mincore
+ internal partial class Advapi32
{
- [DllImport(Libraries.Registry_L1, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")]
+ [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")]
internal static extern int RegQueryValueEx(
SafeRegistryHandle hKey,
string lpValueName,
@@ -20,7 +20,7 @@ internal partial class Interop
[Out] byte[] lpData,
ref int lpcbData);
- [DllImport(Libraries.Registry_L1, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")]
+ [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")]
internal static extern int RegQueryValueEx(
SafeRegistryHandle hKey,
string lpValueName,
@@ -29,28 +29,28 @@ internal partial class Interop
ref int lpData,
ref int lpcbData);
- [DllImport(Libraries.Registry_L1, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")]
+ [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")]
internal static extern int RegQueryValueEx(
SafeRegistryHandle hKey,
- String lpValueName,
+ string lpValueName,
int[] lpReserved,
ref int lpType,
ref long lpData,
ref int lpcbData);
- [DllImport(Libraries.Registry_L1, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")]
+ [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")]
internal static extern int RegQueryValueEx(
SafeRegistryHandle hKey,
- String lpValueName,
+ string lpValueName,
int[] lpReserved,
ref int lpType,
[Out] char[] lpData,
ref int lpcbData);
- [DllImport(Libraries.Registry_L1, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")]
+ [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegQueryValueExW")]
internal static extern int RegQueryValueEx(
SafeRegistryHandle hKey,
- String lpValueName,
+ string lpValueName,
int[] lpReserved,
ref int lpType,
[Out]StringBuilder lpData,
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegSetValueEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegSetValueEx.cs
new file mode 100644
index 000000000..d46f84809
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegSetValueEx.cs
@@ -0,0 +1,59 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Win32;
+using Microsoft.Win32.SafeHandles;
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Advapi32
+ {
+ [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")]
+ internal static extern int RegSetValueEx(
+ SafeRegistryHandle hKey,
+ string lpValueName,
+ int Reserved,
+ RegistryValueKind dwType,
+ byte[] lpData,
+ int cbData);
+
+ [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")]
+ internal static extern int RegSetValueEx(
+ SafeRegistryHandle hKey,
+ string lpValueName,
+ int Reserved,
+ RegistryValueKind dwType,
+ char[] lpData,
+ int cbData);
+
+ [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")]
+ internal static extern int RegSetValueEx(
+ SafeRegistryHandle hKey,
+ string lpValueName,
+ int Reserved,
+ RegistryValueKind dwType,
+ ref int lpData,
+ int cbData);
+
+ [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")]
+ internal static extern int RegSetValueEx(
+ SafeRegistryHandle hKey,
+ string lpValueName,
+ int Reserved,
+ RegistryValueKind dwType,
+ ref long lpData,
+ int cbData);
+
+ [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW")]
+ internal static extern int RegSetValueEx(
+ SafeRegistryHandle hKey,
+ string lpValueName,
+ int Reserved,
+ RegistryValueKind dwType,
+ string lpData,
+ int cbData);
+ }
+}
diff --git a/src/Common/src/Interop/Windows/mincore/Interop.RegistryOptions.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegistryConstants.cs
index 4c95a8b1f..bdb89702f 100644
--- a/src/Common/src/Interop/Windows/mincore/Interop.RegistryOptions.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Advapi32/Interop.RegistryConstants.cs
@@ -4,23 +4,23 @@
internal partial class Interop
{
- internal partial class mincore
+ internal partial class Advapi32
{
- internal partial class RegistryOptions
+ internal static class RegistryOptions
{
internal const int REG_OPTION_NON_VOLATILE = 0x0000; // (default) keys are persisted beyond reboot/unload
internal const int REG_OPTION_VOLATILE = 0x0001; // All keys created by the function are volatile
internal const int REG_OPTION_CREATE_LINK = 0x0002; // They key is a symbolic link
- internal const int REG_OPTION_BACKUP_RESTORE = 0x0004; // Use SE_BACKUP_NAME process special privileges
+ internal const int REG_OPTION_BACKUP_RESTORE = 0x0004; // Use SE_BACKUP_NAME process special privileges
}
- internal partial class RegistryView
+ internal static class RegistryView
{
internal const int KEY_WOW64_64KEY = 0x0100;
internal const int KEY_WOW64_32KEY = 0x0200;
}
- internal partial class RegistryOperations
+ internal static class RegistryOperations
{
internal const int KEY_QUERY_VALUE = 0x0001;
internal const int KEY_SET_VALUE = 0x0002;
@@ -47,7 +47,7 @@ internal partial class Interop
internal const int STANDARD_RIGHTS_WRITE = READ_CONTROL;
}
- internal partial class RegistryValues
+ internal static class RegistryValues
{
internal const int REG_NONE = 0; // No value type
internal const int REG_SZ = 1; // Unicode nul terminated string
@@ -62,4 +62,4 @@ internal partial class Interop
internal const int REG_QWORD = 11; // 64-bit number
}
}
-}
+} \ No newline at end of file
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.BCryptGenRandom.GetRandomBytes.cs b/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.BCryptGenRandom.GetRandomBytes.cs
new file mode 100644
index 000000000..4d75163d4
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.BCryptGenRandom.GetRandomBytes.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal static unsafe void GetRandomBytes(byte* buffer, int length)
+ {
+ Debug.Assert(buffer != null);
+ Debug.Assert(length >= 0);
+
+ BCrypt.NTSTATUS status = BCrypt.BCryptGenRandom(IntPtr.Zero, buffer, length, BCrypt.BCRYPT_USE_SYSTEM_PREFERRED_RNG);
+ if (status != BCrypt.NTSTATUS.STATUS_SUCCESS)
+ {
+ if (status == BCrypt.NTSTATUS.STATUS_NO_MEMORY)
+ {
+ throw new OutOfMemoryException();
+ }
+ else
+ {
+ throw new InvalidOperationException();
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.BCryptGenRandom.cs b/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.BCryptGenRandom.cs
index bc357125b..9d072a3b0 100644
--- a/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.BCryptGenRandom.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.BCryptGenRandom.cs
@@ -10,35 +10,9 @@ internal partial class Interop
{
internal partial class BCrypt
{
- internal static unsafe int BCryptGenRandom(byte* pbBuffer, int count)
- {
- Debug.Assert(pbBuffer != null);
- Debug.Assert(count >= 0);
-
- return BCryptGenRandom(IntPtr.Zero, pbBuffer, count, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
- }
-
- private const int BCRYPT_USE_SYSTEM_PREFERRED_RNG = 0x00000002;
- internal const int STATUS_SUCCESS = 0x0;
- internal const int STATUS_NO_MEMORY = unchecked((int)0xC0000017);
+ internal const int BCRYPT_USE_SYSTEM_PREFERRED_RNG = 0x00000002;
[DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)]
- private static unsafe extern int BCryptGenRandom(IntPtr hAlgorithm, byte* pbBuffer, int cbBuffer, int dwFlags);
- }
-
- internal static unsafe void GetRandomBytes(byte* buffer, int length)
- {
- int status = BCrypt.BCryptGenRandom(buffer, length);
- if (status != BCrypt.STATUS_SUCCESS)
- {
- if (status == BCrypt.STATUS_NO_MEMORY)
- {
- throw new OutOfMemoryException();
- }
- else
- {
- throw new InvalidOperationException();
- }
- }
+ internal static extern unsafe NTSTATUS BCryptGenRandom(IntPtr hAlgorithm, byte* pbBuffer, int cbBuffer, int dwFlags);
}
}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.NTSTATUS.cs b/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.NTSTATUS.cs
new file mode 100644
index 000000000..29aaa2904
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/BCrypt/Interop.NTSTATUS.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+internal partial class Interop
+{
+ internal partial class BCrypt
+ {
+ internal enum NTSTATUS : uint
+ {
+ STATUS_SUCCESS = 0x0,
+ STATUS_NOT_FOUND = 0xc0000225,
+ STATUS_INVALID_PARAMETER = 0xc000000d,
+ STATUS_NO_MEMORY = 0xc0000017,
+ STATUS_AUTH_TAG_MISMATCH = 0xc000a002,
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Interop.Libraries.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Interop.Libraries.cs
index 45d910bfc..398d18a2a 100644
--- a/src/System.Private.CoreLib/shared/Interop/Windows/Interop.Libraries.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Interop.Libraries.cs
@@ -6,11 +6,13 @@ internal static partial class Interop
{
internal static partial class Libraries
{
+ internal const string Advapi32 = "advapi32.dll";
internal const string BCrypt = "BCrypt.dll";
internal const string Crypt32 = "crypt32.dll";
internal const string Kernel32 = "kernel32.dll";
internal const string Ole32 = "ole32.dll";
internal const string OleAut32 = "oleaut32.dll";
internal const string User32 = "user32.dll";
+ internal const string NtDll = "ntdll.dll";
}
}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CloseHandle.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CloseHandle.cs
index 96ed922a8..ff41f939f 100644
--- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CloseHandle.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.CloseHandle.cs
@@ -10,7 +10,6 @@ internal partial class Interop
internal partial class Kernel32
{
[DllImport(Libraries.Kernel32, SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CloseHandle(IntPtr handle);
}
}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Constants.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Constants.cs
new file mode 100644
index 000000000..b13cdfd03
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Constants.cs
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+internal static partial class Interop
+{
+ internal static partial class Kernel32
+ {
+ internal const int MAXIMUM_ALLOWED = 0x02000000;
+ internal const int SYNCHRONIZE = 0x00100000;
+ internal const int MUTEX_MODIFY_STATE = 0x00000001;
+ internal const int SEMAPHORE_MODIFY_STATE = 0x00000002;
+ internal const int EVENT_MODIFY_STATE = 0x00000002;
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.EventWaitHandle.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.EventWaitHandle.cs
new file mode 100644
index 000000000..b562e527e
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.EventWaitHandle.cs
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Win32.SafeHandles;
+using System;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+ internal static partial class Kernel32
+ {
+ internal const uint CREATE_EVENT_INITIAL_SET = 0x2;
+ internal const uint CREATE_EVENT_MANUAL_RESET = 0x1;
+
+ [DllImport(Interop.Libraries.Kernel32, SetLastError = true)]
+ internal static extern bool SetEvent(SafeWaitHandle handle);
+
+ [DllImport(Interop.Libraries.Kernel32, SetLastError = true)]
+ internal static extern bool ResetEvent(SafeWaitHandle handle);
+
+ [DllImport(Interop.Libraries.Kernel32, EntryPoint = "CreateEventExW", SetLastError = true, CharSet = CharSet.Unicode)]
+ internal static extern SafeWaitHandle CreateEventEx(IntPtr lpSecurityAttributes, string name, uint flags, uint desiredAccess);
+
+ [DllImport(Interop.Libraries.Kernel32, EntryPoint = "OpenEventW", SetLastError = true, CharSet = CharSet.Unicode)]
+ internal static extern SafeWaitHandle OpenEvent(uint desiredAccess, bool inheritHandle, string name);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FileTypes.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FileTypes.cs
index 1d306665b..9d52f1f4f 100644
--- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FileTypes.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FileTypes.cs
@@ -8,6 +8,7 @@ internal partial class Interop
{
internal partial class FileTypes
{
+ internal const int FILE_TYPE_UNKNOWN = 0x0000;
internal const int FILE_TYPE_DISK = 0x0001;
internal const int FILE_TYPE_CHAR = 0x0002;
internal const int FILE_TYPE_PIPE = 0x0003;
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FindClose.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FindClose.cs
index 03d8c8b32..fcf9254ac 100644
--- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FindClose.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FindClose.cs
@@ -11,6 +11,6 @@ internal partial class Interop
internal partial class Kernel32
{
[DllImport(Libraries.Kernel32, SetLastError = true)]
- internal extern static bool FindClose(IntPtr hFindFile);
+ internal static extern bool FindClose(IntPtr hFindFile);
}
}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FindFirstFileEx.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FindFirstFileEx.cs
index 80b1ddd28..dcb86ec9b 100644
--- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FindFirstFileEx.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FindFirstFileEx.cs
@@ -19,7 +19,7 @@ internal partial class Interop
internal static SafeFindHandle FindFirstFile(string fileName, ref WIN32_FIND_DATA data)
{
- fileName = PathInternal.EnsureExtendedPrefixOverMaxPath(fileName);
+ fileName = PathInternal.EnsureExtendedPrefixIfNeeded(fileName);
// use FindExInfoBasic since we don't care about short name and it has better perf
return FindFirstFileExPrivate(fileName, FINDEX_INFO_LEVELS.FindExInfoBasic, ref data, FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero, 0);
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FormatMessage.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FormatMessage.cs
index 94722b6c8..3ea12d7cf 100644
--- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FormatMessage.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.FormatMessage.cs
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Text;
using System.Runtime.InteropServices;
internal partial class Interop
@@ -14,99 +13,76 @@ internal partial class Interop
private const int FORMAT_MESSAGE_FROM_HMODULE = 0x00000800;
private const int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
private const int FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000;
-
-
+ private const int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100;
private const int ERROR_INSUFFICIENT_BUFFER = 0x7A;
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, EntryPoint = "FormatMessageW", SetLastError = true, BestFitMapping = true)]
- private static extern int FormatMessage(
+ private static extern unsafe int FormatMessage(
int dwFlags,
IntPtr lpSource,
uint dwMessageId,
int dwLanguageId,
- [Out] StringBuilder lpBuffer,
+ void* lpBuffer,
int nSize,
- IntPtr[] arguments);
+ IntPtr arguments);
/// <summary>
/// Returns a string message for the specified Win32 error code.
/// </summary>
- internal static string GetMessage(int errorCode)
- {
- return GetMessage(IntPtr.Zero, errorCode);
- }
-
- internal static string GetMessage(IntPtr moduleHandle, int errorCode)
- {
- var sb = new StringBuilder(InitialBufferSize);
- do
- {
- string errorMsg;
- if (TryGetErrorMessage(moduleHandle, errorCode, sb, out errorMsg))
- {
- return errorMsg;
- }
- else
- {
- // increase the capacity of the StringBuilder.
- sb.Capacity *= BufferSizeIncreaseFactor;
- }
- }
- while (sb.Capacity < MaxAllowedBufferSize);
-
- // If you come here then a size as large as 65K is also not sufficient and so we give the generic errorMsg.
- return string.Format("Unknown error (0x{0:x})", errorCode);
- }
+ internal static string GetMessage(int errorCode) =>
+ GetMessage(errorCode, IntPtr.Zero);
- private static bool TryGetErrorMessage(IntPtr moduleHandle, int errorCode, StringBuilder sb, out string errorMsg)
+ internal static unsafe string GetMessage(int errorCode, IntPtr moduleHandle)
{
- errorMsg = "";
-
int flags = FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY;
if (moduleHandle != IntPtr.Zero)
{
flags |= FORMAT_MESSAGE_FROM_HMODULE;
}
- int result = FormatMessage(flags, moduleHandle, (uint)errorCode, 0, sb, sb.Capacity, null);
- if (result != 0)
+ // First try to format the message into the stack based buffer. Most error messages willl fit.
+ Span<char> stackBuffer = stackalloc char[256]; // arbitrary stack limit
+ fixed (char* bufferPtr = &MemoryMarshal.GetReference(stackBuffer))
{
- int i = sb.Length;
- while (i > 0)
+ int length = FormatMessage(flags, moduleHandle, unchecked((uint)errorCode), 0, bufferPtr, stackBuffer.Length, IntPtr.Zero);
+ if (length > 0)
{
- char ch = sb[i - 1];
- if (ch > 32 && ch != '.') break;
- i--;
+ return GetAndTrimString(stackBuffer.Slice(0, length));
}
- errorMsg = sb.ToString(0, i);
- }
- else if (Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
- {
- return false;
}
- else
+
+ // We got back an error. If the error indicated that there wasn't enough room to store
+ // the error message, then call FormatMessage again, but this time rather than passing in
+ // a buffer, have the method allocate one, which we then need to free.
+ if (Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
{
- errorMsg = string.Format("Unknown error (0x{0:x})", errorCode);
+ IntPtr nativeMsgPtr = default;
+ try
+ {
+ int length = FormatMessage(flags | FORMAT_MESSAGE_ALLOCATE_BUFFER, moduleHandle, unchecked((uint)errorCode), 0, &nativeMsgPtr, 0, IntPtr.Zero);
+ if (length > 0)
+ {
+ return GetAndTrimString(new Span<char>((char*)nativeMsgPtr, length));
+ }
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(nativeMsgPtr);
+ }
}
- return true;
+ // Couldn't get a message, so manufacture one.
+ return string.Format("Unknown error (0x{0:x})", errorCode);
}
- // Windows API FormatMessage lets you format a message string given an errorcode.
- // Unlike other APIs this API does not support a way to query it for the total message size.
- //
- // So the API can only be used in one of these two ways.
- // a. You pass a buffer of appropriate size and get the resource.
- // b. Windows creates a buffer and passes the address back and the onus of releasing the buffer lies on the caller.
- //
- // Since the error code is coming from the user, it is not possible to know the size in advance.
- // Unfortunately we can't use option b. since the buffer can only be freed using LocalFree and it is a private API on onecore.
- // Also, using option b is ugly for the managed code and could cause memory leak in situations where freeing is unsuccessful.
- //
- // As a result we use the following approach.
- // We initially call the API with a buffer size of 256 and then gradually increase the size in case of failure until we reach the maximum allowed limit of 65K.
- private const int InitialBufferSize = 256;
- private const int BufferSizeIncreaseFactor = 4;
- private const int MaxAllowedBufferSize = 65 * 1024;
+ private static string GetAndTrimString(Span<char> buffer)
+ {
+ int length = buffer.Length;
+ while (length > 0 && buffer[length - 1] <= 32)
+ {
+ length--; // trim off spaces and non-printable ASCII chars at the end of the resource
+ }
+ return buffer.Slice(0, length).ToString();
+ }
}
}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFileType_SafeHandle.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFileType_SafeHandle.cs
index c07a1683a..faa57cc2f 100644
--- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFileType_SafeHandle.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFileType_SafeHandle.cs
@@ -10,6 +10,6 @@ internal partial class Interop
internal partial class Kernel32
{
[DllImport(Libraries.Kernel32, SetLastError = true)]
- internal extern static int GetFileType(SafeHandle hFile);
+ internal static extern int GetFileType(SafeHandle hFile);
}
}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFullPathNameW.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFullPathNameW.cs
index 06030450c..197b0a9be 100644
--- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFullPathNameW.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetFullPathNameW.cs
@@ -13,17 +13,6 @@ internal partial class Interop
/// WARNING: This method does not implicitly handle long paths. Use GetFullPathName or PathHelper.
/// </summary>
[DllImport(Libraries.Kernel32, SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)]
-#if PROJECTN
- internal static extern unsafe uint GetFullPathNameW(string path, uint numBufferChars, char* buffer, IntPtr mustBeZero);
-
- // Works around https://devdiv.visualstudio.com/web/wi.aspx?pcguid=011b8bdf-6d56-4f87-be0d-0092136884d9&id=575202
- internal static unsafe uint GetFullPathNameW(string path, uint numBufferChars, ref char buffer, IntPtr mustBeZero)
- {
- fixed (char* pBuffer = &buffer)
- return GetFullPathNameW(path, numBufferChars, pBuffer, mustBeZero);
- }
-#else
- internal static extern uint GetFullPathNameW(string path, uint numBufferChars, ref char buffer, IntPtr mustBeZero);
-#endif
+ internal static extern uint GetFullPathNameW(ref char lpFileName, uint nBufferLength, ref char lpBuffer, IntPtr lpFilePart);
}
}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetLongPathNameW.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetLongPathNameW.cs
index 09e98d0c9..81b4d096f 100644
--- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetLongPathNameW.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetLongPathNameW.cs
@@ -13,17 +13,6 @@ internal partial class Interop
/// WARNING: This method does not implicitly handle long paths. Use GetFullPath/PathHelper.
/// </summary>
[DllImport(Libraries.Kernel32, SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)]
-#if PROJECTN
- internal static extern unsafe uint GetLongPathNameW(ref char lpszShortPath, char* lpszLongPath, uint cchBuffer);
-
- // Works around https://devdiv.visualstudio.com/web/wi.aspx?pcguid=011b8bdf-6d56-4f87-be0d-0092136884d9&id=575202
- internal static unsafe uint GetLongPathNameW(ref char lpszShortPath, ref char lpszLongPath, uint cchBuffer)
- {
- fixed (char* plpszLongPath = &lpszLongPath)
- return GetLongPathNameW(ref lpszShortPath, plpszLongPath, cchBuffer);
- }
-#else
internal static extern uint GetLongPathNameW(ref char lpszShortPath, ref char lpszLongPath, uint cchBuffer);
-#endif
}
}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetTempFileNameW.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetTempFileNameW.cs
index 36673895b..97e1d8284 100644
--- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetTempFileNameW.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetTempFileNameW.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-using System.Text;
using System.Runtime.InteropServices;
internal partial class Interop
@@ -11,6 +9,6 @@ internal partial class Interop
internal partial class Kernel32
{
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false)]
- internal static extern uint GetTempFileNameW(string tmpPath, string prefix, uint uniqueIdOrZero, [Out]StringBuilder tmpFileName);
+ internal static extern uint GetTempFileNameW(ref char lpPathName, string lpPrefixString, uint uUnique, ref char lpTempFileName);
}
}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetTempPathW.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetTempPathW.cs
index ff2783be2..7f7bb775c 100644
--- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetTempPathW.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.GetTempPathW.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.IO;
-using System.Text;
using System.Runtime.InteropServices;
internal partial class Interop
@@ -11,6 +9,6 @@ internal partial class Interop
internal partial class Kernel32
{
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, BestFitMapping = false)]
- internal static extern uint GetTempPathW(int bufferLen, [Out]StringBuilder buffer);
+ internal static extern uint GetTempPathW(int bufferLen, ref char buffer);
}
}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Globalization.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Globalization.cs
index ed0ada841..2227d59b0 100644
--- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Globalization.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Globalization.cs
@@ -18,13 +18,13 @@ internal static partial class Interop
internal const int COMPARE_STRING = 0x0001;
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
- internal extern static unsafe int LCIDToLocaleName(int locale, char *pLocaleName, int cchName, uint dwFlags);
+ internal static extern unsafe int LCIDToLocaleName(int locale, char *pLocaleName, int cchName, uint dwFlags);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
- internal extern static int LocaleNameToLCID(string lpName, uint dwFlags);
+ internal static extern int LocaleNameToLCID(string lpName, uint dwFlags);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
- internal extern static unsafe int LCMapStringEx(
+ internal static extern unsafe int LCMapStringEx(
string lpLocaleName,
uint dwMapFlags,
char* lpSrcStr,
@@ -36,7 +36,7 @@ internal static partial class Interop
IntPtr sortHandle);
[DllImport("kernel32.dll", EntryPoint = "FindNLSStringEx")]
- internal extern static unsafe int FindNLSStringEx(
+ internal static extern unsafe int FindNLSStringEx(
char* lpLocaleName,
uint dwFindNLSStringFlags,
char* lpStringSource,
@@ -49,7 +49,7 @@ internal static partial class Interop
IntPtr sortHandle);
[DllImport("kernel32.dll", EntryPoint = "CompareStringEx")]
- internal extern static unsafe int CompareStringEx(
+ internal static extern unsafe int CompareStringEx(
char* lpLocaleName,
uint dwCmpFlags,
char* lpString1,
@@ -61,7 +61,7 @@ internal static partial class Interop
IntPtr lParam);
[DllImport("kernel32.dll", EntryPoint = "CompareStringOrdinal")]
- internal extern static unsafe int CompareStringOrdinal(
+ internal static extern unsafe int CompareStringOrdinal(
char* lpString1,
int cchCount1,
char* lpString2,
@@ -69,7 +69,7 @@ internal static partial class Interop
bool bIgnoreCase);
[DllImport("kernel32.dll", EntryPoint = "FindStringOrdinal")]
- internal extern static unsafe int FindStringOrdinal(
+ internal static extern unsafe int FindStringOrdinal(
uint dwFindStringOrdinalFlags,
char* lpStringSource,
int cchSource,
@@ -78,7 +78,7 @@ internal static partial class Interop
int bIgnoreCase);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
- internal extern static unsafe bool IsNLSDefinedString(
+ internal static extern unsafe bool IsNLSDefinedString(
int Function,
uint dwFlags,
IntPtr lpVersionInformation,
@@ -94,26 +94,26 @@ internal static partial class Interop
internal static extern int GetLocaleInfoEx(string lpLocaleName, uint LCType, void* lpLCData, int cchData);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
- internal extern static bool EnumSystemLocalesEx(EnumLocalesProcEx lpLocaleEnumProcEx, uint dwFlags, void* lParam, IntPtr reserved);
+ internal static extern bool EnumSystemLocalesEx(EnumLocalesProcEx lpLocaleEnumProcEx, uint dwFlags, void* lParam, IntPtr reserved);
internal delegate BOOL EnumLocalesProcEx(char* lpLocaleString, uint dwFlags, void* lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
- internal extern static int ResolveLocaleName(string lpNameToResolve, char* lpLocaleName, int cchLocaleName);
+ internal static extern int ResolveLocaleName(string lpNameToResolve, char* lpLocaleName, int cchLocaleName);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
- internal extern static bool EnumTimeFormatsEx(EnumTimeFormatsProcEx lpTimeFmtEnumProcEx, string lpLocaleName, uint dwFlags, void* lParam);
+ internal static extern bool EnumTimeFormatsEx(EnumTimeFormatsProcEx lpTimeFmtEnumProcEx, string lpLocaleName, uint dwFlags, void* lParam);
internal delegate BOOL EnumTimeFormatsProcEx(char* lpTimeFormatString, void* lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
- internal extern static int GetCalendarInfoEx(string lpLocaleName, uint Calendar, IntPtr lpReserved, uint CalType, IntPtr lpCalData, int cchData, out int lpValue);
+ internal static extern int GetCalendarInfoEx(string lpLocaleName, uint Calendar, IntPtr lpReserved, uint CalType, IntPtr lpCalData, int cchData, out int lpValue);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
- internal extern static int GetCalendarInfoEx(string lpLocaleName, uint Calendar, IntPtr lpReserved, uint CalType, IntPtr lpCalData, int cchData, IntPtr lpValue);
+ internal static extern int GetCalendarInfoEx(string lpLocaleName, uint Calendar, IntPtr lpReserved, uint CalType, IntPtr lpCalData, int cchData, IntPtr lpValue);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
- internal extern static bool EnumCalendarInfoExEx(EnumCalendarInfoProcExEx pCalInfoEnumProcExEx, string lpLocaleName, uint Calendar, string lpReserved, uint CalType, void* lParam);
+ internal static extern bool EnumCalendarInfoExEx(EnumCalendarInfoProcExEx pCalInfoEnumProcExEx, string lpLocaleName, uint Calendar, string lpReserved, uint CalType, void* lParam);
internal delegate BOOL EnumCalendarInfoProcExEx(char* lpCalendarInfoString, uint Calendar, IntPtr lpReserved, void* lParam);
@@ -128,6 +128,6 @@ internal static partial class Interop
}
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
- internal extern static unsafe bool GetNLSVersionEx(int function, string localeName, NlsVersionInfoEx* lpVersionInformation);
+ internal static extern unsafe bool GetNLSVersionEx(int function, string localeName, NlsVersionInfoEx* lpVersionInformation);
}
}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MUI.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MUI.cs
index 6ed7aa2dc..8d97c0354 100644
--- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MUI.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MUI.cs
@@ -13,6 +13,6 @@ internal static partial class Interop
internal const uint MUI_PREFERRED_UI_LANGUAGES = 0x10;
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
- internal static extern bool GetFileMUIPath(uint flags, String filePath, [Out] StringBuilder language, ref int languageLength, [Out] StringBuilder fileMuiPath, ref int fileMuiPathLength, ref Int64 enumerator);
+ internal static extern bool GetFileMUIPath(uint flags, string filePath, [Out] StringBuilder language, ref int languageLength, [Out] StringBuilder fileMuiPath, ref int fileMuiPathLength, ref long enumerator);
}
}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MultiByteToWideChar.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MultiByteToWideChar.cs
new file mode 100644
index 000000000..158e4db3f
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.MultiByteToWideChar.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class Kernel32
+ {
+ [DllImport(Libraries.Kernel32)]
+ internal static extern unsafe int MultiByteToWideChar(
+ uint CodePage, uint dwFlags,
+ byte* lpMultiByteStr, int cbMultiByte,
+ char* lpWideCharStr, int cchWideChar);
+
+ internal const uint MB_PRECOMPOSED = 0x00000001;
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Mutex.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Mutex.cs
new file mode 100644
index 000000000..cbb306e4f
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Mutex.cs
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Win32.SafeHandles;
+using System;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+ internal static partial class Kernel32
+ {
+ internal const uint CREATE_MUTEX_INITIAL_OWNER = 0x1;
+
+ [DllImport(Interop.Libraries.Kernel32, EntryPoint = "OpenMutexW", SetLastError = true, CharSet = CharSet.Unicode)]
+ internal static extern SafeWaitHandle OpenMutex(uint desiredAccess, bool inheritHandle, string name);
+
+ [DllImport(Interop.Libraries.Kernel32, EntryPoint = "CreateMutexExW", SetLastError = true, CharSet = CharSet.Unicode)]
+ internal static extern SafeWaitHandle CreateMutexEx(IntPtr lpMutexAttributes, string name, uint flags, uint desiredAccess);
+
+ [DllImport(Interop.Libraries.Kernel32, SetLastError = true)]
+ internal static extern bool ReleaseMutex(SafeWaitHandle handle);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Semaphore.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Semaphore.cs
new file mode 100644
index 000000000..94648a707
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.Semaphore.cs
@@ -0,0 +1,22 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Win32.SafeHandles;
+using System;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+ internal static partial class Kernel32
+ {
+ [DllImport(Interop.Libraries.Kernel32, EntryPoint = "OpenSemaphoreW", SetLastError = true, CharSet = CharSet.Unicode)]
+ internal static extern SafeWaitHandle OpenSemaphore(uint desiredAccess, bool inheritHandle, string name);
+
+ [DllImport(Libraries.Kernel32, EntryPoint = "CreateSemaphoreExW", SetLastError = true, CharSet = CharSet.Unicode)]
+ internal static extern SafeWaitHandle CreateSemaphoreEx(IntPtr lpSecurityAttributes, int initialCount, int maximumCount, string name, uint flags, uint desiredAccess);
+
+ [DllImport(Interop.Libraries.Kernel32, SetLastError = true)]
+ internal static extern bool ReleaseSemaphore(SafeWaitHandle handle, int releaseCount, out int previousCount);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.TimeZone.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.TimeZone.cs
index 05f13ac8e..68d4583b5 100644
--- a/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.TimeZone.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Kernel32/Interop.TimeZone.cs
@@ -86,7 +86,7 @@ internal static partial class Interop
internal const uint TIME_ZONE_ID_INVALID = unchecked((uint)-1);
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
- internal extern static uint GetDynamicTimeZoneInformation(out TIME_DYNAMIC_ZONE_INFORMATION pTimeZoneInformation);
+ internal static extern uint GetDynamicTimeZoneInformation(out TIME_DYNAMIC_ZONE_INFORMATION pTimeZoneInformation);
[DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
internal static extern uint GetTimeZoneInformation(out TIME_ZONE_INFORMATION lpTimeZoneInformation);
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/NtDll/NtQueryInformationFile.cs b/src/System.Private.CoreLib/shared/Interop/Windows/NtDll/NtQueryInformationFile.cs
new file mode 100644
index 000000000..4ba39a74e
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/NtDll/NtQueryInformationFile.cs
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Win32.SafeHandles;
+using System;
+using System.Runtime.InteropServices;
+
+internal partial class Interop
+{
+ internal partial class NtDll
+ {
+ [DllImport(Libraries.NtDll, ExactSpelling = true)]
+ unsafe internal static extern int NtQueryInformationFile(
+ SafeFileHandle FileHandle,
+ out IO_STATUS_BLOCK IoStatusBlock,
+ void* FileInformation,
+ uint Length,
+ uint FileInformationClass);
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct IO_STATUS_BLOCK
+ {
+ IO_STATUS Status;
+ IntPtr Information;
+ }
+
+ // This isn't an actual Windows type, we have to separate it out as the size of IntPtr varies by architecture
+ // and we can't specify the size at compile time to offset the Information pointer in the status block.
+ [StructLayout(LayoutKind.Explicit)]
+ internal struct IO_STATUS
+ {
+ [FieldOffset(0)]
+ int Status;
+
+ [FieldOffset(0)]
+ IntPtr Pointer;
+ }
+
+ internal const uint FileModeInformation = 16;
+ internal const uint FILE_SYNCHRONOUS_IO_ALERT = 0x00000010;
+ internal const uint FILE_SYNCHRONOUS_IO_NONALERT = 0x00000020;
+
+ internal const int STATUS_INVALID_HANDLE = unchecked((int)0xC0000008);
+ }
+}
diff --git a/src/Common/src/Interop/Windows/mincore/Interop.CoCreateGuid.cs b/src/System.Private.CoreLib/shared/Interop/Windows/Ole32/Interop.CoCreateGuid.cs
index ac3bad582..57accbe7c 100644
--- a/src/Common/src/Interop/Windows/mincore/Interop.CoCreateGuid.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/Ole32/Interop.CoCreateGuid.cs
@@ -7,9 +7,9 @@ using System.Runtime.InteropServices;
internal static partial class Interop
{
- internal static partial class mincore
+ internal static partial class Ole32
{
- [DllImport("api-ms-win-core-com-l1-1-0.dll")]
- internal extern static int CoCreateGuid(out Guid pguid);
+ [DllImport(Interop.Libraries.Ole32)]
+ internal static extern int CoCreateGuid(out Guid guid);
}
}
diff --git a/src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysAllocStringLen.cs b/src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysAllocStringLen.cs
index 1af2b3fce..be902b0c5 100644
--- a/src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysAllocStringLen.cs
+++ b/src/System.Private.CoreLib/shared/Interop/Windows/OleAut32/Interop.SysAllocStringLen.cs
@@ -14,6 +14,6 @@ internal partial class Interop
internal static extern SafeBSTRHandle SysAllocStringLen(IntPtr src, uint len);
[DllImport(Libraries.OleAut32, CharSet = CharSet.Unicode)]
- internal static extern IntPtr SysAllocStringLen(String src, int len);
+ internal static extern IntPtr SysAllocStringLen(string src, int len);
}
}
diff --git a/src/System.Private.CoreLib/shared/Microsoft/Win32/Registry.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/Registry.cs
new file mode 100644
index 000000000..bc4ee082a
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/Registry.cs
@@ -0,0 +1,104 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics;
+
+namespace Microsoft.Win32
+{
+ /// <summary>Registry encapsulation. Contains members representing all top level system keys.</summary>
+#if REGISTRY_ASSEMBLY
+ public
+#else
+ internal
+#endif
+ static class Registry
+ {
+ /// <summary>Current User Key. This key should be used as the root for all user specific settings.</summary>
+ public static readonly RegistryKey CurrentUser = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default);
+
+ /// <summary>Local Machine key. This key should be used as the root for all machine specific settings.</summary>
+ public static readonly RegistryKey LocalMachine = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default);
+
+ /// <summary>Classes Root Key. This is the root key of class information.</summary>
+ public static readonly RegistryKey ClassesRoot = RegistryKey.OpenBaseKey(RegistryHive.ClassesRoot, RegistryView.Default);
+
+ /// <summary>Users Root Key. This is the root of users.</summary>
+ public static readonly RegistryKey Users = RegistryKey.OpenBaseKey(RegistryHive.Users, RegistryView.Default);
+
+ /// <summary>Performance Root Key. This is where dynamic performance data is stored on NT.</summary>
+ public static readonly RegistryKey PerformanceData = RegistryKey.OpenBaseKey(RegistryHive.PerformanceData, RegistryView.Default);
+
+ /// <summary>Current Config Root Key. This is where current configuration information is stored.</summary>
+ public static readonly RegistryKey CurrentConfig = RegistryKey.OpenBaseKey(RegistryHive.CurrentConfig, RegistryView.Default);
+
+ /// <summary>
+ /// Parse a keyName and returns the basekey for it.
+ /// It will also store the subkey name in the out parameter.
+ /// If the keyName is not valid, we will throw ArgumentException.
+ /// The return value shouldn't be null.
+ /// </summary>
+ private static RegistryKey GetBaseKeyFromKeyName(string keyName, out string subKeyName)
+ {
+ if (keyName == null)
+ {
+ throw new ArgumentNullException(nameof(keyName));
+ }
+
+ int i = keyName.IndexOf('\\');
+ int length = i != -1 ? i : keyName.Length;
+
+ // Determine the potential base key from the length.
+ RegistryKey baseKey = null;
+ switch (length)
+ {
+ case 10: baseKey = Users; break; // HKEY_USERS
+ case 17: baseKey = char.ToUpperInvariant(keyName[6]) == 'L' ? ClassesRoot : CurrentUser; break; // HKEY_C[L]ASSES_ROOT, otherwise HKEY_CURRENT_USER
+ case 18: baseKey = LocalMachine; break; // HKEY_LOCAL_MACHINE
+ case 19: baseKey = CurrentConfig; break; // HKEY_CURRENT_CONFIG
+ case 21: baseKey = PerformanceData; break; // HKEY_PERFORMANCE_DATA
+ }
+
+ // If a potential base key was found, see if keyName actually starts with the potential base key's name.
+ if (baseKey != null && keyName.StartsWith(baseKey.Name, StringComparison.OrdinalIgnoreCase))
+ {
+ subKeyName = (i == -1 || i == keyName.Length) ?
+ string.Empty :
+ keyName.Substring(i + 1, keyName.Length - i - 1);
+
+ return baseKey;
+ }
+
+ throw new ArgumentException(SR.Format(SR.Arg_RegInvalidKeyName, nameof(keyName)), nameof(keyName));
+ }
+
+ public static object GetValue(string keyName, string valueName, object defaultValue)
+ {
+ string subKeyName;
+ RegistryKey basekey = GetBaseKeyFromKeyName(keyName, out subKeyName);
+
+ using (RegistryKey key = basekey.OpenSubKey(subKeyName))
+ {
+ return key?.GetValue(valueName, defaultValue);
+ }
+ }
+
+ public static void SetValue(string keyName, string valueName, object value)
+ {
+ SetValue(keyName, valueName, value, RegistryValueKind.Unknown);
+ }
+
+ public static void SetValue(string keyName, string valueName, object value, RegistryValueKind valueKind)
+ {
+ string subKeyName;
+ RegistryKey basekey = GetBaseKeyFromKeyName(keyName, out subKeyName);
+
+ using (RegistryKey key = basekey.CreateSubKey(subKeyName))
+ {
+ Debug.Assert(key != null, "An exception should be thrown if failed!");
+ key.SetValue(valueName, value, valueKind);
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryHive.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryHive.cs
index 57a5de393..0f1e9541c 100644
--- a/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryHive.cs
+++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryHive.cs
@@ -21,4 +21,4 @@ namespace Microsoft.Win32
PerformanceData = unchecked((int)0x80000004),
CurrentConfig = unchecked((int)0x80000005),
}
-}
+} \ No newline at end of file
diff --git a/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryOptions.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryOptions.cs
index 90b6a3dd7..201a6df0e 100644
--- a/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryOptions.cs
+++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryOptions.cs
@@ -14,7 +14,7 @@ namespace Microsoft.Win32
#endif
enum RegistryOptions
{
- None = Interop.mincore.RegistryOptions.REG_OPTION_NON_VOLATILE, // 0x0000
- Volatile = Interop.mincore.RegistryOptions.REG_OPTION_VOLATILE, // 0x0001
+ None = Interop.Advapi32.RegistryOptions.REG_OPTION_NON_VOLATILE, // 0x0000
+ Volatile = Interop.Advapi32.RegistryOptions.REG_OPTION_VOLATILE, // 0x0001
};
}
diff --git a/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryValueKind.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryValueKind.cs
index 4cf10c8df..bc6efcc06 100644
--- a/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryValueKind.cs
+++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryValueKind.cs
@@ -11,13 +11,13 @@ namespace Microsoft.Win32
#endif
enum RegistryValueKind
{
- String = Interop.mincore.RegistryValues.REG_SZ,
- ExpandString = Interop.mincore.RegistryValues.REG_EXPAND_SZ,
- Binary = Interop.mincore.RegistryValues.REG_BINARY,
- DWord = Interop.mincore.RegistryValues.REG_DWORD,
- MultiString = Interop.mincore.RegistryValues.REG_MULTI_SZ,
- QWord = Interop.mincore.RegistryValues.REG_QWORD,
+ String = Interop.Advapi32.RegistryValues.REG_SZ,
+ ExpandString = Interop.Advapi32.RegistryValues.REG_EXPAND_SZ,
+ Binary = Interop.Advapi32.RegistryValues.REG_BINARY,
+ DWord = Interop.Advapi32.RegistryValues.REG_DWORD,
+ MultiString = Interop.Advapi32.RegistryValues.REG_MULTI_SZ,
+ QWord = Interop.Advapi32.RegistryValues.REG_QWORD,
Unknown = 0, // REG_NONE is defined as zero but BCL
None = unchecked((int)0xFFFFFFFF), // mistakenly overrode this value.
- } // Now instead of using Interop.mincore.RegistryValues.REG_NONE we use "-1".
+ } // Now instead of using Interop.Kernel32.RegistryValues.REG_NONE we use "-1".
}
diff --git a/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryValueOptions.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryValueOptions.cs
index 7d9b6c403..7d9b6c403 100644
--- a/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryValueOptions.cs
+++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryValueOptions.cs
diff --git a/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryView.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryView.cs
index 2256e2d7e..0d6b3038e 100644
--- a/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryView.cs
+++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/RegistryView.cs
@@ -14,7 +14,7 @@ namespace Microsoft.Win32
enum RegistryView
{
Default = 0, // 0x0000 operate on the default registry view
- Registry64 = Interop.mincore.RegistryView.KEY_WOW64_64KEY, // 0x0100 operate on the 64-bit registry view
- Registry32 = Interop.mincore.RegistryView.KEY_WOW64_32KEY, // 0x0200 operate on the 32-bit registry view
+ Registry64 = Interop.Advapi32.RegistryView.KEY_WOW64_64KEY, // 0x0100 operate on the 64-bit registry view
+ Registry32 = Interop.Advapi32.RegistryView.KEY_WOW64_32KEY, // 0x0200 operate on the 32-bit registry view
};
}
diff --git a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs
index b284c116b..52973f2ab 100644
--- a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs
+++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeFileHandle.Unix.cs
@@ -11,9 +11,6 @@ namespace Microsoft.Win32.SafeHandles
{
public sealed class SafeFileHandle : SafeHandleZeroOrMinusOneIsInvalid
{
- /// <summary>A handle value of -1.</summary>
- private static readonly IntPtr s_invalidHandle = new IntPtr(-1);
-
private SafeFileHandle() : this(ownsHandle: true)
{
}
@@ -21,7 +18,7 @@ namespace Microsoft.Win32.SafeHandles
private SafeFileHandle(bool ownsHandle)
: base(ownsHandle)
{
- SetHandle(s_invalidHandle);
+ SetHandle(new IntPtr(-1));
}
public SafeFileHandle(IntPtr preexistingHandle, bool ownsHandle) : this(ownsHandle)
diff --git a/src/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.Windows.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeRegistryHandle.Windows.cs
index 83814f6ec..9b668047a 100644
--- a/src/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.Windows.cs
+++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeRegistryHandle.Windows.cs
@@ -11,9 +11,9 @@ namespace Microsoft.Win32.SafeHandles
#else
internal
#endif
- sealed partial class SafeRegistryHandle : SafeHandle
+ sealed partial class SafeRegistryHandle : SafeHandleZeroOrMinusOneIsInvalid
{
protected override bool ReleaseHandle() =>
- Interop.mincore.RegCloseKey(handle) == Interop.Errors.ERROR_SUCCESS;
+ Interop.Advapi32.RegCloseKey(handle) == Interop.Errors.ERROR_SUCCESS;
}
}
diff --git a/src/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs
index 158b28683..ae35b03d5 100644
--- a/src/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs
+++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs
@@ -3,20 +3,21 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Runtime.InteropServices;
namespace Microsoft.Win32.SafeHandles
{
+#if REGISTRY_ASSEMBLY
+ public
+#else
internal
- sealed partial class SafeRegistryHandle : SafeHandle
+#endif
+ sealed partial class SafeRegistryHandle : SafeHandleZeroOrMinusOneIsInvalid
{
- internal SafeRegistryHandle() : base(IntPtr.Zero, true) { }
+ internal SafeRegistryHandle() : base(true) { }
- public SafeRegistryHandle(IntPtr preexistingHandle, bool ownsHandle) : base(IntPtr.Zero, ownsHandle)
+ public SafeRegistryHandle(IntPtr preexistingHandle, bool ownsHandle) : base(ownsHandle)
{
SetHandle(preexistingHandle);
}
-
- public override bool IsInvalid => handle == IntPtr.Zero || handle == new IntPtr(-1);
}
}
diff --git a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.Windows.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.Windows.cs
new file mode 100644
index 000000000..66f17f0af
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.Windows.cs
@@ -0,0 +1,11 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Microsoft.Win32.SafeHandles
+{
+ public sealed partial class SafeWaitHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ protected override bool ReleaseHandle() => Interop.Kernel32.CloseHandle(handle);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs
new file mode 100644
index 000000000..edb0cdfca
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace Microsoft.Win32.SafeHandles
+{
+ public sealed partial class SafeWaitHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ // Called by P/Invoke marshaler
+ private SafeWaitHandle() : base(true)
+ {
+ }
+
+ public SafeWaitHandle(IntPtr existingHandle, bool ownsHandle) : base(ownsHandle)
+ {
+ SetHandle(existingHandle);
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems b/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems
index 0b3f971b1..af1b99a30 100644
--- a/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems
+++ b/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems
@@ -20,11 +20,13 @@
</ItemDefinitionGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)Internal\IO\File.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Internal\Padding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Internal\Runtime\CompilerServices\Unsafe.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\CriticalHandleMinusOneIsInvalid.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\CriticalHandleZeroOrMinusOneIsInvalid.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeHandleMinusOneIsInvalid.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeHandleZeroOrMinusOneIsInvalid.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeWaitHandle.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Action.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\AccessViolationException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ApplicationException.cs" />
@@ -46,17 +48,24 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Buffers\ArrayPool.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Buffers\ArrayPoolEventSource.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Buffers\ConfigurableArrayPool.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)System\Buffers\IRetainable.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Buffers\IMemoryOwner.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Buffers\IPinnable.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Buffers\MemoryHandle.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)System\Buffers\OwnedMemory.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Buffers\MemoryManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Buffers\TlsOverPerCoreLockedStacksArrayPool.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Buffers\Utilities.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Buffers\Text\FormattingHelpers.CountDigits.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Byte.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Char.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\CharEnumerator.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\CLSCompliantAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\Comparer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Collections\Concurrent\ConcurrentQueue.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Collections\Concurrent\ConcurrentQueueSegment.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Collections\Concurrent\IProducerConsumerCollection.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Collections\Concurrent\IProducerConsumerCollectionDebugView.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\DictionaryEntry.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Collections\Generic\ArraySortHelper.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\Generic\Dictionary.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\Generic\ICollection.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\Generic\ICollectionDebugView.cs" />
@@ -75,7 +84,10 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\Generic\NonRandomizedStringEqualityComparer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\Generic\ValueListBuilder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\Generic\List.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Collections\CompatibleComparer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Collections\Hashtable.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\HashHelpers.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Collections\HashHelpers.SerializationInfoTable.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\ICollection.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\IComparer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\IDictionary.cs" />
@@ -83,9 +95,11 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\IEnumerable.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\IEnumerator.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\IEqualityComparer.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Collections\IHashCodeProvider.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\IList.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\IStructuralComparable.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\IStructuralEquatable.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Collections\KeyValuePairs.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\ListDictionaryInternal.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\ObjectModel\Collection.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\ObjectModel\ReadOnlyCollection.cs" />
@@ -94,6 +108,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Configuration\Assemblies\AssemblyHashAlgorithm.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Configuration\Assemblies\AssemblyVersionCompatibility.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Convert.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Convert.Base64.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\CurrentSystemTimeZone.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\DataMisalignedException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\DateTime.cs" />
@@ -101,6 +116,8 @@
<Compile Include="$(MSBuildThisFileDirectory)System\DateTimeOffset.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\DayOfWeek.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\DBNull.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Decimal.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Decimal.DecCalc.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\DefaultBinder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\CodeAnalysis\SuppressMessageAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\ConditionalAttribute.cs" />
@@ -114,6 +131,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\DebuggerStepperBoundaryAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\DebuggerTypeProxyAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\DebuggerVisualizerAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\StackFrame.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\StackTraceHiddenAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\DivideByZeroException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\DllNotFoundException.cs" />
@@ -128,6 +146,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\FlagsAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\FormatException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\FormattableString.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Gen2GcCallback.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\BidiCategory.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\Calendar.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CalendarAlgorithmType.cs" />
@@ -158,6 +177,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\HijriCalendar.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\IdnMapping.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\InternalGlobalizationHelper.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\ISOWeek.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\JapaneseCalendar.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\JapaneseLunisolarCalendar.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\JulianCalendar.cs" />
@@ -194,13 +214,14 @@
<Compile Include="$(MSBuildThisFileDirectory)System\IFormattable.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IndexOutOfRangeException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\InsufficientExecutionStackException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\InsufficientMemoryException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\InvalidCastException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\InvalidOperationException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\InvalidProgramException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\InvalidTimeZoneException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\IO\BinaryReader.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\BinaryWriter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\DirectoryNotFoundException.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)System\IO\DriveNotFoundException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\EncodingCache.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\EndOfStreamException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\Error.cs" />
@@ -218,6 +239,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\IO\PathTooLongException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\PinnedBufferMemoryStream.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\SeekOrigin.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\IO\Stream.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\StreamHelpers.CopyValidation.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\StreamReader.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\StreamWriter.cs" />
@@ -235,6 +257,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Int64.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IntPtr.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Lazy.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Marvin.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Math.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\MathF.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\MarshalByRefObject.cs" />
@@ -245,6 +268,8 @@
<Compile Include="$(MSBuildThisFileDirectory)System\MemoryExtensions.Fast.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\MethodAccessException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\MidpointRounding.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\MissingFieldException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\MissingMemberException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\MissingMethodException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\MulticastNotSupportedException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\NotFiniteNumberException.cs" />
@@ -259,6 +284,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\ObjectDisposedException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ObsoleteAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\OperationCanceledException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\OutOfMemoryException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\OverflowException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ParamArrayAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ParamsArray.cs" />
@@ -300,8 +326,19 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\ConstructorInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\CustomAttributeFormatException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\DefaultMemberAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Emit\AssemblyBuilderAccess.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Emit\FlowControl.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Emit\Label.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Emit\Opcode.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Emit\OpCodes.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Emit\OpCodeType.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Emit\OperandType.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Emit\PackingSize.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Emit\PEFileKinds.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\Emit\StackBehaviour.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\EventAttributes.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\EventInfo.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\ExceptionHandlingClause.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\ExceptionHandlingClauseOptions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\FieldAttributes.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\FieldInfo.cs" />
@@ -313,12 +350,14 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\InvalidFilterCriteriaException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\IReflect.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\IReflectableType.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\LocalVariableInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\ManifestResourceInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\MemberFilter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\MemberInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\MemberTypes.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\MethodAttributes.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\MethodBase.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Reflection\MethodBody.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\MethodImplAttributes.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\MethodInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\MethodInfo.Internal.cs" />
@@ -358,11 +397,14 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Reflection\TypeInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ResolveEventArgs.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ResolveEventHandler.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Resources\FastResourceComparer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Resources\IResourceReader.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Resources\MissingManifestResourceException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Resources\MissingSatelliteAssemblyException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Resources\NeutralResourcesLanguageAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Resources\ResourceFallbackManager.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Resources\ResourceReader.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Resources\ResourceSet.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Resources\ResourceTypeCode.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Resources\RuntimeResourceSet.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Resources\SatelliteContractVersionAttribute.cs" />
@@ -371,6 +413,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\AsyncMethodBuilderAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\AsyncStateMachineAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\AsyncValueTaskMethodBuilder.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\CallerArgumentExpressionAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\CallerFilePathAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\CallerLineNumberAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\CallerMemberNameAttribute.cs" />
@@ -391,6 +434,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\FixedBufferAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\FormattableStringFactory.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\IAsyncStateMachine.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\ICastable.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\IndexerNameAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\INotifyCompletion.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\InternalsVisibleToAttribute.cs" />
@@ -414,6 +458,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\StringFreezingAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\StrongBox.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\SuppressIldasmAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\TaskAwaiter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\TupleElementNamesAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\TypeForwardedFromAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\TypeForwardedToAttribute.cs" />
@@ -422,6 +467,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\YieldAwaitable.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\ConstrainedExecution\Cer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\ConstrainedExecution\Consistency.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\ConstrainedExecution\CriticalFinalizerObject.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\ConstrainedExecution\ReliabilityContractAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\ExceptionServices\ExceptionNotification.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\ExceptionServices\HandleProcessCorruptedStateExceptionsAttribute.cs" />
@@ -443,6 +489,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\MarshalDirectiveException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\MemoryMarshal.Fast.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\MemoryMarshal.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\NativeCallableAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\OptionalAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\OutAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\PreserveSigAttribute.cs" />
@@ -451,6 +498,14 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\UnmanagedFunctionPointerAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\UnmanagedType.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\VarEnum.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Vector64.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Vector64DebugView.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Vector128.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Vector128DebugView.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Vector256.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Vector256DebugView.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Enums.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Remoting\ObjectHandle.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Serialization\IDeserializationCallback.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Serialization\IFormatterConverter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Serialization\IObjectReference.cs" />
@@ -463,6 +518,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Serialization\OptionalFieldAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Serialization\SafeSerializationEventArgs.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Serialization\SerializationException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Serialization\SerializationInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Serialization\SerializationInfoEnumerator.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Serialization\StreamingContext.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Versioning\NonVersionableAttribute.cs" />
@@ -491,16 +547,19 @@
<Compile Include="$(MSBuildThisFileDirectory)System\SpanHelpers.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SpanHelpers.BinarySearch.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SpanHelpers.Byte.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\SpanHelpers.Char.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SpanHelpers.T.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\String.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\String.Comparison.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\String.Manipulation.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\String.Searching.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)System\StringSpanHelpers.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\StackOverflowException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\StringComparer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\StringComparison.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\StringSplitOptions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SystemException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\ASCIIEncoding.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Text\StringBuilderCache.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\Decoder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\DecoderNLS.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\DecoderBestFitFallback.cs" />
@@ -520,6 +579,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Text\Latin1Encoding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\NormalizationForm.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\StringBuilder.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Text\StringBuilder.Debug.cs" Condition="'$(Configuration)' == 'Debug'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\UnicodeEncoding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\UTF32Encoding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Text\UTF7Encoding.cs" />
@@ -531,19 +591,29 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ApartmentState.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\AsyncLocal.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\AutoResetEvent.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\CancellationToken.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\DeferredDisposableLifetime.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\EventResetMode.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\EventWaitHandle.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ExecutionContext.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\LazyInitializer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\LazyThreadSafetyMode.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\LockRecursionException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ManualResetEvent.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\ManualResetEventSlim.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\Mutex.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\NativeOverlapped.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ParameterizedThreadStart.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ReaderWriterLockSlim.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\Semaphore.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SemaphoreFullException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\SemaphoreSlim.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SendOrPostCallback.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\SpinLock.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SpinWait.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SynchronizationLockException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\ThreadLocal.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\ConcurrentExclusiveSchedulerPair.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\TaskCanceledException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\TaskCompletionSource.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\TaskExtensions.cs" />
@@ -552,6 +622,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\ValueTask.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\Sources\IValueTaskSource.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ThreadAbortException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\ThreadInterruptedException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ThreadPriority.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ThreadStart.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ThreadStartException.cs" />
@@ -663,11 +734,12 @@
</ItemGroup>
<ItemGroup Condition="$(TargetsWindows)">
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\BCrypt\Interop.BCryptGenRandom.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\BCrypt\Interop.BCryptGenRandom.GetRandomBytes.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\BCrypt\Interop.NTSTATUS.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Crypt32\Interop.CryptProtectMemory.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Interop.BOOL.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Interop.Libraries.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.CancelIoEx.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.CloseHandle.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FileAttributes.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FILE_INFO_BY_HANDLE_CLASS.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FileTypes.cs" />
@@ -687,6 +759,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.Globalization.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.LockFile.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.MAX_PATH.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.MultiByteToWideChar.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.OutputDebugString.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.ReadFile_SafeHandle_IntPtr.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.ReadFile_SafeHandle_NativeOverlapped.cs" />
@@ -696,12 +769,13 @@
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.SetEnvironmentVariable.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.SetThreadErrorMode.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.SetFilePointerEx.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.TimeZone.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.WideCharToMultiByte.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.WriteFile_SafeHandle_IntPtr.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.WriteFile_SafeHandle_NativeOverlapped.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Normaliz\Interop.Idna.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Normaliz\Interop.Normalization.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
- <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.TimeZone.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Ole32\Interop.CoCreateGuid.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\OleAut32\Interop.SysAllocStringLen.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\OleAut32\Interop.SysFreeString.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\OleAut32\Interop.SysStringLen.cs" />
@@ -709,6 +783,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeFileHandle.Windows.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeFindHandle.Windows.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CalendarData.Windows.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CompareInfo.Windows.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CultureData.Windows.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\HijriCalendar.Win32.cs" Condition="'$(EnableWinRT)' != 'true' and '$(EnableDummyGlobalizationImplementation)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\HijriCalendar.WinRT.cs" Condition="'$(EnableWinRT)' == 'true'" />
@@ -717,6 +792,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\JapaneseCalendar.WinRT.cs" Condition="'$(EnableWinRT)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\Normalization.Windows.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\TextInfo.Windows.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Guid.Windows.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStream.Windows.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStreamCompletionSource.Win32.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\Path.Windows.cs" />
@@ -727,17 +803,39 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Security\SecureString.Windows.cs" />
</ItemGroup>
<ItemGroup Condition="$(TargetsWindows) and '$(EnableWinRT)' != 'true'">
- <Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStream.Win32.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)System\TimeZoneInfo.Win32.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeLibraryHandle.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.LoadLibraryEx.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FreeLibrary.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.RegCloseKey.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.RegCreateKeyEx.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.RegDeleteKeyEx.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.RegDeleteValue.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.RegEnumKeyEx.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.RegEnumValue.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.RegFlushKey.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.RegistryConstants.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.RegOpenKeyEx.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.RegQueryInfoKey.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.RegQueryValueEx.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Advapi32\Interop.RegSetValueEx.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\Registry.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\RegistryHive.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\RegistryOptions.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\RegistryValueKind.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\RegistryValueOptions.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\RegistryView.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeRegistryHandle.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeRegistryHandle.Windows.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Security\AccessControl\RegistryRights.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.CreateFile.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FreeLibrary.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.LoadLibraryEx.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.MUI.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.TimeZone.Registry.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\NtDll\NtQueryInformationFile.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\User32\Interop.Constants.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\User32\Interop.SendMessageTimeout.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\User32\Interop.LoadString.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\User32\Interop.SendMessageTimeout.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeLibraryHandle.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStream.Win32.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\TimeZoneInfo.Win32.cs" />
</ItemGroup>
<ItemGroup Condition="$(TargetsWindows) and '$(EnableWinRT)' == 'true'">
<Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStream.WinRT.cs" />
@@ -745,9 +843,18 @@
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.CREATEFILE2_EXTENDED_PARAMETERS.cs" />
</ItemGroup>
<ItemGroup Condition="$(TargetsWindows) or '$(FeaturePal)'=='true'">
+ <Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeWaitHandle.Windows.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.CloseHandle.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.Constants.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Interop.Errors.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.FormatMessage.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.Mutex.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.Semaphore.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Interop\Windows\Kernel32\Interop.EventWaitHandle.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\Win32Marshal.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\Mutex.Windows.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\Semaphore.Windows.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\EventWaitHandle.Windows.cs" />
</ItemGroup>
<ItemGroup Condition="$(TargetsUnix)">
<Compile Include="$(MSBuildThisFileDirectory)Interop\Unix\Interop.Errors.cs" />
@@ -789,6 +896,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeFileHandle.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Debug.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CalendarData.Unix.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CompareInfo.Unix.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CultureData.Unix.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\HijriCalendar.Unix.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\IdnMapping.Unix.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
@@ -796,6 +904,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\LocaleData.Unix.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\Normalization.Unix.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\TextInfo.Unix.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Guid.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStream.OSX.cs" Condition="'$(TargetsOSX)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStream.Linux.cs" Condition="'$(TargetsOSX)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\FileStream.Unix.cs" />
@@ -804,4 +913,52 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Security\SecureString.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\TimeZoneInfo.Unix.cs" />
</ItemGroup>
+ <ItemGroup Condition="'$(FeatureHardwareIntrinsics)' == 'true' AND ('$(Platform)' == 'x64' OR '$(Platform)' == 'x86')">
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Aes.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx2.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Bmi1.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Bmi2.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Fma.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Lzcnt.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Pclmulqdq.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Popcnt.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Sse.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Sse2.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Sse3.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Sse41.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Sse42.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Ssse3.cs" />
+ </ItemGroup>
+ <ItemGroup Condition="'$(FeatureHardwareIntrinsics)' != 'true' OR ('$(Platform)' != 'x64' AND '$(Platform)' != 'x86')">
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Aes.PlatformNotSupported.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx.PlatformNotSupported.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Avx2.PlatformNotSupported.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Bmi1.PlatformNotSupported.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Bmi2.PlatformNotSupported.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Fma.PlatformNotSupported.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Lzcnt.PlatformNotSupported.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Pclmulqdq.PlatformNotSupported.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Popcnt.PlatformNotSupported.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Sse.PlatformNotSupported.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Sse2.PlatformNotSupported.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Sse3.PlatformNotSupported.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Sse41.PlatformNotSupported.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Sse42.PlatformNotSupported.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Ssse3.PlatformNotSupported.cs" />
+ </ItemGroup>
+ <ItemGroup Condition="'$(FeatureHardwareIntrinsics)' == 'true' AND '$(Platform)' == 'arm64'">
+ <Compile Include="$(MSBuildThisFileDirectory)\System\Runtime\Intrinsics\Arm\Arm64\Aes.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)\System\Runtime\Intrinsics\Arm\Arm64\Base.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)\System\Runtime\Intrinsics\Arm\Arm64\Sha1.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)\System\Runtime\Intrinsics\Arm\Arm64\Sha256.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)\System\Runtime\Intrinsics\Arm\Arm64\Simd.cs" />
+ </ItemGroup>
+ <ItemGroup Condition="'$(FeatureHardwareIntrinsics)' != 'true' OR '$(Platform)' != 'arm64'">
+ <Compile Include="$(MSBuildThisFileDirectory)\System\Runtime\Intrinsics\Arm\Arm64\Aes.PlatformNotSupported.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)\System\Runtime\Intrinsics\Arm\Arm64\Base.PlatformNotSupported.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)\System\Runtime\Intrinsics\Arm\Arm64\Sha1.PlatformNotSupported.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)\System\Runtime\Intrinsics\Arm\Arm64\Sha256.PlatformNotSupported.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)\System\Runtime\Intrinsics\Arm\Arm64\Simd.PlatformNotSupported.cs" />
+ </ItemGroup>
</Project>
diff --git a/src/System.Private.CoreLib/shared/System/AccessViolationException.cs b/src/System.Private.CoreLib/shared/System/AccessViolationException.cs
index 280d9b8a9..a66f2a892 100644
--- a/src/System.Private.CoreLib/shared/System/AccessViolationException.cs
+++ b/src/System.Private.CoreLib/shared/System/AccessViolationException.cs
@@ -26,13 +26,13 @@ namespace System
HResult = HResults.E_POINTER;
}
- public AccessViolationException(String message)
+ public AccessViolationException(string message)
: base(message)
{
HResult = HResults.E_POINTER;
}
- public AccessViolationException(String message, Exception innerException)
+ public AccessViolationException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.E_POINTER;
diff --git a/src/System.Private.CoreLib/shared/System/ApplicationException.cs b/src/System.Private.CoreLib/shared/System/ApplicationException.cs
index f36e2c127..cac29196b 100644
--- a/src/System.Private.CoreLib/shared/System/ApplicationException.cs
+++ b/src/System.Private.CoreLib/shared/System/ApplicationException.cs
@@ -39,13 +39,13 @@ namespace System
// message, its HRESULT set to COR_E_APPLICATION,
// and its ExceptionInfo reference set to null.
//
- public ApplicationException(String message)
+ public ApplicationException(string message)
: base(message)
{
HResult = HResults.COR_E_APPLICATION;
}
- public ApplicationException(String message, Exception innerException)
+ public ApplicationException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_APPLICATION;
diff --git a/src/System.Private.CoreLib/shared/System/ArgumentException.cs b/src/System.Private.CoreLib/shared/System/ArgumentException.cs
index 8a8fe3e5e..5a918063e 100644
--- a/src/System.Private.CoreLib/shared/System/ArgumentException.cs
+++ b/src/System.Private.CoreLib/shared/System/ArgumentException.cs
@@ -23,7 +23,7 @@ namespace System
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class ArgumentException : SystemException
{
- private String _paramName;
+ private string _paramName;
// Creates a new ArgumentException with its message
// string set to the empty string.
@@ -36,26 +36,26 @@ namespace System
// Creates a new ArgumentException with its message
// string set to message.
//
- public ArgumentException(String message)
+ public ArgumentException(string message)
: base(message)
{
HResult = HResults.COR_E_ARGUMENT;
}
- public ArgumentException(String message, Exception innerException)
+ public ArgumentException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_ARGUMENT;
}
- public ArgumentException(String message, String paramName, Exception innerException)
+ public ArgumentException(string message, string paramName, Exception innerException)
: base(message, innerException)
{
_paramName = paramName;
HResult = HResults.COR_E_ARGUMENT;
}
- public ArgumentException(String message, String paramName)
+ public ArgumentException(string message, string paramName)
: base(message)
{
_paramName = paramName;
@@ -74,14 +74,14 @@ namespace System
info.AddValue("ParamName", _paramName, typeof(string));
}
- public override String Message
+ public override string Message
{
get
{
- String s = base.Message;
- if (!String.IsNullOrEmpty(_paramName))
+ string s = base.Message;
+ if (!string.IsNullOrEmpty(_paramName))
{
- String resourceString = SR.Format(SR.Arg_ParamName_Name, _paramName);
+ string resourceString = SR.Format(SR.Arg_ParamName_Name, _paramName);
return s + Environment.NewLine + resourceString;
}
else
@@ -89,7 +89,7 @@ namespace System
}
}
- public virtual String ParamName
+ public virtual string ParamName
{
get { return _paramName; }
}
diff --git a/src/System.Private.CoreLib/shared/System/ArgumentNullException.cs b/src/System.Private.CoreLib/shared/System/ArgumentNullException.cs
index 80e43cc26..edc38f2a4 100644
--- a/src/System.Private.CoreLib/shared/System/ArgumentNullException.cs
+++ b/src/System.Private.CoreLib/shared/System/ArgumentNullException.cs
@@ -30,19 +30,19 @@ namespace System
HResult = HResults.E_POINTER;
}
- public ArgumentNullException(String paramName)
+ public ArgumentNullException(string paramName)
: base(SR.ArgumentNull_Generic, paramName)
{
HResult = HResults.E_POINTER;
}
- public ArgumentNullException(String message, Exception innerException)
+ public ArgumentNullException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.E_POINTER;
}
- public ArgumentNullException(String paramName, String message)
+ public ArgumentNullException(string paramName, string message)
: base(message, paramName)
{
HResult = HResults.E_POINTER;
diff --git a/src/System.Private.CoreLib/shared/System/ArgumentOutOfRangeException.cs b/src/System.Private.CoreLib/shared/System/ArgumentOutOfRangeException.cs
index 604caa8ee..8d91561ce 100644
--- a/src/System.Private.CoreLib/shared/System/ArgumentOutOfRangeException.cs
+++ b/src/System.Private.CoreLib/shared/System/ArgumentOutOfRangeException.cs
@@ -22,7 +22,7 @@ namespace System
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class ArgumentOutOfRangeException : ArgumentException
{
- private Object _actualValue;
+ private object _actualValue;
// Creates a new ArgumentOutOfRangeException with its message
// string set to a default message explaining an argument was out of range.
@@ -32,19 +32,19 @@ namespace System
HResult = HResults.COR_E_ARGUMENTOUTOFRANGE;
}
- public ArgumentOutOfRangeException(String paramName)
+ public ArgumentOutOfRangeException(string paramName)
: base(SR.Arg_ArgumentOutOfRangeException, paramName)
{
HResult = HResults.COR_E_ARGUMENTOUTOFRANGE;
}
- public ArgumentOutOfRangeException(String paramName, String message)
+ public ArgumentOutOfRangeException(string paramName, string message)
: base(message, paramName)
{
HResult = HResults.COR_E_ARGUMENTOUTOFRANGE;
}
- public ArgumentOutOfRangeException(String message, Exception innerException)
+ public ArgumentOutOfRangeException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_ARGUMENTOUTOFRANGE;
@@ -53,7 +53,7 @@ namespace System
// We will not use this in the classlibs, but we'll provide it for
// anyone that's really interested so they don't have to stick a bunch
// of printf's in their code.
- public ArgumentOutOfRangeException(String paramName, Object actualValue, String message)
+ public ArgumentOutOfRangeException(string paramName, object actualValue, string message)
: base(message, paramName)
{
_actualValue = actualValue;
@@ -72,14 +72,14 @@ namespace System
info.AddValue("ActualValue", _actualValue, typeof(object));
}
- public override String Message
+ public override string Message
{
get
{
- String s = base.Message;
+ string s = base.Message;
if (_actualValue != null)
{
- String valueMessage = SR.Format(SR.ArgumentOutOfRange_ActualValue, _actualValue.ToString());
+ string valueMessage = SR.Format(SR.ArgumentOutOfRange_ActualValue, _actualValue.ToString());
if (s == null)
return valueMessage;
return s + Environment.NewLine + valueMessage;
@@ -92,7 +92,7 @@ namespace System
// Note - we don't set this anywhere in the class libraries in
// version 1, but it might come in handy for other developers who
// want to avoid sticking printf's in their code.
- public virtual Object ActualValue
+ public virtual object ActualValue
{
get { return _actualValue; }
}
diff --git a/src/System.Private.CoreLib/shared/System/ArithmeticException.cs b/src/System.Private.CoreLib/shared/System/ArithmeticException.cs
index 606f1debf..46492cab5 100644
--- a/src/System.Private.CoreLib/shared/System/ArithmeticException.cs
+++ b/src/System.Private.CoreLib/shared/System/ArithmeticException.cs
@@ -34,13 +34,13 @@ namespace System
// message, its HRESULT set to COR_E_ARITHMETIC,
// and its ExceptionInfo reference set to null.
//
- public ArithmeticException(String message)
+ public ArithmeticException(string message)
: base(message)
{
HResult = HResults.COR_E_ARITHMETIC;
}
- public ArithmeticException(String message, Exception innerException)
+ public ArithmeticException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_ARITHMETIC;
diff --git a/src/System.Private.CoreLib/shared/System/ArraySegment.cs b/src/System.Private.CoreLib/shared/System/ArraySegment.cs
index 3a13595e8..b2bd41780 100644
--- a/src/System.Private.CoreLib/shared/System/ArraySegment.cs
+++ b/src/System.Private.CoreLib/shared/System/ArraySegment.cs
@@ -131,7 +131,7 @@ namespace System
System.Array.Copy(_array, _offset, destination._array, destination._offset, _count);
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
if (obj is ArraySegment<T>)
return Equals((ArraySegment<T>)obj);
@@ -289,7 +289,7 @@ namespace System
bool ICollection<T>.Remove(T item)
{
ThrowHelper.ThrowNotSupportedException();
- return default(bool);
+ return default;
}
#endregion
diff --git a/src/System.Private.CoreLib/shared/System/ArrayTypeMismatchException.cs b/src/System.Private.CoreLib/shared/System/ArrayTypeMismatchException.cs
index 49820f58f..2f60fd4ea 100644
--- a/src/System.Private.CoreLib/shared/System/ArrayTypeMismatchException.cs
+++ b/src/System.Private.CoreLib/shared/System/ArrayTypeMismatchException.cs
@@ -34,13 +34,13 @@ namespace System
// message, its HRESULT set to COR_E_ARRAYTYPEMISMATCH,
// and its ExceptionInfo reference set to null.
//
- public ArrayTypeMismatchException(String message)
+ public ArrayTypeMismatchException(string message)
: base(message)
{
HResult = HResults.COR_E_ARRAYTYPEMISMATCH;
}
- public ArrayTypeMismatchException(String message, Exception innerException)
+ public ArrayTypeMismatchException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_ARRAYTYPEMISMATCH;
diff --git a/src/System.Private.CoreLib/shared/System/BadImageFormatException.cs b/src/System.Private.CoreLib/shared/System/BadImageFormatException.cs
index 1743075a6..c8cb65c64 100644
--- a/src/System.Private.CoreLib/shared/System/BadImageFormatException.cs
+++ b/src/System.Private.CoreLib/shared/System/BadImageFormatException.cs
@@ -21,8 +21,8 @@ namespace System
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public partial class BadImageFormatException : SystemException
{
- private String _fileName; // The name of the corrupt PE file.
- private String _fusionLog = null; // fusion log (when applicable)
+ private string _fileName; // The name of the corrupt PE file.
+ private string _fusionLog = null; // fusion log (when applicable)
public BadImageFormatException()
: base(SR.Arg_BadImageFormatException)
@@ -30,25 +30,25 @@ namespace System
HResult = HResults.COR_E_BADIMAGEFORMAT;
}
- public BadImageFormatException(String message)
+ public BadImageFormatException(string message)
: base(message)
{
HResult = HResults.COR_E_BADIMAGEFORMAT;
}
- public BadImageFormatException(String message, Exception inner)
+ public BadImageFormatException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_BADIMAGEFORMAT;
}
- public BadImageFormatException(String message, String fileName) : base(message)
+ public BadImageFormatException(string message, string fileName) : base(message)
{
HResult = HResults.COR_E_BADIMAGEFORMAT;
_fileName = fileName;
}
- public BadImageFormatException(String message, String fileName, Exception inner)
+ public BadImageFormatException(string message, string fileName, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_BADIMAGEFORMAT;
@@ -69,7 +69,7 @@ namespace System
info.AddValue("BadImageFormat_FusionLog", _fusionLog, typeof(string));
}
- public override String Message
+ public override string Message
{
get
{
@@ -91,14 +91,14 @@ namespace System
}
}
- public String FileName
+ public string FileName
{
get { return _fileName; }
}
- public override String ToString()
+ public override string ToString()
{
- String s = GetType().ToString() + ": " + Message;
+ string s = GetType().ToString() + ": " + Message;
if (_fileName != null && _fileName.Length != 0)
s += Environment.NewLine + SR.Format(SR.IO_FileName_Name, _fileName);
@@ -121,7 +121,7 @@ namespace System
return s;
}
- public String FusionLog
+ public string FusionLog
{
get { return _fusionLog; }
}
diff --git a/src/System.Private.CoreLib/shared/System/BitConverter.cs b/src/System.Private.CoreLib/shared/System/BitConverter.cs
index e3cf20eb6..8a8101ddc 100644
--- a/src/System.Private.CoreLib/shared/System/BitConverter.cs
+++ b/src/System.Private.CoreLib/shared/System/BitConverter.cs
@@ -376,7 +376,7 @@ namespace System
if (length > (int.MaxValue / 3))
{
- // (Int32.MaxValue / 3) == 715,827,882 Bytes == 699 MB
+ // (int.MaxValue / 3) == 715,827,882 Bytes == 699 MB
throw new ArgumentOutOfRangeException(nameof(length), SR.Format(SR.ArgumentOutOfRange_LengthTooLarge, (int.MaxValue / 3)));
}
diff --git a/src/System.Private.CoreLib/shared/System/Boolean.cs b/src/System.Private.CoreLib/shared/System/Boolean.cs
index fd56082f9..4daf6f3f9 100644
--- a/src/System.Private.CoreLib/shared/System/Boolean.cs
+++ b/src/System.Private.CoreLib/shared/System/Boolean.cs
@@ -12,7 +12,6 @@
**
===========================================================*/
-using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
@@ -20,12 +19,12 @@ namespace System
{
[Serializable]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct Boolean : IComparable, IConvertible, IComparable<Boolean>, IEquatable<Boolean>
+ public readonly struct Boolean : IComparable, IConvertible, IComparable<bool>, IEquatable<bool>
{
//
// Member Variables
//
- private bool m_value; // Do not rename (binary serialization)
+ private readonly bool m_value; // Do not rename (binary serialization)
// The true value.
//
@@ -42,11 +41,11 @@ namespace System
// The internal string representation of true.
//
- internal const String TrueLiteral = "True";
+ internal const string TrueLiteral = "True";
// The internal string representation of false.
//
- internal const String FalseLiteral = "False";
+ internal const string FalseLiteral = "False";
//
@@ -55,11 +54,11 @@ namespace System
// The public string representation of true.
//
- public static readonly String TrueString = TrueLiteral;
+ public static readonly string TrueString = TrueLiteral;
// The public string representation of false.
//
- public static readonly String FalseString = FalseLiteral;
+ public static readonly string FalseString = FalseLiteral;
//
// Overriden Instance Methods
@@ -82,7 +81,7 @@ namespace System
**Exceptions: None.
==============================================================================*/
// Converts the boolean value of this instance to a String.
- public override String ToString()
+ public override string ToString()
{
if (false == m_value)
{
@@ -91,41 +90,57 @@ namespace System
return TrueLiteral;
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return ToString();
}
public bool TryFormat(Span<char> destination, out int charsWritten)
{
- string s = m_value ? TrueLiteral : FalseLiteral;
-
- if (s.AsSpan().TryCopyTo(destination))
+ if (m_value)
{
- charsWritten = s.Length;
- return true;
+ if ((uint)destination.Length > 3) // uint cast, per https://github.com/dotnet/coreclr/issues/18688
+ {
+ destination[0] = 'T';
+ destination[1] = 'r';
+ destination[2] = 'u';
+ destination[3] = 'e';
+ charsWritten = 4;
+ return true;
+ }
}
else
{
- charsWritten = 0;
- return false;
+ if ((uint)destination.Length > 4)
+ {
+ destination[0] = 'F';
+ destination[1] = 'a';
+ destination[2] = 'l';
+ destination[3] = 's';
+ destination[4] = 'e';
+ charsWritten = 5;
+ return true;
+ }
}
+
+ charsWritten = 0;
+ return false;
}
// Determines whether two Boolean objects are equal.
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
//If it's not a boolean, we're definitely not equal
- if (!(obj is Boolean))
+ if (!(obj is bool))
{
return false;
}
- return (m_value == ((Boolean)obj).m_value);
+ return (m_value == ((bool)obj).m_value);
}
[NonVersionable]
- public bool Equals(Boolean obj)
+ public bool Equals(bool obj)
{
return m_value == obj;
}
@@ -137,18 +152,18 @@ namespace System
//
// Returns a value less than zero if this object
//
- public int CompareTo(Object obj)
+ public int CompareTo(object obj)
{
if (obj == null)
{
return 1;
}
- if (!(obj is Boolean))
+ if (!(obj is bool))
{
throw new ArgumentException(SR.Arg_MustBeBoolean);
}
- if (m_value == ((Boolean)obj).m_value)
+ if (m_value == ((bool)obj).m_value)
{
return 0;
}
@@ -159,7 +174,7 @@ namespace System
return 1;
}
- public int CompareTo(Boolean value)
+ public int CompareTo(bool value)
{
if (m_value == value)
{
@@ -176,20 +191,41 @@ namespace System
// Static Methods
//
+ // Custom string compares for early application use by config switches, etc
+ //
+ internal static bool IsTrueStringIgnoreCase(ReadOnlySpan<char> value)
+ {
+ return (value.Length == 4 &&
+ (value[0] == 't' || value[0] == 'T') &&
+ (value[1] == 'r' || value[1] == 'R') &&
+ (value[2] == 'u' || value[2] == 'U') &&
+ (value[3] == 'e' || value[3] == 'E'));
+ }
+
+ internal static bool IsFalseStringIgnoreCase(ReadOnlySpan<char> value)
+ {
+ return (value.Length == 5 &&
+ (value[0] == 'f' || value[0] == 'F') &&
+ (value[1] == 'a' || value[1] == 'A') &&
+ (value[2] == 'l' || value[2] == 'L') &&
+ (value[3] == 's' || value[3] == 'S') &&
+ (value[4] == 'e' || value[4] == 'E'));
+ }
+
// Determines whether a String represents true or false.
//
- public static Boolean Parse(String value)
+ public static bool Parse(string value)
{
if (value == null) throw new ArgumentNullException(nameof(value));
return Parse(value.AsSpan());
}
public static bool Parse(ReadOnlySpan<char> value) =>
- TryParse(value, out bool result) ? result : throw new FormatException(SR.Format_BadBoolean);
+ TryParse(value, out bool result) ? result : throw new FormatException(SR.Format(SR.Format_BadBoolean, new string(value)));
// Determines whether a String represents true or false.
//
- public static Boolean TryParse(String value, out Boolean result)
+ public static bool TryParse(string value, out bool result)
{
if (value == null)
{
@@ -202,15 +238,13 @@ namespace System
public static bool TryParse(ReadOnlySpan<char> value, out bool result)
{
- ReadOnlySpan<char> trueSpan = TrueLiteral.AsSpan();
- if (StringSpanHelpers.Equals(trueSpan, value, StringComparison.OrdinalIgnoreCase))
+ if (IsTrueStringIgnoreCase(value))
{
result = true;
return true;
}
- ReadOnlySpan<char> falseSpan = FalseLiteral.AsSpan();
- if (StringSpanHelpers.Equals(falseSpan, value, StringComparison.OrdinalIgnoreCase))
+ if (IsFalseStringIgnoreCase(value))
{
result = false;
return true;
@@ -219,13 +253,13 @@ namespace System
// Special case: Trim whitespace as well as null characters.
value = TrimWhiteSpaceAndNull(value);
- if (StringSpanHelpers.Equals(trueSpan, value, StringComparison.OrdinalIgnoreCase))
+ if (IsTrueStringIgnoreCase(value))
{
result = true;
return true;
}
- if (StringSpanHelpers.Equals(falseSpan, value, StringComparison.OrdinalIgnoreCase))
+ if (IsFalseStringIgnoreCase(value))
{
result = false;
return true;
@@ -242,7 +276,7 @@ namespace System
int start = 0;
while (start < value.Length)
{
- if (!Char.IsWhiteSpace(value[start]) && value[start] != nullChar)
+ if (!char.IsWhiteSpace(value[start]) && value[start] != nullChar)
{
break;
}
@@ -252,7 +286,7 @@ namespace System
int end = value.Length - 1;
while (end >= start)
{
- if (!Char.IsWhiteSpace(value[end]) && value[end] != nullChar)
+ if (!char.IsWhiteSpace(value[end]) && value[end] != nullChar)
{
break;
}
@@ -332,7 +366,7 @@ namespace System
return Convert.ToDouble(m_value);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -342,7 +376,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Boolean", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/ArrayPool.cs b/src/System.Private.CoreLib/shared/System/Buffers/ArrayPool.cs
index 77a07f7fa..22ad7821f 100644
--- a/src/System.Private.CoreLib/shared/System/Buffers/ArrayPool.cs
+++ b/src/System.Private.CoreLib/shared/System/Buffers/ArrayPool.cs
@@ -33,9 +33,7 @@ namespace System.Buffers
/// optimized for very fast access speeds, at the expense of more memory consumption.
/// The shared pool instance is created lazily on first access.
/// </remarks>
- public static ArrayPool<T> Shared { get; } =
- typeof(T) == typeof(byte) || typeof(T) == typeof(char) ? new TlsOverPerCoreLockedStacksArrayPool<T>() :
- Create();
+ public static ArrayPool<T> Shared { get; } = new TlsOverPerCoreLockedStacksArrayPool<T>();
/// <summary>
/// Creates a new <see cref="ArrayPool{T}"/> instance using default configuration options.
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/ArrayPoolEventSource.cs b/src/System.Private.CoreLib/shared/System/Buffers/ArrayPoolEventSource.cs
index b2d0dbd32..d0563c497 100644
--- a/src/System.Private.CoreLib/shared/System/Buffers/ArrayPoolEventSource.cs
+++ b/src/System.Private.CoreLib/shared/System/Buffers/ArrayPoolEventSource.cs
@@ -86,5 +86,19 @@ namespace System.Buffers
/// </summary>
[Event(3, Level = EventLevel.Verbose)]
internal void BufferReturned(int bufferId, int bufferSize, int poolId) => WriteEvent(3, bufferId, bufferSize, poolId);
+
+ /// <summary>
+ /// Event raised when we attempt to free a buffer due to inactivity or memory pressure (by no longer
+ /// referencing it). It is possible (although not commmon) this buffer could be rented as we attempt
+ /// to free it. A rent event before or after this event for the same ID, is a rare, but expected case.
+ /// </summary>
+ [Event(4, Level = EventLevel.Informational)]
+ internal void BufferTrimmed(int bufferId, int bufferSize, int poolId) => WriteEvent(4, bufferId, bufferSize, poolId);
+
+ /// <summary>
+ /// Event raised when we check to trim buffers.
+ /// </summary>
+ [Event(5, Level = EventLevel.Informational)]
+ internal void BufferTrimPoll(int milliseconds, int pressure) => WriteEvent(5, milliseconds, pressure);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/IMemoryOwner.cs b/src/System.Private.CoreLib/shared/System/Buffers/IMemoryOwner.cs
new file mode 100644
index 000000000..44f16c582
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Buffers/IMemoryOwner.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Buffers
+{
+ /// <summary>
+ /// Owner of Memory<typeparamref name="T"/> that is responsible for disposing the underlying memory appropriately.
+ /// </summary>
+ public interface IMemoryOwner<T> : IDisposable
+ {
+ /// <summary>
+ /// Returns a Memory<typeparamref name="T"/>.
+ /// </summary>
+ Memory<T> Memory { get; }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/IPinnable.cs b/src/System.Private.CoreLib/shared/System/Buffers/IPinnable.cs
new file mode 100644
index 000000000..623e716a0
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Buffers/IPinnable.cs
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Buffers
+{
+ /// <summary>
+ /// Provides a mechanism for pinning and unpinning objects to prevent the GC from moving them.
+ /// </summary>
+ public interface IPinnable
+ {
+ /// <summary>
+ /// Call this method to indicate that the IPinnable object can not be moved by the garbage collector.
+ /// The address of the pinned object can be taken.
+ /// <param name="elementIndex">The offset to the element within the memory at which the returned <see cref="MemoryHandle"/> points to.</param>
+ /// </summary>
+ MemoryHandle Pin(int elementIndex);
+
+ /// <summary>
+ /// Call this method to indicate that the IPinnable object no longer needs to be pinned.
+ /// The garbage collector is free to move the object now.
+ /// </summary>
+ void Unpin();
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/IRetainable.cs b/src/System.Private.CoreLib/shared/System/Buffers/IRetainable.cs
deleted file mode 100644
index 6ac508859..000000000
--- a/src/System.Private.CoreLib/shared/System/Buffers/IRetainable.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Runtime;
-using System.Runtime.CompilerServices;
-
-namespace System.Buffers
-{
- /// <summary>
- /// Provides a mechanism for manual lifetime management.
- /// </summary>
- public interface IRetainable
- {
- /// <summary>
- /// Call this method to indicate that the IRetainable object is in use.
- /// Do not dispose until Release is called.
- /// </summary>
- void Retain();
- /// <summary>
- /// Call this method to indicate that the IRetainable object is no longer in use.
- /// The object can now be disposed.
- /// </summary>
- bool Release();
- }
-} \ No newline at end of file
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/MemoryHandle.cs b/src/System.Private.CoreLib/shared/System/Buffers/MemoryHandle.cs
index 754403862..b218534c5 100644
--- a/src/System.Private.CoreLib/shared/System/Buffers/MemoryHandle.cs
+++ b/src/System.Private.CoreLib/shared/System/Buffers/MemoryHandle.cs
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Runtime;
using System.Runtime.InteropServices;
namespace System.Buffers
@@ -12,53 +11,48 @@ namespace System.Buffers
/// </summary>
public unsafe struct MemoryHandle : IDisposable
{
- private IRetainable _retainable;
private void* _pointer;
private GCHandle _handle;
+ private IPinnable _pinnable;
/// <summary>
/// Creates a new memory handle for the memory.
/// </summary>
- /// <param name="retainable">reference to manually managed object</param>
- /// <param name="pointer">pointer to memory, or null if a pointer was not provided when the handle was created</param>
+ /// <param name="pointer">pointer to memory</param>
+ /// <param name="pinnable">reference to manually managed object, or default if there is no memory manager</param>
/// <param name="handle">handle used to pin array buffers</param>
[CLSCompliant(false)]
- public MemoryHandle(IRetainable retainable, void* pointer = null, GCHandle handle = default(GCHandle))
+ public MemoryHandle(void* pointer, GCHandle handle = default, IPinnable pinnable = default)
{
- _retainable = retainable;
_pointer = pointer;
_handle = handle;
+ _pinnable = pinnable;
}
/// <summary>
- /// Returns the pointer to memory, or null if a pointer was not provided when the handle was created.
+ /// Returns the pointer to memory, where the memory is assumed to be pinned and hence the address won't change.
/// </summary>
[CLSCompliant(false)]
public void* Pointer => _pointer;
/// <summary>
- /// Returns false if the pointer to memory is null.
+ /// Frees the pinned handle and releases IPinnable.
/// </summary>
- public bool HasPointer => _pointer != null;
-
- /// <summary>
- /// Frees the pinned handle and releases IRetainable.
- /// </summary>
- public void Dispose()
+ public void Dispose()
{
if (_handle.IsAllocated)
{
_handle.Free();
}
- if (_retainable != null)
+ if (_pinnable != null)
{
- _retainable.Release();
- _retainable = null;
+ _pinnable.Unpin();
+ _pinnable = null;
}
_pointer = null;
}
}
-} \ No newline at end of file
+}
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/MemoryManager.cs b/src/System.Private.CoreLib/shared/System/Buffers/MemoryManager.cs
new file mode 100644
index 000000000..1b235b538
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Buffers/MemoryManager.cs
@@ -0,0 +1,75 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.CompilerServices;
+
+namespace System.Buffers
+{
+ /// <summary>
+ /// Manager of <see cref="System.Memory{T}"/> that provides the implementation.
+ /// </summary>
+ public abstract class MemoryManager<T> : IMemoryOwner<T>, IPinnable
+ {
+ /// <summary>
+ /// Returns a <see cref="System.Memory{T}"/>.
+ /// </summary>
+ public virtual Memory<T> Memory => new Memory<T>(this, GetSpan().Length);
+
+ /// <summary>
+ /// Returns a span wrapping the underlying memory.
+ /// </summary>
+ public abstract Span<T> GetSpan();
+
+ /// <summary>
+ /// Returns a handle to the memory that has been pinned and hence its address can be taken.
+ /// </summary>
+ /// <param name="elementIndex">The offset to the element within the memory at which the returned <see cref="MemoryHandle"/> points to. (default = 0)</param>
+ public abstract MemoryHandle Pin(int elementIndex = 0);
+
+ /// <summary>
+ /// Lets the garbage collector know that the object is free to be moved now.
+ /// </summary>
+ public abstract void Unpin();
+
+ /// <summary>
+ /// Returns a <see cref="System.Memory{T}"/> for the current <see cref="MemoryManager{T}"/>.
+ /// </summary>
+ /// <param name="length">The element count in the memory, starting at offset 0.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected Memory<T> CreateMemory(int length) => new Memory<T>(this, length);
+
+ /// <summary>
+ /// Returns a <see cref="System.Memory{T}"/> for the current <see cref="MemoryManager{T}"/>.
+ /// </summary>
+ /// <param name="start">The offset to the element which the returned memory starts at.</param>
+ /// <param name="length">The element count in the memory, starting at element offset <paramref name="start"/>.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ protected Memory<T> CreateMemory(int start, int length) => new Memory<T>(this, start, length);
+
+ /// <summary>
+ /// Returns an array segment.
+ /// <remarks>Returns the default array segment if not overriden.</remarks>
+ /// </summary>
+ protected internal virtual bool TryGetArray(out ArraySegment<T> segment)
+ {
+ segment = default;
+ return false;
+ }
+
+ /// <summary>
+ /// Implements IDisposable.
+ /// </summary>
+ void IDisposable.Dispose()
+ {
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Clean up of any leftover managed and unmanaged resources.
+ /// </summary>
+ protected abstract void Dispose(bool disposing);
+
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/OwnedMemory.cs b/src/System.Private.CoreLib/shared/System/Buffers/OwnedMemory.cs
deleted file mode 100644
index eade1feff..000000000
--- a/src/System.Private.CoreLib/shared/System/Buffers/OwnedMemory.cs
+++ /dev/null
@@ -1,95 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Runtime;
-using System.Runtime.CompilerServices;
-
-namespace System.Buffers
-{
- /// <summary>
- /// Owner of Memory<typeparamref name="T"/> that provides appropriate lifetime management mechanisms for it.
- /// </summary>
- public abstract class OwnedMemory<T> : IDisposable, IRetainable
- {
- /// <summary>
- /// The number of items in the Memory<typeparamref name="T"/>.
- /// </summary>
- public abstract int Length { get; }
-
- /// <summary>
- /// Returns a span wrapping the underlying memory.
- /// </summary>
- public abstract Span<T> Span { get; }
-
- /// <summary>
- /// Returns a Memory<typeparamref name="T"/> if the underlying memory has not been freed.
- /// </summary>
- /// <exception cref="System.ObjectDisposedException">
- /// Thrown when the underlying memory has already been disposed.
- /// </exception>
- public Memory<T> Memory
- {
- get
- {
- if (IsDisposed)
- {
- ThrowHelper.ThrowObjectDisposedException_MemoryDisposed();
- }
- return new Memory<T>(owner: this, 0, Length);
- }
- }
-
- /// <summary>
- /// Returns a handle for the array that has been pinned and hence its address can be taken
- /// </summary>
- public abstract MemoryHandle Pin(int byteOffset = 0);
-
- /// <summary>
- /// Returns an array segment.
- /// </summary>
- protected internal abstract bool TryGetArray(out ArraySegment<T> arraySegment);
-
- /// <summary>
- /// Implements IDisposable.
- /// </summary>
- /// <exception cref="System.InvalidOperationException">
- /// Throw when there are still retained references to the memory
- /// </exception>
- public void Dispose()
- {
- if (IsRetained)
- {
- ThrowHelper.ThrowInvalidOperationException_OutstandingReferences();
- }
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- /// <summary>
- /// Clean up of any leftover managed and unmanaged resources.
- /// </summary>
- protected abstract void Dispose(bool disposing);
-
- /// <summary>
- /// Return true if someone is holding a reference to the memory.
- /// </summary>
- protected abstract bool IsRetained { get; }
-
- /// <summary>
- /// Return true if the underlying memory has been freed.
- /// </summary>
- public abstract bool IsDisposed { get; }
-
- /// <summary>
- /// Implements IRetainable. Prevent accidental disposal of the memory.
- /// </summary>
- public abstract void Retain();
-
- /// <summary>
- /// Implements IRetainable. The memory can now be diposed.
- /// </summary>
- public abstract bool Release();
-
- }
-}
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/Text/FormattingHelpers.CountDigits.cs b/src/System.Private.CoreLib/shared/System/Buffers/Text/FormattingHelpers.CountDigits.cs
new file mode 100644
index 000000000..b6140adba
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Buffers/Text/FormattingHelpers.CountDigits.cs
@@ -0,0 +1,161 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace System.Buffers.Text
+{
+ internal static partial class FormattingHelpers
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int CountDigits(ulong value)
+ {
+ int digits = 1;
+ uint part;
+ if (value >= 10000000)
+ {
+ if (value >= 100000000000000)
+ {
+ part = (uint)(value / 100000000000000);
+ digits += 14;
+ }
+ else
+ {
+ part = (uint)(value / 10000000);
+ digits += 7;
+ }
+ }
+ else
+ {
+ part = (uint)value;
+ }
+
+ if (part < 10)
+ {
+ // no-op
+ }
+ else if (part < 100)
+ {
+ digits += 1;
+ }
+ else if (part < 1000)
+ {
+ digits += 2;
+ }
+ else if (part < 10000)
+ {
+ digits += 3;
+ }
+ else if (part < 100000)
+ {
+ digits += 4;
+ }
+ else if (part < 1000000)
+ {
+ digits += 5;
+ }
+ else
+ {
+ Debug.Assert(part < 10000000);
+ digits += 6;
+ }
+
+ return digits;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int CountDigits(uint value)
+ {
+ int digits = 1;
+ if (value >= 100000)
+ {
+ value = value / 100000;
+ digits += 5;
+ }
+
+ if (value < 10)
+ {
+ // no-op
+ }
+ else if (value < 100)
+ {
+ digits += 1;
+ }
+ else if (value < 1000)
+ {
+ digits += 2;
+ }
+ else if (value < 10000)
+ {
+ digits += 3;
+ }
+ else
+ {
+ Debug.Assert(value < 100000);
+ digits += 4;
+ }
+
+ return digits;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int CountHexDigits(ulong value)
+ {
+ // TODO: When x86 intrinsic support comes online, experiment with implementing this using lzcnt.
+ // return 16 - (int)((uint)Lzcnt.LeadingZeroCount(value | 1) >> 3);
+
+ int digits = 1;
+
+ if (value > 0xFFFFFFFF)
+ {
+ digits += 8;
+ value >>= 0x20;
+ }
+ if (value > 0xFFFF)
+ {
+ digits += 4;
+ value >>= 0x10;
+ }
+ if (value > 0xFF)
+ {
+ digits += 2;
+ value >>= 0x8;
+ }
+ if (value > 0xF)
+ digits++;
+
+ return digits;
+ }
+
+
+ // Counts the number of trailing '0' digits in a decimal number.
+ // e.g., value = 0 => retVal = 0, valueWithoutTrailingZeros = 0
+ // value = 1234 => retVal = 0, valueWithoutTrailingZeros = 1234
+ // value = 320900 => retVal = 2, valueWithoutTrailingZeros = 3209
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int CountDecimalTrailingZeros(uint value, out uint valueWithoutTrailingZeros)
+ {
+ int zeroCount = 0;
+
+ if (value != 0)
+ {
+ while (true)
+ {
+ uint temp = value / 10;
+ if (value != (temp * 10))
+ {
+ break;
+ }
+
+ value = temp;
+ zeroCount++;
+ }
+ }
+
+ valueWithoutTrailingZeros = value;
+ return zeroCount;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs b/src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs
index 64c5cebe8..96efb0d52 100644
--- a/src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs
+++ b/src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs
@@ -2,9 +2,12 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using Microsoft.Win32;
+using System;
+using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
+using Internal.Runtime.Augments;
+using Internal.Runtime.CompilerServices;
namespace System.Buffers
{
@@ -22,7 +25,6 @@ namespace System.Buffers
{
// TODO: #7747: "Investigate optimizing ArrayPool heuristics"
// - Explore caching in TLS more than one array per size per thread, and moving stale buffers to the global queue.
- // - Explore dumping stale buffers from the global queue, similar to PinnableBufferCache (maybe merging them).
// - Explore changing the size of each per-core bucket, potentially dynamically or based on other factors like array size.
// - Explore changing number of buckets and what sizes of arrays are cached.
// - Investigate whether false sharing is causing any issues, in particular on LockedStack's count and the contents of its array.
@@ -46,6 +48,15 @@ namespace System.Buffers
[ThreadStatic]
private static T[][] t_tlsBuckets;
+ private int _callbackCreated;
+
+ private readonly static bool s_trimBuffers = GetTrimBuffers();
+
+ /// <summary>
+ /// Used to keep track of all thread local buckets for trimming if needed
+ /// </summary>
+ private static readonly ConditionalWeakTable<T[][], object> s_allTlsBuckets = s_trimBuffers ? new ConditionalWeakTable<T[][], object>() : null;
+
/// <summary>Initialize the pool.</summary>
public TlsOverPerCoreLockedStacksArrayPool()
{
@@ -180,15 +191,24 @@ namespace System.Buffers
{
t_tlsBuckets = tlsBuckets = new T[NumBuckets][];
tlsBuckets[bucketIndex] = array;
+ if (s_trimBuffers)
+ {
+ s_allTlsBuckets.Add(tlsBuckets, null);
+ if (Interlocked.Exchange(ref _callbackCreated, 1) != 1)
+ {
+ Gen2GcCallback.Register(Gen2GcCallbackFunc, this);
+ }
+ }
}
else
{
T[] prev = tlsBuckets[bucketIndex];
tlsBuckets[bucketIndex] = array;
+
if (prev != null)
{
- PerCoreLockedStacks bucket = _buckets[bucketIndex] ?? CreatePerCoreLockedStacks(bucketIndex);
- bucket.TryPush(prev);
+ PerCoreLockedStacks stackBucket = _buckets[bucketIndex] ?? CreatePerCoreLockedStacks(bucketIndex);
+ stackBucket.TryPush(prev);
}
}
}
@@ -201,6 +221,103 @@ namespace System.Buffers
}
}
+ public bool Trim()
+ {
+ int milliseconds = Environment.TickCount;
+ MemoryPressure pressure = GetMemoryPressure();
+
+ ArrayPoolEventSource log = ArrayPoolEventSource.Log;
+ if (log.IsEnabled())
+ log.BufferTrimPoll(milliseconds, (int)pressure);
+
+ foreach (PerCoreLockedStacks bucket in _buckets)
+ {
+ bucket?.Trim((uint)milliseconds, Id, pressure, _bucketArraySizes);
+ }
+
+ if (pressure == MemoryPressure.High)
+ {
+ // Under high pressure, release all thread locals
+ if (log.IsEnabled())
+ {
+ foreach (KeyValuePair<T[][], object> tlsBuckets in s_allTlsBuckets)
+ {
+ T[][] buckets = tlsBuckets.Key;
+ for (int i = 0; i < buckets.Length; i++)
+ {
+ T[] buffer = Interlocked.Exchange(ref buckets[i], null);
+ if (buffer != null)
+ {
+ // As we don't want to take a perf hit in the rent path it
+ // is possible that a buffer could be rented as we "free" it.
+ log.BufferTrimmed(buffer.GetHashCode(), buffer.Length, Id);
+ }
+ }
+ }
+ }
+ else
+ {
+ foreach (KeyValuePair<T[][], object> tlsBuckets in s_allTlsBuckets)
+ {
+ T[][] buckets = tlsBuckets.Key;
+ Array.Clear(buckets, 0, buckets.Length);
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// This is the static function that is called from the gen2 GC callback.
+ /// The input object is the instance we want the callback on.
+ /// </summary>
+ /// <remarks>
+ /// The reason that we make this function static and take the instance as a parameter is that
+ /// we would otherwise root the instance to the Gen2GcCallback object, leaking the instance even when
+ /// the application no longer needs it.
+ /// </remarks>
+ private static bool Gen2GcCallbackFunc(object target)
+ {
+ return ((TlsOverPerCoreLockedStacksArrayPool<T>)(target)).Trim();
+ }
+
+ private enum MemoryPressure
+ {
+ Low,
+ Medium,
+ High
+ }
+
+ private static MemoryPressure GetMemoryPressure()
+ {
+ const double HighPressureThreshold = .90; // Percent of GC memory pressure threshold we consider "high"
+ const double MediumPressureThreshold = .70; // Percent of GC memory pressure threshold we consider "medium"
+
+ GC.GetMemoryInfo(out uint threshold, out _, out uint lastLoad, out _, out _);
+ if (lastLoad >= threshold * HighPressureThreshold)
+ {
+ return MemoryPressure.High;
+ }
+ else if (lastLoad >= threshold * MediumPressureThreshold)
+ {
+ return MemoryPressure.Medium;
+ }
+ return MemoryPressure.Low;
+ }
+
+ private static bool GetTrimBuffers()
+ {
+ // Environment uses ArrayPool, so we have to hit the API directly.
+#if !CORECLR
+ // P/Invokes are different for CoreCLR/RT- for RT we'll not allow
+ // enabling/disabling for now.
+ return true;
+#else
+ return CLRConfig.GetBoolValueWithFallbacks("System.Buffers.ArrayPool.TrimShared", "DOTNET_SYSTEM_BUFFERS_ARRAYPOOL_TRIMSHARED", defaultValue: true);
+#endif
+ }
+
/// <summary>
/// Stores a set of stacks of arrays, with one stack per core.
/// </summary>
@@ -228,7 +345,7 @@ namespace System.Buffers
// Try to push on to the associated stack first. If that fails,
// round-robin through the other stacks.
LockedStack[] stacks = _perCoreStacks;
- int index = Environment.CurrentExecutionId % stacks.Length;
+ int index = RuntimeThread.GetCurrentProcessorId() % stacks.Length;
for (int i = 0; i < stacks.Length; i++)
{
if (stacks[index].TryPush(array)) return;
@@ -244,7 +361,7 @@ namespace System.Buffers
// round-robin through the other stacks.
T[] arr;
LockedStack[] stacks = _perCoreStacks;
- int index = Environment.CurrentExecutionId % stacks.Length;
+ int index = RuntimeThread.GetCurrentProcessorId() % stacks.Length;
for (int i = 0; i < stacks.Length; i++)
{
if ((arr = stacks[index].TryPop()) != null) return arr;
@@ -252,6 +369,16 @@ namespace System.Buffers
}
return null;
}
+
+ public bool Trim(uint tickCount, int id, MemoryPressure pressure, int[] bucketSizes)
+ {
+ LockedStack[] stacks = _perCoreStacks;
+ for (int i = 0; i < stacks.Length; i++)
+ {
+ stacks[i].Trim(tickCount, id, pressure, bucketSizes[i]);
+ }
+ return true;
+ }
}
/// <summary>Provides a simple stack of arrays, protected by a lock.</summary>
@@ -259,6 +386,7 @@ namespace System.Buffers
{
private readonly T[][] _arrays = new T[MaxBuffersPerArraySizePerCore][];
private int _count;
+ private uint _firstStackItemMS;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryPush(T[] array)
@@ -267,6 +395,12 @@ namespace System.Buffers
Monitor.Enter(this);
if (_count < MaxBuffersPerArraySizePerCore)
{
+ if (s_trimBuffers && _count == 0)
+ {
+ // Stash the time the bottom of the stack was filled
+ _firstStackItemMS = (uint)Environment.TickCount;
+ }
+
_arrays[_count++] = array;
enqueued = true;
}
@@ -287,6 +421,76 @@ namespace System.Buffers
Monitor.Exit(this);
return arr;
}
+
+ public void Trim(uint tickCount, int id, MemoryPressure pressure, int bucketSize)
+ {
+ const uint StackTrimAfterMS = 60 * 1000; // Trim after 60 seconds for low/moderate pressure
+ const uint StackHighTrimAfterMS = 10 * 1000; // Trim after 10 seconds for high pressure
+ const uint StackRefreshMS = StackTrimAfterMS / 4; // Time bump after trimming (1/4 trim time)
+ const int StackLowTrimCount = 1; // Trim one item when pressure is low
+ const int StackMediumTrimCount = 2; // Trim two items when pressure is moderate
+ const int StackHighTrimCount = MaxBuffersPerArraySizePerCore; // Trim all items when pressure is high
+ const int StackLargeBucket = 16384; // If the bucket is larger than this we'll trim an extra when under high pressure
+ const int StackModerateTypeSize = 16; // If T is larger than this we'll trim an extra when under high pressure
+ const int StackLargeTypeSize = 32; // If T is larger than this we'll trim an extra (additional) when under high pressure
+
+ if (_count == 0)
+ return;
+ uint trimTicks = pressure == MemoryPressure.High ? StackHighTrimAfterMS : StackTrimAfterMS;
+
+ lock (this)
+ {
+ if (_count > 0 && _firstStackItemMS > tickCount || (tickCount - _firstStackItemMS) > trimTicks)
+ {
+ // We've wrapped the tick count or elapsed enough time since the
+ // first item went into the stack. Drop the top item so it can
+ // be collected and make the stack look a little newer.
+
+ ArrayPoolEventSource log = ArrayPoolEventSource.Log;
+ int trimCount = StackLowTrimCount;
+ switch (pressure)
+ {
+ case MemoryPressure.High:
+ trimCount = StackHighTrimCount;
+
+ // When pressure is high, aggressively trim larger arrays.
+ if (bucketSize > StackLargeBucket)
+ {
+ trimCount++;
+ }
+ if (Unsafe.SizeOf<T>() > StackModerateTypeSize)
+ {
+ trimCount++;
+ }
+ if (Unsafe.SizeOf<T>() > StackLargeTypeSize)
+ {
+ trimCount++;
+ }
+ break;
+ case MemoryPressure.Medium:
+ trimCount = StackMediumTrimCount;
+ break;
+ }
+
+ while (_count > 0 && trimCount-- > 0)
+ {
+ T[] array = _arrays[--_count];
+ _arrays[_count] = null;
+
+ if (log.IsEnabled())
+ {
+ log.BufferTrimmed(array.GetHashCode(), array.Length, id);
+ }
+ }
+
+ if (_count > 0 && _firstStackItemMS < uint.MaxValue - StackRefreshMS)
+ {
+ // Give the remaining items a bit more time
+ _firstStackItemMS += StackRefreshMS;
+ }
+ }
+ }
+ }
}
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Buffers/Utilities.cs b/src/System.Private.CoreLib/shared/System/Buffers/Utilities.cs
index 4f115fe9d..b675100b0 100644
--- a/src/System.Private.CoreLib/shared/System/Buffers/Utilities.cs
+++ b/src/System.Private.CoreLib/shared/System/Buffers/Utilities.cs
@@ -12,14 +12,19 @@ namespace System.Buffers
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static int SelectBucketIndex(int bufferSize)
{
+ Debug.Assert(bufferSize >= 0);
+
+ // bufferSize of 0 will underflow here, causing a huge
+ // index which the caller will discard because it is not
+ // within the bounds of the bucket array.
uint bitsRemaining = ((uint)bufferSize - 1) >> 4;
int poolIndex = 0;
if (bitsRemaining > 0xFFFF) { bitsRemaining >>= 16; poolIndex = 16; }
- if (bitsRemaining > 0xFF) { bitsRemaining >>= 8; poolIndex += 8; }
- if (bitsRemaining > 0xF) { bitsRemaining >>= 4; poolIndex += 4; }
- if (bitsRemaining > 0x3) { bitsRemaining >>= 2; poolIndex += 2; }
- if (bitsRemaining > 0x1) { bitsRemaining >>= 1; poolIndex += 1; }
+ if (bitsRemaining > 0xFF) { bitsRemaining >>= 8; poolIndex += 8; }
+ if (bitsRemaining > 0xF) { bitsRemaining >>= 4; poolIndex += 4; }
+ if (bitsRemaining > 0x3) { bitsRemaining >>= 2; poolIndex += 2; }
+ if (bitsRemaining > 0x1) { bitsRemaining >>= 1; poolIndex += 1; }
return poolIndex + (int)bitsRemaining;
}
diff --git a/src/System.Private.CoreLib/shared/System/Byte.cs b/src/System.Private.CoreLib/shared/System/Byte.cs
index 13ceb7573..da1f9147b 100644
--- a/src/System.Private.CoreLib/shared/System/Byte.cs
+++ b/src/System.Private.CoreLib/shared/System/Byte.cs
@@ -12,9 +12,9 @@ namespace System
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct Byte : IComparable, IConvertible, IFormattable, IComparable<Byte>, IEquatable<Byte>, ISpanFormattable
+ public readonly struct Byte : IComparable, IConvertible, IFormattable, IComparable<byte>, IEquatable<byte>, ISpanFormattable
{
- private byte m_value; // Do not rename (binary serialization)
+ private readonly byte m_value; // Do not rename (binary serialization)
// The maximum value that a Byte may represent: 255.
public const byte MaxValue = (byte)0xFF;
@@ -29,37 +29,37 @@ namespace System
// null is considered to be less than any instance.
// If object is not of type byte, this method throws an ArgumentException.
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
- if (!(value is Byte))
+ if (!(value is byte))
{
throw new ArgumentException(SR.Arg_MustBeByte);
}
- return m_value - (((Byte)value).m_value);
+ return m_value - (((byte)value).m_value);
}
- public int CompareTo(Byte value)
+ public int CompareTo(byte value)
{
return m_value - value;
}
// Determines whether two Byte objects are equal.
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is Byte))
+ if (!(obj is byte))
{
return false;
}
- return m_value == ((Byte)obj).m_value;
+ return m_value == ((byte)obj).m_value;
}
[NonVersionable]
- public bool Equals(Byte obj)
+ public bool Equals(byte obj)
{
return m_value == obj;
}
@@ -70,20 +70,20 @@ namespace System
return m_value;
}
- public static byte Parse(String s)
+ public static byte Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}
- public static byte Parse(String s, NumberStyles style)
+ public static byte Parse(string s, NumberStyles style)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, style, NumberFormatInfo.CurrentInfo);
}
- public static byte Parse(String s, IFormatProvider provider)
+ public static byte Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
@@ -92,7 +92,7 @@ namespace System
// Parses an unsigned byte from a String in the given style. If
// a NumberFormatInfo isn't specified, the current culture's
// NumberFormatInfo is assumed.
- public static byte Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static byte Parse(string s, NumberStyles style, IFormatProvider provider)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -121,7 +121,7 @@ namespace System
return (byte)i;
}
- public static bool TryParse(String s, out Byte result)
+ public static bool TryParse(string s, out byte result)
{
if (s == null)
{
@@ -137,7 +137,7 @@ namespace System
return TryParse(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
}
- public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out Byte result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out byte result)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
@@ -156,7 +156,7 @@ namespace System
return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
}
- private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out Byte result)
+ private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out byte result)
{
result = 0;
int i;
@@ -172,33 +172,29 @@ namespace System
return true;
}
- public override String ToString()
+ public override string ToString()
{
- return Number.FormatInt32(m_value, null, null);
+ return Number.FormatUInt32(m_value, null, null);
}
- public String ToString(String format)
+ public string ToString(string format)
{
- return Number.FormatInt32(m_value, format, null);
+ return Number.FormatUInt32(m_value, format, null);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
- return Number.FormatInt32(m_value, null, provider);
+ return Number.FormatUInt32(m_value, null, provider);
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
- return Number.FormatInt32(m_value, format, provider);
+ return Number.FormatUInt32(m_value, format, provider);
}
- // TODO https://github.com/dotnet/corefx/issues/25337: Remove this overload once corefx is updated to target the new signatures
- public bool TryFormat(Span<char> destination, out int charsWritten, string format, IFormatProvider provider) =>
- TryFormat(destination, out charsWritten, (ReadOnlySpan<char>)format, provider);
-
public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format = default, IFormatProvider provider = null)
{
- return Number.TryFormatInt32(m_value, format, provider, destination, out charsWritten);
+ return Number.TryFormatUInt32(m_value, format, provider, destination, out charsWritten);
}
//
@@ -270,7 +266,7 @@ namespace System
return Convert.ToDouble(m_value);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -280,7 +276,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Byte", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/Char.cs b/src/System.Private.CoreLib/shared/System/Char.cs
index d3ed1f5b6..8c743369b 100644
--- a/src/System.Private.CoreLib/shared/System/Char.cs
+++ b/src/System.Private.CoreLib/shared/System/Char.cs
@@ -21,12 +21,12 @@ namespace System
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct Char : IComparable, IComparable<Char>, IEquatable<Char>, IConvertible
+ public readonly struct Char : IComparable, IComparable<char>, IEquatable<char>, IConvertible
{
//
// Member Variables
//
- private char m_value; // Do not rename (binary serialization)
+ private readonly char m_value; // Do not rename (binary serialization)
//
// Public Constants
@@ -87,7 +87,7 @@ namespace System
// Return the Unicode category for Unicode character <= 0x00ff.
private static UnicodeCategory GetLatin1UnicodeCategory(char ch)
{
- Debug.Assert(IsLatin1(ch), "Char.GetLatin1UnicodeCategory(): ch should be <= 007f");
+ Debug.Assert(IsLatin1(ch), "char.GetLatin1UnicodeCategory(): ch should be <= 007f");
return (UnicodeCategory)(s_categoryForLatin1[(int)ch]);
}
@@ -107,17 +107,17 @@ namespace System
// Used for comparing two boxed Char objects.
//
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is Char))
+ if (!(obj is char))
{
return false;
}
- return (m_value == ((Char)obj).m_value);
+ return (m_value == ((char)obj).m_value);
}
[System.Runtime.Versioning.NonVersionable]
- public bool Equals(Char obj)
+ public bool Equals(char obj)
{
return m_value == obj;
}
@@ -128,34 +128,34 @@ namespace System
// null is considered to be less than any instance.
// If object is not of type Char, this method throws an ArgumentException.
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
- if (!(value is Char))
+ if (!(value is char))
{
throw new ArgumentException(SR.Arg_MustBeChar);
}
- return (m_value - ((Char)value).m_value);
+ return (m_value - ((char)value).m_value);
}
- public int CompareTo(Char value)
+ public int CompareTo(char value)
{
return (m_value - value);
}
// Overrides System.Object.ToString.
- public override String ToString()
+ public override string ToString()
{
- return Char.ToString(m_value);
+ return char.ToString(m_value);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
- return Char.ToString(m_value);
+ return char.ToString(m_value);
}
//
@@ -168,7 +168,7 @@ namespace System
// Provides a string representation of a character.
public static string ToString(char c) => string.CreateFromChar(c);
- public static char Parse(String s)
+ public static char Parse(string s)
{
if (s == null)
{
@@ -182,7 +182,7 @@ namespace System
return s[0];
}
- public static bool TryParse(String s, out Char result)
+ public static bool TryParse(string s, out char result)
{
result = '\0';
if (s == null)
@@ -201,7 +201,7 @@ namespace System
// Static Methods
//
/*=================================ISDIGIT======================================
- **A wrapper for Char. Returns a boolean indicating whether **
+ **A wrapper for char. Returns a boolean indicating whether **
**character c is considered to be a digit. **
==============================================================================*/
// Determines whether a character is a digit.
@@ -233,7 +233,7 @@ namespace System
}
/*=================================ISLETTER=====================================
- **A wrapper for Char. Returns a boolean indicating whether **
+ **A wrapper for char. Returns a boolean indicating whether **
**character c is considered to be a letter. **
==============================================================================*/
// Determines whether a character is a letter.
@@ -271,7 +271,7 @@ namespace System
}
/*===============================ISWHITESPACE===================================
- **A wrapper for Char. Returns a boolean indicating whether **
+ **A wrapper for char. Returns a boolean indicating whether **
**character c is considered to be a whitespace character. **
==============================================================================*/
// Determines whether a character is whitespace.
@@ -393,7 +393,7 @@ namespace System
}
/*=================================TOUPPER======================================
- **A wrapper for Char.toUpperCase. Converts character c to its **
+ **A wrapper for char.ToUpperCase. Converts character c to its **
**uppercase equivalent. If c is already an uppercase character or is not an **
**alphabetic, nothing happens. **
==============================================================================*/
@@ -425,7 +425,7 @@ namespace System
}
/*=================================TOLOWER======================================
- **A wrapper for Char.toLowerCase. Converts character c to its **
+ **A wrapper for char.ToLowerCase. Converts character c to its **
**lowercase equivalent. If c is already a lowercase character or is not an **
**alphabetic, nothing happens. **
==============================================================================*/
@@ -512,7 +512,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Char", "Double"));
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Char", "Decimal"));
}
@@ -522,7 +522,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Char", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
@@ -535,7 +535,7 @@ namespace System
return (CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.Control);
}
- public static bool IsControl(String s, int index)
+ public static bool IsControl(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -552,7 +552,7 @@ namespace System
}
- public static bool IsDigit(String s, int index)
+ public static bool IsDigit(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -568,7 +568,7 @@ namespace System
return (CharUnicodeInfo.GetUnicodeCategory(s, index) == UnicodeCategory.DecimalDigitNumber);
}
- public static bool IsLetter(String s, int index)
+ public static bool IsLetter(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -589,7 +589,7 @@ namespace System
return (CheckLetter(CharUnicodeInfo.GetUnicodeCategory(s, index)));
}
- public static bool IsLetterOrDigit(String s, int index)
+ public static bool IsLetterOrDigit(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -605,7 +605,7 @@ namespace System
return CheckLetterOrDigit(CharUnicodeInfo.GetUnicodeCategory(s, index));
}
- public static bool IsLower(String s, int index)
+ public static bool IsLower(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -655,7 +655,7 @@ namespace System
return (CheckNumber(CharUnicodeInfo.GetUnicodeCategory(c)));
}
- public static bool IsNumber(String s, int index)
+ public static bool IsNumber(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -683,7 +683,7 @@ namespace System
//
////////////////////////////////////////////////////////////////////////
- public static bool IsPunctuation(String s, int index)
+ public static bool IsPunctuation(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -732,7 +732,7 @@ namespace System
return (CheckSeparator(CharUnicodeInfo.GetUnicodeCategory(c)));
}
- public static bool IsSeparator(String s, int index)
+ public static bool IsSeparator(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -753,7 +753,7 @@ namespace System
return (c >= HIGH_SURROGATE_START && c <= LOW_SURROGATE_END);
}
- public static bool IsSurrogate(String s, int index)
+ public static bool IsSurrogate(string s, int index)
{
if (s == null)
{
@@ -792,7 +792,7 @@ namespace System
return (CheckSymbol(CharUnicodeInfo.GetUnicodeCategory(c)));
}
- public static bool IsSymbol(String s, int index)
+ public static bool IsSymbol(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -809,7 +809,7 @@ namespace System
}
- public static bool IsUpper(String s, int index)
+ public static bool IsUpper(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -830,7 +830,7 @@ namespace System
return (CharUnicodeInfo.GetUnicodeCategory(s, index) == UnicodeCategory.UppercaseLetter);
}
- public static bool IsWhiteSpace(String s, int index)
+ public static bool IsWhiteSpace(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -856,7 +856,7 @@ namespace System
return CharUnicodeInfo.GetUnicodeCategory((int)c);
}
- public static UnicodeCategory GetUnicodeCategory(String s, int index)
+ public static UnicodeCategory GetUnicodeCategory(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -876,7 +876,7 @@ namespace System
return CharUnicodeInfo.GetNumericValue(c);
}
- public static double GetNumericValue(String s, int index)
+ public static double GetNumericValue(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -896,7 +896,7 @@ namespace System
return ((c >= CharUnicodeInfo.HIGH_SURROGATE_START) && (c <= CharUnicodeInfo.HIGH_SURROGATE_END));
}
- public static bool IsHighSurrogate(String s, int index)
+ public static bool IsHighSurrogate(string s, int index)
{
if (s == null)
{
@@ -917,7 +917,7 @@ namespace System
return ((c >= CharUnicodeInfo.LOW_SURROGATE_START) && (c <= CharUnicodeInfo.LOW_SURROGATE_END));
}
- public static bool IsLowSurrogate(String s, int index)
+ public static bool IsLowSurrogate(string s, int index)
{
if (s == null)
{
@@ -933,7 +933,7 @@ namespace System
/*================================= IsSurrogatePair ============================
** Check if the string specified by the index starts with a surrogate pair.
==============================================================================*/
- public static bool IsSurrogatePair(String s, int index)
+ public static bool IsSurrogatePair(string s, int index)
{
if (s == null)
{
@@ -972,7 +972,7 @@ namespace System
** Convert an UTF32 value into a surrogate pair.
==============================================================================*/
- public static String ConvertFromUtf32(int utf32)
+ public static string ConvertFromUtf32(int utf32)
{
// For UTF32 values from U+00D800 ~ U+00DFFF, we should throw. They
// are considered as irregular code unit sequence, but they are not illegal.
@@ -984,7 +984,7 @@ namespace System
if (utf32 < UNICODE_PLANE01_START)
{
// This is a BMP character.
- return (Char.ToString((char)utf32));
+ return (char.ToString((char)utf32));
}
unsafe
@@ -1025,7 +1025,7 @@ namespace System
** This method throws if a low surrogate is seen without preceding a high-surrogate.
==============================================================================*/
- public static int ConvertToUtf32(String s, int index)
+ public static int ConvertToUtf32(string s, int index)
{
if (s == null)
{
diff --git a/src/System.Private.CoreLib/shared/System/CharEnumerator.cs b/src/System.Private.CoreLib/shared/System/CharEnumerator.cs
index ea9915a7c..ca60705d9 100644
--- a/src/System.Private.CoreLib/shared/System/CharEnumerator.cs
+++ b/src/System.Private.CoreLib/shared/System/CharEnumerator.cs
@@ -19,11 +19,11 @@ namespace System
{
public sealed class CharEnumerator : IEnumerator, IEnumerator<char>, IDisposable, ICloneable
{
- private String _str;
+ private string _str;
private int _index;
private char _currentElement;
- internal CharEnumerator(String str)
+ internal CharEnumerator(string str)
{
_str = str;
_index = -1;
@@ -54,7 +54,7 @@ namespace System
_str = null;
}
- Object IEnumerator.Current
+ object IEnumerator.Current
{
get { return Current; }
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Comparer.cs b/src/System.Private.CoreLib/shared/System/Collections/Comparer.cs
index 6fcedc09a..e22fb5bb9 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/Comparer.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/Comparer.cs
@@ -52,7 +52,7 @@ namespace System.Collections
// If a doesn't implement IComparable and b does, -(b.CompareTo(a)) is returned.
// Otherwise an exception is thrown.
//
- public int Compare(Object a, Object b)
+ public int Compare(object a, object b)
{
if (a == b) return 0;
if (a == null) return -1;
diff --git a/src/System.Private.CoreLib/shared/System/Collections/CompatibleComparer.cs b/src/System.Private.CoreLib/shared/System/Collections/CompatibleComparer.cs
new file mode 100644
index 000000000..587fd6839
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Collections/CompatibleComparer.cs
@@ -0,0 +1,61 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#pragma warning disable 618 // obsolete types
+
+namespace System.Collections
+{
+ internal sealed class CompatibleComparer : IEqualityComparer
+ {
+ private readonly IHashCodeProvider _hcp;
+ private readonly IComparer _comparer;
+
+ internal CompatibleComparer(IHashCodeProvider hashCodeProvider, IComparer comparer)
+ {
+ _hcp = hashCodeProvider;
+ _comparer = comparer;
+ }
+
+ internal IHashCodeProvider HashCodeProvider => _hcp;
+
+ internal IComparer Comparer => _comparer;
+
+ public new bool Equals(object a, object b) => Compare(a, b) == 0;
+
+ public int Compare(object a, object b)
+ {
+ if (a == b)
+ return 0;
+ if (a == null)
+ return -1;
+ if (b == null)
+ return 1;
+
+ if (_comparer != null)
+ {
+ return _comparer.Compare(a, b);
+ }
+
+ IComparable ia = a as IComparable;
+ if (ia != null)
+ {
+ return ia.CompareTo(b);
+ }
+
+ throw new ArgumentException(SR.Argument_ImplementIComparable);
+ }
+
+ public int GetHashCode(object obj)
+ {
+ if (obj == null)
+ {
+ throw new ArgumentNullException(nameof(obj));
+ }
+
+ return _hcp != null ?
+ _hcp.GetHashCode(obj) :
+ obj.GetHashCode();
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Collections/Concurrent/LowLevelConcurrentQueue.cs b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueue.cs
index 5e799db68..63880b09f 100644
--- a/src/System.Private.CoreLib/src/System/Collections/Concurrent/LowLevelConcurrentQueue.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueue.cs
@@ -2,20 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
-//
-// A lock-free, concurrent queue primitive, and its associated debugger view type.
-//
-// This is a stripped-down version of ConcurrentQueue, for use from within the System.Threading
-// surface to eliminate a dependency on System.Collections.Concurrent.
-// Please try to keep this in sync with the public ConcurrentQueue implementation.
-//
-// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
-using System.Runtime.Serialization;
using System.Threading;
namespace System.Collections.Concurrent
@@ -25,11 +14,12 @@ namespace System.Collections.Concurrent
/// </summary>
/// <typeparam name="T">Specifies the type of elements in the queue.</typeparam>
/// <remarks>
- /// All public and protected members of <see cref="LowLevelConcurrentQueue{T}"/> are thread-safe and may be used
+ /// All public and protected members of <see cref="ConcurrentQueue{T}"/> are thread-safe and may be used
/// concurrently from multiple threads.
/// </remarks>
[DebuggerDisplay("Count = {Count}")]
- internal class LowLevelConcurrentQueue<T> : /* IProducerConsumerCollection<T>, */ IReadOnlyCollection<T>
+ [DebuggerTypeProxy(typeof(IProducerConsumerCollectionDebugView<>))]
+ public class ConcurrentQueue<T> : IProducerConsumerCollection<T>, IReadOnlyCollection<T>
{
// This implementation provides an unbounded, multi-producer multi-consumer queue
// that supports the standard Enqueue/TryDequeue operations, as well as support for
@@ -62,47 +52,19 @@ namespace System.Collections.Concurrent
/// Lock used to protect cross-segment operations, including any updates to <see cref="_tail"/> or <see cref="_head"/>
/// and any operations that need to get a consistent view of them.
/// </summary>
- [NonSerialized]
- private Lock _crossSegmentLock;
+ private object _crossSegmentLock;
/// <summary>The current tail segment.</summary>
- [NonSerialized]
- private volatile Segment _tail;
+ private volatile ConcurrentQueueSegment<T> _tail;
/// <summary>The current head segment.</summary>
- [NonSerialized]
- private volatile Segment _head;
- /// <summary>Field used to temporarily store the contents of the queue for serialization.</summary>
- private T[] _serializationArray;
+ private volatile ConcurrentQueueSegment<T> _head;
/// <summary>
- /// Initializes a new instance of the <see cref="LowLevelConcurrentQueue{T}"/> class.
+ /// Initializes a new instance of the <see cref="ConcurrentQueue{T}"/> class.
/// </summary>
- public LowLevelConcurrentQueue()
- {
- _crossSegmentLock = new Lock();
- _tail = _head = new Segment(InitialSegmentLength);
- }
-
- /// <summary>Set the data array to be serialized.</summary>
- [OnSerializing]
- private void OnSerializing(StreamingContext context)
- {
- _serializationArray = ToArray();
- }
-
- /// <summary>Clear the data array that was serialized.</summary>
- [OnSerialized]
- private void OnSerialized(StreamingContext context)
- {
- _serializationArray = null;
- }
-
- /// <summary>Construct the queue from the deserialized <see cref="_serializationArray"/>.</summary>
- [OnDeserialized]
- private void OnDeserialized(StreamingContext context)
+ public ConcurrentQueue()
{
- Debug.Assert(_serializationArray != null);
- InitializeFromCollection(_serializationArray);
- _serializationArray = null;
+ _crossSegmentLock = new object();
+ _tail = _head = new ConcurrentQueueSegment<T>(InitialSegmentLength);
}
/// <summary>
@@ -111,10 +73,10 @@ namespace System.Collections.Concurrent
/// <param name="collection">A collection from which to copy elements.</param>
private void InitializeFromCollection(IEnumerable<T> collection)
{
- _crossSegmentLock = new Lock();
+ _crossSegmentLock = new object();
// Determine the initial segment size. We'll use the default,
- // unless the collection is known to be larger than than, in which
+ // unless the collection is known to be larger than that, in which
// case we round its length up to a power of 2, as all segments must
// be a power of 2 in length.
int length = InitialSegmentLength;
@@ -124,12 +86,12 @@ namespace System.Collections.Concurrent
int count = c.Count;
if (count > length)
{
- length = Math.Min(RoundUpToPowerOf2(count), MaxSegmentLength);
+ length = Math.Min(ConcurrentQueueSegment<T>.RoundUpToPowerOf2(count), MaxSegmentLength);
}
}
// Initialize the segment and add all of the data to it.
- _tail = _head = new Segment(length);
+ _tail = _head = new ConcurrentQueueSegment<T>(length);
foreach (T item in collection)
{
Enqueue(item);
@@ -137,31 +99,122 @@ namespace System.Collections.Concurrent
}
/// <summary>
- /// Initializes a new instance of the <see cref="LowLevelConcurrentQueue{T}"/> class that contains elements copied
+ /// Initializes a new instance of the <see cref="ConcurrentQueue{T}"/> class that contains elements copied
/// from the specified collection.
/// </summary>
/// <param name="collection">
- /// The collection whose elements are copied to the new <see cref="LowLevelConcurrentQueue{T}"/>.
+ /// The collection whose elements are copied to the new <see cref="ConcurrentQueue{T}"/>.
/// </param>
/// <exception cref="System.ArgumentNullException">The <paramref name="collection"/> argument is null.</exception>
- public LowLevelConcurrentQueue(IEnumerable<T> collection)
+ public ConcurrentQueue(IEnumerable<T> collection)
{
if (collection == null)
{
- throw new ArgumentNullException(nameof(collection));
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
}
InitializeFromCollection(collection);
}
+ /// <summary>
+ /// Copies the elements of the <see cref="ICollection"/> to an <see
+ /// cref="Array"/>, starting at a particular <see cref="Array"/> index.
+ /// </summary>
+ /// <param name="array">
+ /// The one-dimensional <see cref="Array">Array</see> that is the destination of the
+ /// elements copied from the <see cref="ConcurrentQueue{T}"/>. <paramref name="array"/> must have
+ /// zero-based indexing.
+ /// </param>
+ /// <param name="index">The zero-based index in <paramref name="array"/> at which copying begins.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is a null reference (Nothing in
+ /// Visual Basic).</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than
+ /// zero.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="array"/> is multidimensional. -or-
+ /// <paramref name="array"/> does not have zero-based indexing. -or-
+ /// <paramref name="index"/> is equal to or greater than the length of the <paramref name="array"/>
+ /// -or- The number of elements in the source <see cref="ICollection"/> is
+ /// greater than the available space from <paramref name="index"/> to the end of the destination
+ /// <paramref name="array"/>. -or- The type of the source <see
+ /// cref="ICollection"/> cannot be cast automatically to the type of the
+ /// destination <paramref name="array"/>.
+ /// </exception>
+ void ICollection.CopyTo(Array array, int index)
+ {
+ // Special-case when the Array is actually a T[], taking a faster path
+ T[] szArray = array as T[];
+ if (szArray != null)
+ {
+ CopyTo(szArray, index);
+ return;
+ }
+
+ // Validate arguments.
+ if (array == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ // Otherwise, fall back to the slower path that first copies the contents
+ // to an array, and then uses that array's non-generic CopyTo to do the copy.
+ ToArray().CopyTo(array, index);
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether access to the <see cref="ICollection"/> is
+ /// synchronized with the SyncRoot.
+ /// </summary>
+ /// <value>true if access to the <see cref="ICollection"/> is synchronized
+ /// with the SyncRoot; otherwise, false. For <see cref="ConcurrentQueue{T}"/>, this property always
+ /// returns false.</value>
+ bool ICollection.IsSynchronized => false; // always false, as true implies synchronization via SyncRoot
+
+ /// <summary>
+ /// Gets an object that can be used to synchronize access to the <see
+ /// cref="ICollection"/>. This property is not supported.
+ /// </summary>
+ /// <exception cref="NotSupportedException">The SyncRoot property is not supported.</exception>
+ object ICollection.SyncRoot { get { ThrowHelper.ThrowNotSupportedException(ExceptionResource.ConcurrentCollection_SyncRoot_NotSupported); return default; } }
+
/// <summary>Returns an enumerator that iterates through a collection.</summary>
/// <returns>An <see cref="IEnumerator"/> that can be used to iterate through the collection.</returns>
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<T>)this).GetEnumerator();
/// <summary>
- /// Gets a value that indicates whether the <see cref="LowLevelConcurrentQueue{T}"/> is empty.
+ /// Attempts to add an object to the <see cref="Concurrent.IProducerConsumerCollection{T}"/>.
+ /// </summary>
+ /// <param name="item">The object to add to the <see
+ /// cref="Concurrent.IProducerConsumerCollection{T}"/>. The value can be a null
+ /// reference (Nothing in Visual Basic) for reference types.
+ /// </param>
+ /// <returns>true if the object was added successfully; otherwise, false.</returns>
+ /// <remarks>For <see cref="ConcurrentQueue{T}"/>, this operation will always add the object to the
+ /// end of the <see cref="ConcurrentQueue{T}"/>
+ /// and return true.</remarks>
+ bool IProducerConsumerCollection<T>.TryAdd(T item)
+ {
+ Enqueue(item);
+ return true;
+ }
+
+ /// <summary>
+ /// Attempts to remove and return an object from the <see cref="Concurrent.IProducerConsumerCollection{T}"/>.
+ /// </summary>
+ /// <param name="item">
+ /// When this method returns, if the operation was successful, <paramref name="item"/> contains the
+ /// object removed. If no object was available to be removed, the value is unspecified.
+ /// </param>
+ /// <returns>true if an element was removed and returned successfully; otherwise, false.</returns>
+ /// <remarks>For <see cref="ConcurrentQueue{T}"/>, this operation will attempt to remove the object
+ /// from the beginning of the <see cref="ConcurrentQueue{T}"/>.
+ /// </remarks>
+ bool IProducerConsumerCollection<T>.TryTake(out T item) => TryDequeue(out item);
+
+ /// <summary>
+ /// Gets a value that indicates whether the <see cref="ConcurrentQueue{T}"/> is empty.
/// </summary>
- /// <value>true if the <see cref="LowLevelConcurrentQueue{T}"/> is empty; otherwise, false.</value>
+ /// <value>true if the <see cref="ConcurrentQueue{T}"/> is empty; otherwise, false.</value>
/// <remarks>
/// For determining whether the collection contains any items, use of this property is recommended
/// rather than retrieving the number of items from the <see cref="Count"/> property and comparing it
@@ -181,12 +234,12 @@ namespace System.Collections.Concurrent
}
}
- /// <summary>Copies the elements stored in the <see cref="LowLevelConcurrentQueue{T}"/> to a new array.</summary>
- /// <returns>A new array containing a snapshot of elements copied from the <see cref="LowLevelConcurrentQueue{T}"/>.</returns>
+ /// <summary>Copies the elements stored in the <see cref="ConcurrentQueue{T}"/> to a new array.</summary>
+ /// <returns>A new array containing a snapshot of elements copied from the <see cref="ConcurrentQueue{T}"/>.</returns>
public T[] ToArray()
{
// Snap the current contents for enumeration.
- Segment head, tail;
+ ConcurrentQueueSegment<T> head, tail;
int headHead, tailTail;
SnapForObservation(out head, out headHead, out tail, out tailTail);
@@ -211,9 +264,9 @@ namespace System.Collections.Concurrent
}
/// <summary>
- /// Gets the number of elements contained in the <see cref="LowLevelConcurrentQueue{T}"/>.
+ /// Gets the number of elements contained in the <see cref="ConcurrentQueue{T}"/>.
/// </summary>
- /// <value>The number of elements contained in the <see cref="LowLevelConcurrentQueue{T}"/>.</value>
+ /// <value>The number of elements contained in the <see cref="ConcurrentQueue{T}"/>.</value>
/// <remarks>
/// For determining whether the collection contains any items, use of the <see cref="IsEmpty"/>
/// property is recommended rather than retrieving the number of items from the <see cref="Count"/>
@@ -223,26 +276,24 @@ namespace System.Collections.Concurrent
{
get
{
- Segment head, tail;
- int headHead, headTail, tailHead, tailTail;
var spinner = new SpinWait();
while (true)
{
// Capture the head and tail, as well as the head's head and tail.
- head = _head;
- tail = _tail;
- headHead = Volatile.Read(ref head._headAndTail.Head);
- headTail = Volatile.Read(ref head._headAndTail.Tail);
+ ConcurrentQueueSegment<T> head = _head;
+ ConcurrentQueueSegment<T> tail = _tail;
+ int headHead = Volatile.Read(ref head._headAndTail.Head);
+ int headTail = Volatile.Read(ref head._headAndTail.Tail);
if (head == tail)
{
- // There was a single segment in the queue. If the captured
- // values still (or again) represent reality, return the segment's
- // count. A single segment should be the most common case once the
- // queue's size has stabilized after segments have grown to
- // the point where growing is no longer needed.
+ // There was a single segment in the queue. If the captured segments still
+ // match, then we can trust the values to compute the segment's count. (It's
+ // theoretically possible the values could have looped around and still exactly match,
+ // but that would required at least ~4 billion elements to have been enqueued and
+ // dequeued between the reads.)
if (head == _head &&
- head == _tail &&
+ tail == _tail &&
headHead == Volatile.Read(ref head._headAndTail.Head) &&
headTail == Volatile.Read(ref head._headAndTail.Tail))
{
@@ -251,11 +302,10 @@ namespace System.Collections.Concurrent
}
else if (head._nextSegment == tail)
{
- // There were two segments in the queue. Get the positions
- // from the tail, and if the captured values still (or again) match
- // reality, return the sum of the counts from both segments.
- tailHead = Volatile.Read(ref tail._headAndTail.Head);
- tailTail = Volatile.Read(ref tail._headAndTail.Tail);
+ // There were two segments in the queue. Get the positions from the tail, and as above,
+ // if the captured values match the previous reads, return the sum of the counts from both segments.
+ int tailHead = Volatile.Read(ref tail._headAndTail.Head);
+ int tailTail = Volatile.Read(ref tail._headAndTail.Tail);
if (head == _head &&
tail == _tail &&
headHead == Volatile.Read(ref head._headAndTail.Head) &&
@@ -263,17 +313,52 @@ namespace System.Collections.Concurrent
tailHead == Volatile.Read(ref tail._headAndTail.Head) &&
tailTail == Volatile.Read(ref tail._headAndTail.Tail))
{
- // We got stable values, so we can just compute the sizes based on those
- // values and return the sum of the counts of the segments.
return GetCount(head, headHead, headTail) + GetCount(tail, tailHead, tailTail);
}
}
else
{
- // There were more than two segments. Take the slower path, where we freeze the
- // queue and then count the now stable segments.
- SnapForObservation(out head, out headHead, out tail, out tailTail);
- return unchecked((int)GetCount(head, headHead, tail, tailTail));
+ // There were more than two segments in the queue. Fall back to taking the cross-segment lock,
+ // which will ensure that the head and tail segments we read are stable (since the lock is needed to change them);
+ // for the two-segment case above, we can simply rely on subsequent comparisons, but for the two+ case, we need
+ // to be able to trust the internal segments between the head and tail.
+ lock (_crossSegmentLock)
+ {
+ // Now that we hold the lock, re-read the previously captured head and tail segments and head positions.
+ // If either has changed, start over.
+ if (head == _head && tail == _tail)
+ {
+ // Get the positions from the tail, and as above, if the captured values match the previous reads,
+ // we can use the values to compute the count of the head and tail segments.
+ int tailHead = Volatile.Read(ref tail._headAndTail.Head);
+ int tailTail = Volatile.Read(ref tail._headAndTail.Tail);
+ if (headHead == Volatile.Read(ref head._headAndTail.Head) &&
+ headTail == Volatile.Read(ref head._headAndTail.Tail) &&
+ tailHead == Volatile.Read(ref tail._headAndTail.Head) &&
+ tailTail == Volatile.Read(ref tail._headAndTail.Tail))
+ {
+ // We got stable values for the head and tail segments, so we can just compute the sizes
+ // based on those and add them. Note that this and the below additions to count may overflow: previous
+ // implementations allowed that, so we don't check, either, and it is theoretically possible for the
+ // queue to store more than int.MaxValue items.
+ int count = GetCount(head, headHead, headTail) + GetCount(tail, tailHead, tailTail);
+
+ // Now add the counts for each internal segment. Since there were segments before these,
+ // for counting purposes we consider them to start at the 0th element, and since there is at
+ // least one segment after each, each was frozen, so we can count until each's frozen tail.
+ // With the cross-segment lock held, we're guaranteed that all of these internal segments are
+ // consistent, as the head and tail segment can't be changed while we're holding the lock, and
+ // dequeueing and enqueueing can only be done from the head and tail segments, which these aren't.
+ for (ConcurrentQueueSegment<T> s = head._nextSegment; s != tail; s = s._nextSegment)
+ {
+ Debug.Assert(s._frozenForEnqueues, "Internal segment must be frozen as there's a following segment.");
+ count += s._headAndTail.Tail - s.FreezeOffset;
+ }
+
+ return count;
+ }
+ }
+ }
}
// We raced with enqueues/dequeues and captured an inconsistent picture of the queue.
@@ -284,7 +369,7 @@ namespace System.Collections.Concurrent
}
/// <summary>Computes the number of items in a segment based on a fixed head and tail in that segment.</summary>
- private static int GetCount(Segment s, int head, int tail)
+ private static int GetCount(ConcurrentQueueSegment<T> s, int head, int tail)
{
if (head != tail && head != tail - s.FreezeOffset)
{
@@ -296,7 +381,7 @@ namespace System.Collections.Concurrent
}
/// <summary>Gets the number of items in snapped region.</summary>
- private static long GetCount(Segment head, int headHead, Segment tail, int tailTail)
+ private static long GetCount(ConcurrentQueueSegment<T> head, int headHead, ConcurrentQueueSegment<T> tail, int tailTail)
{
// All of the segments should have been both frozen for enqueues and preserved for observation.
// Validate that here for head and tail; we'll validate it for intermediate segments later.
@@ -332,7 +417,7 @@ namespace System.Collections.Concurrent
// Since there were segments before these, for our purposes we consider them to start at
// the 0th element, and since there is at least one segment after each, each was frozen
// by the time we snapped it, so we can iterate until each's frozen tail.
- for (Segment s = head._nextSegment; s != tail; s = s._nextSegment)
+ for (ConcurrentQueueSegment<T> s = head._nextSegment; s != tail; s = s._nextSegment)
{
Debug.Assert(s._preservedForObservation);
Debug.Assert(s._frozenForEnqueues);
@@ -351,12 +436,12 @@ namespace System.Collections.Concurrent
}
/// <summary>
- /// Copies the <see cref="LowLevelConcurrentQueue{T}"/> elements to an existing one-dimensional <see
+ /// Copies the <see cref="ConcurrentQueue{T}"/> elements to an existing one-dimensional <see
/// cref="Array">Array</see>, starting at the specified array index.
/// </summary>
/// <param name="array">The one-dimensional <see cref="Array">Array</see> that is the
/// destination of the elements copied from the
- /// <see cref="LowLevelConcurrentQueue{T}"/>. The <see cref="Array">Array</see> must have zero-based
+ /// <see cref="ConcurrentQueue{T}"/>. The <see cref="Array">Array</see> must have zero-based
/// indexing.</param>
/// <param name="index">The zero-based index in <paramref name="array"/> at which copying
/// begins.</param>
@@ -366,7 +451,7 @@ namespace System.Collections.Concurrent
/// zero.</exception>
/// <exception cref="ArgumentException"><paramref name="index"/> is equal to or greater than the
/// length of the <paramref name="array"/>
- /// -or- The number of elements in the source <see cref="LowLevelConcurrentQueue{T}"/> is greater than the
+ /// -or- The number of elements in the source <see cref="ConcurrentQueue{T}"/> is greater than the
/// available space from <paramref name="index"/> to the end of the destination <paramref
/// name="array"/>.
/// </exception>
@@ -374,15 +459,15 @@ namespace System.Collections.Concurrent
{
if (array == null)
{
- throw new ArgumentNullException(nameof(array));
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
}
if (index < 0)
{
- throw new ArgumentOutOfRangeException(nameof(index));
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index);
}
// Snap for enumeration
- Segment head, tail;
+ ConcurrentQueueSegment<T> head, tail;
int headHead, tailTail;
SnapForObservation(out head, out headHead, out tail, out tailTail);
@@ -390,7 +475,7 @@ namespace System.Collections.Concurrent
long count = GetCount(head, headHead, tail, tailTail);
if (index > array.Length - count)
{
- throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall);
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
}
// Copy the items to the target array
@@ -405,9 +490,9 @@ namespace System.Collections.Concurrent
Debug.Assert(count == i - index);
}
- /// <summary>Returns an enumerator that iterates through the <see cref="LowLevelConcurrentQueue{T}"/>.</summary>
+ /// <summary>Returns an enumerator that iterates through the <see cref="ConcurrentQueue{T}"/>.</summary>
/// <returns>An enumerator for the contents of the <see
- /// cref="LowLevelConcurrentQueue{T}"/>.</returns>
+ /// cref="ConcurrentQueue{T}"/>.</returns>
/// <remarks>
/// The enumeration represents a moment-in-time snapshot of the contents
/// of the queue. It does not reflect any updates to the collection after
@@ -416,7 +501,7 @@ namespace System.Collections.Concurrent
/// </remarks>
public IEnumerator<T> GetEnumerator()
{
- Segment head, tail;
+ ConcurrentQueueSegment<T> head, tail;
int headHead, tailTail;
SnapForObservation(out head, out headHead, out tail, out tailTail);
return Enumerate(head, headHead, tail, tailTail);
@@ -427,9 +512,9 @@ namespace System.Collections.Concurrent
/// After this call returns, the specified region can be enumerated any number
/// of times and will not change.
/// </summary>
- private void SnapForObservation(out Segment head, out int headHead, out Segment tail, out int tailTail)
+ private void SnapForObservation(out ConcurrentQueueSegment<T> head, out int headHead, out ConcurrentQueueSegment<T> tail, out int tailTail)
{
- using (LockHolder.Hold(_crossSegmentLock)) // _head and _tail may only change while the lock is held.
+ lock (_crossSegmentLock) // _head and _tail may only change while the lock is held.
{
// Snap the head and tail
head = _head;
@@ -440,7 +525,7 @@ namespace System.Collections.Concurrent
// Mark them and all segments in between as preserving, and ensure no additional items
// can be added to the tail.
- for (Segment s = head; ; s = s._nextSegment)
+ for (ConcurrentQueueSegment<T> s = head; ; s = s._nextSegment)
{
s._preservedForObservation = true;
if (s == tail) break;
@@ -457,7 +542,7 @@ namespace System.Collections.Concurrent
}
/// <summary>Gets the item stored in the <paramref name="i"/>th entry in <paramref name="segment"/>.</summary>
- private T GetItemWhenAvailable(Segment segment, int i)
+ private T GetItemWhenAvailable(ConcurrentQueueSegment<T> segment, int i)
{
Debug.Assert(segment._preservedForObservation);
@@ -479,7 +564,7 @@ namespace System.Collections.Concurrent
return segment._slots[i].Item;
}
- private IEnumerator<T> Enumerate(Segment head, int headHead, Segment tail, int tailTail)
+ private IEnumerator<T> Enumerate(ConcurrentQueueSegment<T> head, int headHead, ConcurrentQueueSegment<T> tail, int tailTail)
{
Debug.Assert(head._preservedForObservation);
Debug.Assert(head._frozenForEnqueues);
@@ -512,7 +597,7 @@ namespace System.Collections.Concurrent
{
// Each segment between head and tail, not including head and tail. Since there were
// segments before these, for our purposes we consider it to start at the 0th element.
- for (Segment s = head._nextSegment; s != tail; s = s._nextSegment)
+ for (ConcurrentQueueSegment<T> s = head._nextSegment; s != tail; s = s._nextSegment)
{
Debug.Assert(s._preservedForObservation, "Would have had to been preserved as a segment part of enumeration");
Debug.Assert(s._frozenForEnqueues, "Would have had to be frozen for enqueues as it's intermediate");
@@ -534,21 +619,9 @@ namespace System.Collections.Concurrent
}
}
- /// <summary>Round the specified value up to the next power of 2, if it isn't one already.</summary>
- private static int RoundUpToPowerOf2(int i)
- {
- --i;
- i |= i >> 1;
- i |= i >> 2;
- i |= i >> 4;
- i |= i >> 8;
- i |= i >> 16;
- return i + 1;
- }
-
- /// <summary>Adds an object to the end of the <see cref="LowLevelConcurrentQueue{T}"/>.</summary>
+ /// <summary>Adds an object to the end of the <see cref="ConcurrentQueue{T}"/>.</summary>
/// <param name="item">
- /// The object to add to the end of the <see cref="LowLevelConcurrentQueue{T}"/>.
+ /// The object to add to the end of the <see cref="ConcurrentQueue{T}"/>.
/// The value can be a null reference (Nothing in Visual Basic) for reference types.
/// </param>
public void Enqueue(T item)
@@ -567,7 +640,7 @@ namespace System.Collections.Concurrent
{
while (true)
{
- Segment tail = _tail;
+ ConcurrentQueueSegment<T> tail = _tail;
// Try to append to the existing tail.
if (tail.TryEnqueue(item))
@@ -578,7 +651,7 @@ namespace System.Collections.Concurrent
// If we were unsuccessful, take the lock so that we can compare and manipulate
// the tail. Assuming another enqueuer hasn't already added a new segment,
// do so, then loop around to try enqueueing again.
- using (LockHolder.Hold(_crossSegmentLock)) // _head and _tail may only change while the lock is held.
+ lock (_crossSegmentLock)
{
if (tail == _tail)
{
@@ -595,7 +668,7 @@ namespace System.Collections.Concurrent
// this will help to avoid wasted memory, and if they're not, we'll
// relatively quickly grow again to a larger size.
int nextSize = tail._preservedForObservation ? InitialSegmentLength : Math.Min(tail.Capacity * 2, MaxSegmentLength);
- var newTail = new Segment(nextSize);
+ var newTail = new ConcurrentQueueSegment<T>(nextSize);
// Hook up the new tail.
tail._nextSegment = newTail;
@@ -607,7 +680,7 @@ namespace System.Collections.Concurrent
/// <summary>
/// Attempts to remove and return the object at the beginning of the <see
- /// cref="LowLevelConcurrentQueue{T}"/>.
+ /// cref="ConcurrentQueue{T}"/>.
/// </summary>
/// <param name="result">
/// When this method returns, if the operation was successful, <paramref name="result"/> contains the
@@ -615,7 +688,7 @@ namespace System.Collections.Concurrent
/// </param>
/// <returns>
/// true if an element was removed and returned from the beginning of the
- /// <see cref="LowLevelConcurrentQueue{T}"/> successfully; otherwise, false.
+ /// <see cref="ConcurrentQueue{T}"/> successfully; otherwise, false.
/// </returns>
public bool TryDequeue(out T result) =>
_head.TryDequeue(out result) || // fast-path that operates just on the head segment
@@ -627,7 +700,7 @@ namespace System.Collections.Concurrent
while (true)
{
// Get the current head
- Segment head = _head;
+ ConcurrentQueueSegment<T> head = _head;
// Try to take. If we're successful, we're done.
if (head.TryDequeue(out item))
@@ -640,7 +713,7 @@ namespace System.Collections.Concurrent
// check and this check, another item could have arrived).
if (head._nextSegment == null)
{
- item = default(T);
+ item = default;
return false;
}
@@ -657,7 +730,7 @@ namespace System.Collections.Concurrent
// This segment is frozen (nothing more can be added) and empty (nothing is in it).
// Update head to point to the next segment in the list, assuming no one's beat us to it.
- using (LockHolder.Hold(_crossSegmentLock)) // _head and _tail may only change while the lock is held.
+ lock (_crossSegmentLock)
{
if (head == _head)
{
@@ -668,12 +741,12 @@ namespace System.Collections.Concurrent
}
/// <summary>
- /// Attempts to return an object from the beginning of the <see cref="LowLevelConcurrentQueue{T}"/>
+ /// Attempts to return an object from the beginning of the <see cref="ConcurrentQueue{T}"/>
/// without removing it.
/// </summary>
/// <param name="result">
/// When this method returns, <paramref name="result"/> contains an object from
- /// the beginning of the <see cref="Concurrent.LowLevelConcurrentQueue{T}"/> or default(T)
+ /// the beginning of the <see cref="Concurrent.ConcurrentQueue{T}"/> or default(T)
/// if the operation failed.
/// </param>
/// <returns>true if and object was returned successfully; otherwise, false.</returns>
@@ -685,19 +758,19 @@ namespace System.Collections.Concurrent
/// <summary>Attempts to retrieve the value for the first element in the queue.</summary>
/// <param name="result">The value of the first element, if found.</param>
- /// <param name="resultUsed">true if the result is neede; otherwise false if only the true/false outcome is needed.</param>
+ /// <param name="resultUsed">true if the result is needed; otherwise false if only the true/false outcome is needed.</param>
/// <returns>true if an element was found; otherwise, false.</returns>
private bool TryPeek(out T result, bool resultUsed)
{
// Starting with the head segment, look through all of the segments
// for the first one we can find that's not empty.
- Segment s = _head;
+ ConcurrentQueueSegment<T> s = _head;
while (true)
{
// Grab the next segment from this one, before we peek.
// This is to be able to see whether the value has changed
// during the peek operation.
- Segment next = Volatile.Read(ref s._nextSegment);
+ ConcurrentQueueSegment<T> next = Volatile.Read(ref s._nextSegment);
// Peek at the segment. If we find an element, we're done.
if (s.TryPeek(out result, resultUsed))
@@ -734,16 +807,16 @@ namespace System.Collections.Concurrent
// and we'll traverse to that segment.
}
- result = default(T);
+ result = default;
return false;
}
/// <summary>
- /// Removes all objects from the <see cref="LowLevelConcurrentQueue{T}"/>.
+ /// Removes all objects from the <see cref="ConcurrentQueue{T}"/>.
/// </summary>
public void Clear()
{
- using (LockHolder.Hold(_crossSegmentLock)) // _head and _tail may only change while the lock is held.
+ lock (_crossSegmentLock)
{
// Simply substitute a new segment for the existing head/tail,
// as is done in the constructor. Operations currently in flight
@@ -754,315 +827,8 @@ namespace System.Collections.Concurrent
// be dropped, we first freeze it; that'll force enqueuers to take
// this lock to synchronize and see the new tail.
_tail.EnsureFrozenForEnqueues();
- _tail = _head = new Segment(InitialSegmentLength);
- }
- }
-
- /// <summary>
- /// Provides a multi-producer, multi-consumer thread-safe bounded segment. When the queue is full,
- /// enqueues fail and return false. When the queue is empty, dequeues fail and return null.
- /// These segments are linked together to form the unbounded <see cref="LowLevelConcurrentQueue{T}"/>.
- /// </summary>
- [DebuggerDisplay("Capacity = {Capacity}")]
- private sealed class Segment
- {
- // Segment design is inspired by the algorithm outlined at:
- // http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue
-
- /// <summary>The array of items in this queue. Each slot contains the item in that slot and its "sequence number".</summary>
- internal readonly Slot[] _slots;
- /// <summary>Mask for quickly accessing a position within the queue's array.</summary>
- internal readonly int _slotsMask;
- /// <summary>The head and tail positions, with padding to help avoid false sharing contention.</summary>
- /// <remarks>Dequeueing happens from the head, enqueueing happens at the tail.</remarks>
- internal PaddedHeadAndTail _headAndTail; // mutable struct: do not make this readonly
-
- /// <summary>Indicates whether the segment has been marked such that dequeues don't overwrite the removed data.</summary>
- internal bool _preservedForObservation;
- /// <summary>Indicates whether the segment has been marked such that no additional items may be enqueued.</summary>
- internal bool _frozenForEnqueues;
- /// <summary>The segment following this one in the queue, or null if this segment is the last in the queue.</summary>
- internal Segment _nextSegment;
-
- /// <summary>Creates the segment.</summary>
- /// <param name="boundedLength">
- /// The maximum number of elements the segment can contain. Must be a power of 2.
- /// </param>
- public Segment(int boundedLength)
- {
- // Validate the length
- Debug.Assert(boundedLength >= 2, $"Must be >= 2, got {boundedLength}");
- Debug.Assert((boundedLength & (boundedLength - 1)) == 0, $"Must be a power of 2, got {boundedLength}");
-
- // Initialize the slots and the mask. The mask is used as a way of quickly doing "% _slots.Length",
- // instead letting us do "& _slotsMask".
- _slots = new Slot[boundedLength];
- _slotsMask = boundedLength - 1;
-
- // Initialize the sequence number for each slot. The sequence number provides a ticket that
- // allows dequeuers to know whether they can dequeue and enqueuers to know whether they can
- // enqueue. An enqueuer at position N can enqueue when the sequence number is N, and a dequeuer
- // for position N can dequeue when the sequence number is N + 1. When an enqueuer is done writing
- // at position N, it sets the sequence number to N so that a dequeuer will be able to dequeue,
- // and when a dequeuer is done dequeueing at position N, it sets the sequence number to N + _slots.Length,
- // so that when an enqueuer loops around the slots, it'll find that the sequence number at
- // position N is N. This also means that when an enqueuer finds that at position N the sequence
- // number is < N, there is still a value in that slot, i.e. the segment is full, and when a
- // dequeuer finds that the value in a slot is < N + 1, there is nothing currently available to
- // dequeue. (It is possible for multiple enqueuers to enqueue concurrently, writing into
- // subsequent slots, and to have the first enqueuer take longer, so that the slots for 1, 2, 3, etc.
- // may have values, but the 0th slot may still be being filled... in that case, TryDequeue will
- // return false.)
- for (int i = 0; i < _slots.Length; i++)
- {
- _slots[i].SequenceNumber = i;
- }
- }
-
- /// <summary>Gets the number of elements this segment can store.</summary>
- internal int Capacity => _slots.Length;
-
- /// <summary>Gets the "freeze offset" for this segment.</summary>
- internal int FreezeOffset => _slots.Length * 2;
-
- /// <summary>
- /// Ensures that the segment will not accept any subsequent enqueues that aren't already underway.
- /// </summary>
- /// <remarks>
- /// When we mark a segment as being frozen for additional enqueues,
- /// we set the <see cref="_frozenForEnqueues"/> bool, but that's mostly
- /// as a small helper to avoid marking it twice. The real marking comes
- /// by modifying the Tail for the segment, increasing it by this
- /// <see cref="FreezeOffset"/>. This effectively knocks it off the
- /// sequence expected by future enqueuers, such that any additional enqueuer
- /// will be unable to enqueue due to it not lining up with the expected
- /// sequence numbers. This value is chosen specially so that Tail will grow
- /// to a value that maps to the same slot but that won't be confused with
- /// any other enqueue/dequeue sequence number.
- /// </remarks>
- internal void EnsureFrozenForEnqueues() // must only be called while queue's segment lock is held
- {
- if (!_frozenForEnqueues) // flag used to ensure we don't increase the Tail more than once if frozen more than once
- {
- _frozenForEnqueues = true;
-
- // Increase the tail by FreezeOffset, spinning until we're successful in doing so.
- var spinner = new SpinWait();
- while (true)
- {
- int tail = Volatile.Read(ref _headAndTail.Tail);
- if (Interlocked.CompareExchange(ref _headAndTail.Tail, tail + FreezeOffset, tail) == tail)
- {
- break;
- }
- spinner.SpinOnce();
- }
- }
- }
-
- /// <summary>Tries to dequeue an element from the queue.</summary>
- public bool TryDequeue(out T item)
- {
- // Loop in case of contention...
- var spinner = new SpinWait();
- while (true)
- {
- // Get the head at which to try to dequeue.
- int currentHead = Volatile.Read(ref _headAndTail.Head);
- int slotsIndex = currentHead & _slotsMask;
-
- // Read the sequence number for the head position.
- int sequenceNumber = Volatile.Read(ref _slots[slotsIndex].SequenceNumber);
-
- // We can dequeue from this slot if it's been filled by an enqueuer, which
- // would have left the sequence number at pos+1.
- int diff = sequenceNumber - (currentHead + 1);
- if (diff == 0)
- {
- // We may be racing with other dequeuers. Try to reserve the slot by incrementing
- // the head. Once we've done that, no one else will be able to read from this slot,
- // and no enqueuer will be able to read from this slot until we've written the new
- // sequence number. WARNING: The next few lines are not reliable on a runtime that
- // supports thread aborts. If a thread abort were to sneak in after the CompareExchange
- // but before the Volatile.Write, enqueuers trying to enqueue into this slot would
- // spin indefinitely. If this implementation is ever used on such a platform, this
- // if block should be wrapped in a finally / prepared region.
- if (Interlocked.CompareExchange(ref _headAndTail.Head, currentHead + 1, currentHead) == currentHead)
- {
- // Successfully reserved the slot. Note that after the above CompareExchange, other threads
- // trying to dequeue from this slot will end up spinning until we do the subsequent Write.
- item = _slots[slotsIndex].Item;
- if (!Volatile.Read(ref _preservedForObservation))
- {
- // If we're preserving, though, we don't zero out the slot, as we need it for
- // enumerations, peeking, ToArray, etc. And we don't update the sequence number,
- // so that an enqueuer will see it as full and be forced to move to a new segment.
- _slots[slotsIndex].Item = default(T);
- Volatile.Write(ref _slots[slotsIndex].SequenceNumber, currentHead + _slots.Length);
- }
- return true;
- }
- }
- else if (diff < 0)
- {
- // The sequence number was less than what we needed, which means this slot doesn't
- // yet contain a value we can dequeue, i.e. the segment is empty. Technically it's
- // possible that multiple enqueuers could have written concurrently, with those
- // getting later slots actually finishing first, so there could be elements after
- // this one that are available, but we need to dequeue in order. So before declaring
- // failure and that the segment is empty, we check the tail to see if we're actually
- // empty or if we're just waiting for items in flight or after this one to become available.
- bool frozen = _frozenForEnqueues;
- int currentTail = Volatile.Read(ref _headAndTail.Tail);
- if (currentTail - currentHead <= 0 || (frozen && (currentTail - FreezeOffset - currentHead <= 0)))
- {
- item = default(T);
- return false;
- }
-
- // It's possible it could have become frozen after we checked _frozenForEnqueues
- // and before reading the tail. That's ok: in that rare race condition, we just
- // loop around again.
- }
-
- // Lost a race. Spin a bit, then try again.
- spinner.SpinOnce();
- }
- }
-
- /// <summary>Tries to peek at an element from the queue, without removing it.</summary>
- public bool TryPeek(out T result, bool resultUsed)
- {
- if (resultUsed)
- {
- // In order to ensure we don't get a torn read on the value, we mark the segment
- // as preserving for observation. Additional items can still be enqueued to this
- // segment, but no space will be freed during dequeues, such that the segment will
- // no longer be reusable.
- _preservedForObservation = true;
- Interlocked.MemoryBarrier();
- }
-
- // Loop in case of contention...
- var spinner = new SpinWait();
- while (true)
- {
- // Get the head at which to try to peek.
- int currentHead = Volatile.Read(ref _headAndTail.Head);
- int slotsIndex = currentHead & _slotsMask;
-
- // Read the sequence number for the head position.
- int sequenceNumber = Volatile.Read(ref _slots[slotsIndex].SequenceNumber);
-
- // We can peek from this slot if it's been filled by an enqueuer, which
- // would have left the sequence number at pos+1.
- int diff = sequenceNumber - (currentHead + 1);
- if (diff == 0)
- {
- result = resultUsed ? _slots[slotsIndex].Item : default(T);
- return true;
- }
- else if (diff < 0)
- {
- // The sequence number was less than what we needed, which means this slot doesn't
- // yet contain a value we can peek, i.e. the segment is empty. Technically it's
- // possible that multiple enqueuers could have written concurrently, with those
- // getting later slots actually finishing first, so there could be elements after
- // this one that are available, but we need to peek in order. So before declaring
- // failure and that the segment is empty, we check the tail to see if we're actually
- // empty or if we're just waiting for items in flight or after this one to become available.
- bool frozen = _frozenForEnqueues;
- int currentTail = Volatile.Read(ref _headAndTail.Tail);
- if (currentTail - currentHead <= 0 || (frozen && (currentTail - FreezeOffset - currentHead <= 0)))
- {
- result = default(T);
- return false;
- }
-
- // It's possible it could have become frozen after we checked _frozenForEnqueues
- // and before reading the tail. That's ok: in that rare race condition, we just
- // loop around again.
- }
-
- // Lost a race. Spin a bit, then try again.
- spinner.SpinOnce();
- }
- }
-
- /// <summary>
- /// Attempts to enqueue the item. If successful, the item will be stored
- /// in the queue and true will be returned; otherwise, the item won't be stored, and false
- /// will be returned.
- /// </summary>
- public bool TryEnqueue(T item)
- {
- // Loop in case of contention...
- var spinner = new SpinWait();
- while (true)
- {
- // Get the tail at which to try to return.
- int currentTail = Volatile.Read(ref _headAndTail.Tail);
- int slotsIndex = currentTail & _slotsMask;
-
- // Read the sequence number for the tail position.
- int sequenceNumber = Volatile.Read(ref _slots[slotsIndex].SequenceNumber);
-
- // The slot is empty and ready for us to enqueue into it if its sequence
- // number matches the slot.
- int diff = sequenceNumber - currentTail;
- if (diff == 0)
- {
- // We may be racing with other enqueuers. Try to reserve the slot by incrementing
- // the tail. Once we've done that, no one else will be able to write to this slot,
- // and no dequeuer will be able to read from this slot until we've written the new
- // sequence number. WARNING: The next few lines are not reliable on a runtime that
- // supports thread aborts. If a thread abort were to sneak in after the CompareExchange
- // but before the Volatile.Write, other threads will spin trying to access this slot.
- // If this implementation is ever used on such a platform, this if block should be
- // wrapped in a finally / prepared region.
- if (Interlocked.CompareExchange(ref _headAndTail.Tail, currentTail + 1, currentTail) == currentTail)
- {
- // Successfully reserved the slot. Note that after the above CompareExchange, other threads
- // trying to return will end up spinning until we do the subsequent Write.
- _slots[slotsIndex].Item = item;
- Volatile.Write(ref _slots[slotsIndex].SequenceNumber, currentTail + 1);
- return true;
- }
- }
- else if (diff < 0)
- {
- // The sequence number was less than what we needed, which means this slot still
- // contains a value, i.e. the segment is full. Technically it's possible that multiple
- // dequeuers could have read concurrently, with those getting later slots actually
- // finishing first, so there could be spaces after this one that are available, but
- // we need to enqueue in order.
- return false;
- }
-
- // Lost a race. Spin a bit, then try again.
- spinner.SpinOnce();
- }
- }
-
- /// <summary>Represents a slot in the queue.</summary>
- [StructLayout(LayoutKind.Auto)]
- [DebuggerDisplay("Item = {Item}, SequenceNumber = {SequenceNumber}")]
- internal struct Slot
- {
- /// <summary>The item.</summary>
- public T Item;
- /// <summary>The sequence number for this slot, used to synchronize between enqueuers and dequeuers.</summary>
- public int SequenceNumber;
+ _tail = _head = new ConcurrentQueueSegment<T>(InitialSegmentLength);
}
}
}
-
- /// <summary>Padded head and tail indices, to avoid false sharing between producers and consumers.</summary>
- [DebuggerDisplay("Head = {Head}, Tail = {Tail}")]
- [StructLayout(LayoutKind.Explicit, Size = 192)] // padding before/between/after fields based on typical cache line size of 64
- internal struct PaddedHeadAndTail
- {
- [FieldOffset(64)] public int Head;
- [FieldOffset(128)] public int Tail;
- }
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueueSegment.cs b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueueSegment.cs
new file mode 100644
index 000000000..12e92d0e0
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/ConcurrentQueueSegment.cs
@@ -0,0 +1,332 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+namespace System.Collections.Concurrent
+{
+ /// <summary>
+ /// Provides a multi-producer, multi-consumer thread-safe bounded segment. When the queue is full,
+ /// enqueues fail and return false. When the queue is empty, dequeues fail and return null.
+ /// These segments are linked together to form the unbounded <see cref="ConcurrentQueue{T}"/>.
+ /// </summary>
+ [DebuggerDisplay("Capacity = {Capacity}")]
+ internal sealed class ConcurrentQueueSegment<T>
+ {
+ // Segment design is inspired by the algorithm outlined at:
+ // http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue
+
+ /// <summary>The array of items in this queue. Each slot contains the item in that slot and its "sequence number".</summary>
+ internal readonly Slot[] _slots;
+ /// <summary>Mask for quickly accessing a position within the queue's array.</summary>
+ internal readonly int _slotsMask;
+ /// <summary>The head and tail positions, with padding to help avoid false sharing contention.</summary>
+ /// <remarks>Dequeuing happens from the head, enqueuing happens at the tail.</remarks>
+ internal PaddedHeadAndTail _headAndTail; // mutable struct: do not make this readonly
+
+ /// <summary>Indicates whether the segment has been marked such that dequeues don't overwrite the removed data.</summary>
+ internal bool _preservedForObservation;
+ /// <summary>Indicates whether the segment has been marked such that no additional items may be enqueued.</summary>
+ internal bool _frozenForEnqueues;
+#pragma warning disable 0649 // some builds don't assign to this field
+ /// <summary>The segment following this one in the queue, or null if this segment is the last in the queue.</summary>
+ internal ConcurrentQueueSegment<T> _nextSegment;
+#pragma warning restore 0649
+
+ /// <summary>Creates the segment.</summary>
+ /// <param name="boundedLength">
+ /// The maximum number of elements the segment can contain. Must be a power of 2.
+ /// </param>
+ internal ConcurrentQueueSegment(int boundedLength)
+ {
+ // Validate the length
+ Debug.Assert(boundedLength >= 2, $"Must be >= 2, got {boundedLength}");
+ Debug.Assert((boundedLength & (boundedLength - 1)) == 0, $"Must be a power of 2, got {boundedLength}");
+
+ // Initialize the slots and the mask. The mask is used as a way of quickly doing "% _slots.Length",
+ // instead letting us do "& _slotsMask".
+ _slots = new Slot[boundedLength];
+ _slotsMask = boundedLength - 1;
+
+ // Initialize the sequence number for each slot. The sequence number provides a ticket that
+ // allows dequeuers to know whether they can dequeue and enqueuers to know whether they can
+ // enqueue. An enqueuer at position N can enqueue when the sequence number is N, and a dequeuer
+ // for position N can dequeue when the sequence number is N + 1. When an enqueuer is done writing
+ // at position N, it sets the sequence number to N + 1 so that a dequeuer will be able to dequeue,
+ // and when a dequeuer is done dequeueing at position N, it sets the sequence number to N + _slots.Length,
+ // so that when an enqueuer loops around the slots, it'll find that the sequence number at
+ // position N is N. This also means that when an enqueuer finds that at position N the sequence
+ // number is < N, there is still a value in that slot, i.e. the segment is full, and when a
+ // dequeuer finds that the value in a slot is < N + 1, there is nothing currently available to
+ // dequeue. (It is possible for multiple enqueuers to enqueue concurrently, writing into
+ // subsequent slots, and to have the first enqueuer take longer, so that the slots for 1, 2, 3, etc.
+ // may have values, but the 0th slot may still be being filled... in that case, TryDequeue will
+ // return false.)
+ for (int i = 0; i < _slots.Length; i++)
+ {
+ _slots[i].SequenceNumber = i;
+ }
+ }
+
+ /// <summary>Round the specified value up to the next power of 2, if it isn't one already.</summary>
+ internal static int RoundUpToPowerOf2(int i)
+ {
+ // Based on https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
+ --i;
+ i |= i >> 1;
+ i |= i >> 2;
+ i |= i >> 4;
+ i |= i >> 8;
+ i |= i >> 16;
+ return i + 1;
+ }
+
+ /// <summary>Gets the number of elements this segment can store.</summary>
+ internal int Capacity => _slots.Length;
+
+ /// <summary>Gets the "freeze offset" for this segment.</summary>
+ internal int FreezeOffset => _slots.Length * 2;
+
+ /// <summary>
+ /// Ensures that the segment will not accept any subsequent enqueues that aren't already underway.
+ /// </summary>
+ /// <remarks>
+ /// When we mark a segment as being frozen for additional enqueues,
+ /// we set the <see cref="_frozenForEnqueues"/> bool, but that's mostly
+ /// as a small helper to avoid marking it twice. The real marking comes
+ /// by modifying the Tail for the segment, increasing it by this
+ /// <see cref="FreezeOffset"/>. This effectively knocks it off the
+ /// sequence expected by future enqueuers, such that any additional enqueuer
+ /// will be unable to enqueue due to it not lining up with the expected
+ /// sequence numbers. This value is chosen specially so that Tail will grow
+ /// to a value that maps to the same slot but that won't be confused with
+ /// any other enqueue/dequeue sequence number.
+ /// </remarks>
+ internal void EnsureFrozenForEnqueues() // must only be called while queue's segment lock is held
+ {
+ if (!_frozenForEnqueues) // flag used to ensure we don't increase the Tail more than once if frozen more than once
+ {
+ _frozenForEnqueues = true;
+
+ // Increase the tail by FreezeOffset, spinning until we're successful in doing so.
+ var spinner = new SpinWait();
+ while (true)
+ {
+ int tail = Volatile.Read(ref _headAndTail.Tail);
+ if (Interlocked.CompareExchange(ref _headAndTail.Tail, tail + FreezeOffset, tail) == tail)
+ {
+ break;
+ }
+ spinner.SpinOnce();
+ }
+ }
+ }
+
+ /// <summary>Tries to dequeue an element from the queue.</summary>
+ public bool TryDequeue(out T item)
+ {
+ // Loop in case of contention...
+ var spinner = new SpinWait();
+ while (true)
+ {
+ // Get the head at which to try to dequeue.
+ int currentHead = Volatile.Read(ref _headAndTail.Head);
+ int slotsIndex = currentHead & _slotsMask;
+
+ // Read the sequence number for the head position.
+ int sequenceNumber = Volatile.Read(ref _slots[slotsIndex].SequenceNumber);
+
+ // We can dequeue from this slot if it's been filled by an enqueuer, which
+ // would have left the sequence number at pos+1.
+ int diff = sequenceNumber - (currentHead + 1);
+ if (diff == 0)
+ {
+ // We may be racing with other dequeuers. Try to reserve the slot by incrementing
+ // the head. Once we've done that, no one else will be able to read from this slot,
+ // and no enqueuer will be able to read from this slot until we've written the new
+ // sequence number. WARNING: The next few lines are not reliable on a runtime that
+ // supports thread aborts. If a thread abort were to sneak in after the CompareExchange
+ // but before the Volatile.Write, enqueuers trying to enqueue into this slot would
+ // spin indefinitely. If this implementation is ever used on such a platform, this
+ // if block should be wrapped in a finally / prepared region.
+ if (Interlocked.CompareExchange(ref _headAndTail.Head, currentHead + 1, currentHead) == currentHead)
+ {
+ // Successfully reserved the slot. Note that after the above CompareExchange, other threads
+ // trying to dequeue from this slot will end up spinning until we do the subsequent Write.
+ item = _slots[slotsIndex].Item;
+ if (!Volatile.Read(ref _preservedForObservation))
+ {
+ // If we're preserving, though, we don't zero out the slot, as we need it for
+ // enumerations, peeking, ToArray, etc. And we don't update the sequence number,
+ // so that an enqueuer will see it as full and be forced to move to a new segment.
+ _slots[slotsIndex].Item = default(T);
+ Volatile.Write(ref _slots[slotsIndex].SequenceNumber, currentHead + _slots.Length);
+ }
+ return true;
+ }
+ }
+ else if (diff < 0)
+ {
+ // The sequence number was less than what we needed, which means this slot doesn't
+ // yet contain a value we can dequeue, i.e. the segment is empty. Technically it's
+ // possible that multiple enqueuers could have written concurrently, with those
+ // getting later slots actually finishing first, so there could be elements after
+ // this one that are available, but we need to dequeue in order. So before declaring
+ // failure and that the segment is empty, we check the tail to see if we're actually
+ // empty or if we're just waiting for items in flight or after this one to become available.
+ bool frozen = _frozenForEnqueues;
+ int currentTail = Volatile.Read(ref _headAndTail.Tail);
+ if (currentTail - currentHead <= 0 || (frozen && (currentTail - FreezeOffset - currentHead <= 0)))
+ {
+ item = default(T);
+ return false;
+ }
+
+ // It's possible it could have become frozen after we checked _frozenForEnqueues
+ // and before reading the tail. That's ok: in that rare race condition, we just
+ // loop around again.
+ }
+
+ // Lost a race. Spin a bit, then try again.
+ spinner.SpinOnce();
+ }
+ }
+
+ /// <summary>Tries to peek at an element from the queue, without removing it.</summary>
+ public bool TryPeek(out T result, bool resultUsed)
+ {
+ if (resultUsed)
+ {
+ // In order to ensure we don't get a torn read on the value, we mark the segment
+ // as preserving for observation. Additional items can still be enqueued to this
+ // segment, but no space will be freed during dequeues, such that the segment will
+ // no longer be reusable.
+ _preservedForObservation = true;
+ Interlocked.MemoryBarrier();
+ }
+
+ // Loop in case of contention...
+ var spinner = new SpinWait();
+ while (true)
+ {
+ // Get the head at which to try to peek.
+ int currentHead = Volatile.Read(ref _headAndTail.Head);
+ int slotsIndex = currentHead & _slotsMask;
+
+ // Read the sequence number for the head position.
+ int sequenceNumber = Volatile.Read(ref _slots[slotsIndex].SequenceNumber);
+
+ // We can peek from this slot if it's been filled by an enqueuer, which
+ // would have left the sequence number at pos+1.
+ int diff = sequenceNumber - (currentHead + 1);
+ if (diff == 0)
+ {
+ result = resultUsed ? _slots[slotsIndex].Item : default(T);
+ return true;
+ }
+ else if (diff < 0)
+ {
+ // The sequence number was less than what we needed, which means this slot doesn't
+ // yet contain a value we can peek, i.e. the segment is empty. Technically it's
+ // possible that multiple enqueuers could have written concurrently, with those
+ // getting later slots actually finishing first, so there could be elements after
+ // this one that are available, but we need to peek in order. So before declaring
+ // failure and that the segment is empty, we check the tail to see if we're actually
+ // empty or if we're just waiting for items in flight or after this one to become available.
+ bool frozen = _frozenForEnqueues;
+ int currentTail = Volatile.Read(ref _headAndTail.Tail);
+ if (currentTail - currentHead <= 0 || (frozen && (currentTail - FreezeOffset - currentHead <= 0)))
+ {
+ result = default(T);
+ return false;
+ }
+
+ // It's possible it could have become frozen after we checked _frozenForEnqueues
+ // and before reading the tail. That's ok: in that rare race condition, we just
+ // loop around again.
+ }
+
+ // Lost a race. Spin a bit, then try again.
+ spinner.SpinOnce();
+ }
+ }
+
+ /// <summary>
+ /// Attempts to enqueue the item. If successful, the item will be stored
+ /// in the queue and true will be returned; otherwise, the item won't be stored, and false
+ /// will be returned.
+ /// </summary>
+ public bool TryEnqueue(T item)
+ {
+ // Loop in case of contention...
+ var spinner = new SpinWait();
+ while (true)
+ {
+ // Get the tail at which to try to return.
+ int currentTail = Volatile.Read(ref _headAndTail.Tail);
+ int slotsIndex = currentTail & _slotsMask;
+
+ // Read the sequence number for the tail position.
+ int sequenceNumber = Volatile.Read(ref _slots[slotsIndex].SequenceNumber);
+
+ // The slot is empty and ready for us to enqueue into it if its sequence
+ // number matches the slot.
+ int diff = sequenceNumber - currentTail;
+ if (diff == 0)
+ {
+ // We may be racing with other enqueuers. Try to reserve the slot by incrementing
+ // the tail. Once we've done that, no one else will be able to write to this slot,
+ // and no dequeuer will be able to read from this slot until we've written the new
+ // sequence number. WARNING: The next few lines are not reliable on a runtime that
+ // supports thread aborts. If a thread abort were to sneak in after the CompareExchange
+ // but before the Volatile.Write, other threads will spin trying to access this slot.
+ // If this implementation is ever used on such a platform, this if block should be
+ // wrapped in a finally / prepared region.
+ if (Interlocked.CompareExchange(ref _headAndTail.Tail, currentTail + 1, currentTail) == currentTail)
+ {
+ // Successfully reserved the slot. Note that after the above CompareExchange, other threads
+ // trying to return will end up spinning until we do the subsequent Write.
+ _slots[slotsIndex].Item = item;
+ Volatile.Write(ref _slots[slotsIndex].SequenceNumber, currentTail + 1);
+ return true;
+ }
+ }
+ else if (diff < 0)
+ {
+ // The sequence number was less than what we needed, which means this slot still
+ // contains a value, i.e. the segment is full. Technically it's possible that multiple
+ // dequeuers could have read concurrently, with those getting later slots actually
+ // finishing first, so there could be spaces after this one that are available, but
+ // we need to enqueue in order.
+ return false;
+ }
+
+ // Lost a race. Spin a bit, then try again.
+ spinner.SpinOnce();
+ }
+ }
+
+ /// <summary>Represents a slot in the queue.</summary>
+ [StructLayout(LayoutKind.Auto)]
+ [DebuggerDisplay("Item = {Item}, SequenceNumber = {SequenceNumber}")]
+ internal struct Slot
+ {
+ /// <summary>The item.</summary>
+ public T Item;
+ /// <summary>The sequence number for this slot, used to synchronize between enqueuers and dequeuers.</summary>
+ public int SequenceNumber;
+ }
+ }
+
+ /// <summary>Padded head and tail indices, to avoid false sharing between producers and consumers.</summary>
+ [DebuggerDisplay("Head = {Head}, Tail = {Tail}")]
+ [StructLayout(LayoutKind.Explicit, Size = 3 * Internal.PaddingHelpers.CACHE_LINE_SIZE)] // padding before/between/after fields
+ internal struct PaddedHeadAndTail
+ {
+ [FieldOffset(1 * Internal.PaddingHelpers.CACHE_LINE_SIZE)] public int Head;
+ [FieldOffset(2 * Internal.PaddingHelpers.CACHE_LINE_SIZE)] public int Tail;
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollection.cs b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollection.cs
new file mode 100644
index 000000000..972715056
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollection.cs
@@ -0,0 +1,70 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace System.Collections.Concurrent
+{
+ /// <summary>
+ /// A common interface for all concurrent collections.
+ /// Defines methods to manipulate thread-safe collections intended for producer/consumer usage.
+ /// </summary>
+ /// <typeparam name="T">Specifies the type of elements in the collection.</typeparam>
+ /// <remarks>
+ /// All implementations of this interface must enable all members of this interface
+ /// to be used concurrently from multiple threads.
+ /// </remarks>
+ public interface IProducerConsumerCollection<T> : IEnumerable<T>, ICollection
+ {
+ /// <summary>
+ /// Copies the elements of the <see cref="IProducerConsumerCollection{T}"/> to
+ /// an
+ /// <see cref="T:System.Array"/>, starting at a specified index.
+ /// </summary>
+ /// <param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of
+ /// the elements copied from the <see cref="IProducerConsumerCollection{T}"/>.
+ /// The array must have zero-based indexing.</param>
+ /// <param name="index">The zero-based index in <paramref name="array"/> at which copying
+ /// begins.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is a null reference (Nothing in
+ /// Visual Basic).</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than
+ /// zero.</exception>
+ /// <exception cref="ArgumentException"><paramref name="index"/> is equal to or greater than the
+ /// length of the <paramref name="array"/>
+ /// -or- The number of elements in the source <see cref="ConcurrentQueue{T}"/> is greater than the
+ /// available space from <paramref name="index"/> to the end of the destination <paramref
+ /// name="array"/>.
+ /// </exception>
+ void CopyTo(T[] array, int index);
+
+ /// <summary>
+ /// Attempts to add an object to the <see
+ /// cref="IProducerConsumerCollection{T}"/>.
+ /// </summary>
+ /// <param name="item">The object to add to the <see
+ /// cref="IProducerConsumerCollection{T}"/>.</param>
+ /// <returns>true if the object was added successfully; otherwise, false.</returns>
+ /// <exception cref="T:System.ArgumentException">The <paramref name="item"/> was invalid for this collection.</exception>
+ bool TryAdd(T item);
+
+ /// <summary>
+ /// Attempts to remove and return an object from the <see cref="IProducerConsumerCollection{T}"/>.
+ /// </summary>
+ /// <param name="item">
+ /// When this method returns, if the object was removed and returned successfully, <paramref
+ /// name="item"/> contains the removed object. If no object was available to be removed, the value is
+ /// unspecified.
+ /// </param>
+ /// <returns>true if an object was removed and returned successfully; otherwise, false.</returns>
+ bool TryTake(out T item);
+
+ /// <summary>
+ /// Copies the elements contained in the <see cref="IProducerConsumerCollection{T}"/> to a new array.
+ /// </summary>
+ /// <returns>A new array containing the elements copied from the <see cref="IProducerConsumerCollection{T}"/>.</returns>
+ T[] ToArray();
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollectionDebugView.cs b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollectionDebugView.cs
new file mode 100644
index 000000000..0205e068e
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Collections/Concurrent/IProducerConsumerCollectionDebugView.cs
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+
+namespace System.Collections.Concurrent
+{
+ /// <summary>
+ /// A debugger view of the IProducerConsumerCollection that makes it simple to browse the
+ /// collection's contents at a point in time.
+ /// </summary>
+ /// <typeparam name="T">The type of elements stored within.</typeparam>
+ internal sealed class IProducerConsumerCollectionDebugView<T>
+ {
+ private readonly IProducerConsumerCollection<T> _collection; // The collection being viewed.
+
+ /// <summary>
+ /// Constructs a new debugger view object for the provided collection object.
+ /// </summary>
+ /// <param name="collection">A collection to browse in the debugger.</param>
+ public IProducerConsumerCollectionDebugView(IProducerConsumerCollection<T> collection)
+ {
+ if (collection == null)
+ {
+ throw new ArgumentNullException(nameof(collection));
+ }
+
+ _collection = collection;
+ }
+
+ /// <summary>
+ /// Returns a snapshot of the underlying collection's elements.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public T[] Items
+ {
+ get { return _collection.ToArray(); }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/DictionaryEntry.cs b/src/System.Private.CoreLib/shared/System/Collections/DictionaryEntry.cs
index d0cbcb666..eabb01376 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/DictionaryEntry.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/DictionaryEntry.cs
@@ -16,18 +16,18 @@ namespace System.Collections
#endif
public struct DictionaryEntry
{
- private Object _key; // Do not rename (binary serialization)
- private Object _value; // Do not rename (binary serialization)
+ private object _key; // Do not rename (binary serialization)
+ private object _value; // Do not rename (binary serialization)
// Constructs a new DictionaryEnumerator by setting the Key
// and Value fields appropriately.
- public DictionaryEntry(Object key, Object value)
+ public DictionaryEntry(object key, object value)
{
_key = key;
_value = value;
}
- public Object Key
+ public object Key
{
get
{
@@ -40,7 +40,7 @@ namespace System.Collections
}
}
- public Object Value
+ public object Value
{
get
{
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Generic/ArraySortHelper.cs b/src/System.Private.CoreLib/shared/System/Collections/Generic/ArraySortHelper.cs
new file mode 100644
index 000000000..03b986504
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Collections/Generic/ArraySortHelper.cs
@@ -0,0 +1,1115 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: class to sort arrays
+**
+**
+===========================================================*/
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace System.Collections.Generic
+{
+ #region ArraySortHelper for single arrays
+
+ internal static class IntrospectiveSortUtilities
+ {
+ // This is the threshold where Introspective sort switches to Insertion sort.
+ // Empirically, 16 seems to speed up most cases without slowing down others, at least for integers.
+ // Large value types may benefit from a smaller number.
+ internal const int IntrosortSizeThreshold = 16;
+
+ internal static int FloorLog2PlusOne(int n)
+ {
+ int result = 0;
+ while (n >= 1)
+ {
+ result++;
+ n = n / 2;
+ }
+ return result;
+ }
+
+ internal static void ThrowOrIgnoreBadComparer(object comparer)
+ {
+ throw new ArgumentException(SR.Format(SR.Arg_BogusIComparer, comparer));
+ }
+ }
+
+ internal partial class ArraySortHelper<T>
+ {
+ #region IArraySortHelper<T> Members
+
+ public void Sort(T[] keys, int index, int length, IComparer<T> comparer)
+ {
+ Debug.Assert(keys != null, "Check the arguments in the caller!");
+ Debug.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!");
+
+ // Add a try block here to detect IComparers (or their
+ // underlying IComparables, etc) that are bogus.
+ try
+ {
+ if (comparer == null)
+ {
+ comparer = Comparer<T>.Default;
+ }
+
+ IntrospectiveSort(keys, index, length, comparer.Compare);
+ }
+ catch (IndexOutOfRangeException)
+ {
+ IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_IComparerFailed, e);
+ }
+ }
+
+ public int BinarySearch(T[] array, int index, int length, T value, IComparer<T> comparer)
+ {
+ try
+ {
+ if (comparer == null)
+ {
+ comparer = Comparer<T>.Default;
+ }
+
+ return InternalBinarySearch(array, index, length, value, comparer);
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_IComparerFailed, e);
+ }
+ }
+
+ #endregion
+
+ internal static void Sort(T[] keys, int index, int length, Comparison<T> comparer)
+ {
+ Debug.Assert(keys != null, "Check the arguments in the caller!");
+ Debug.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!");
+ Debug.Assert(comparer != null, "Check the arguments in the caller!");
+
+ // Add a try block here to detect bogus comparisons
+ try
+ {
+ IntrospectiveSort(keys, index, length, comparer);
+ }
+ catch (IndexOutOfRangeException)
+ {
+ IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_IComparerFailed, e);
+ }
+ }
+
+ internal static int InternalBinarySearch(T[] array, int index, int length, T value, IComparer<T> comparer)
+ {
+ Debug.Assert(array != null, "Check the arguments in the caller!");
+ Debug.Assert(index >= 0 && length >= 0 && (array.Length - index >= length), "Check the arguments in the caller!");
+
+ int lo = index;
+ int hi = index + length - 1;
+ while (lo <= hi)
+ {
+ int i = lo + ((hi - lo) >> 1);
+ int order = comparer.Compare(array[i], value);
+
+ if (order == 0) return i;
+ if (order < 0)
+ {
+ lo = i + 1;
+ }
+ else
+ {
+ hi = i - 1;
+ }
+ }
+
+ return ~lo;
+ }
+
+ private static void SwapIfGreater(T[] keys, Comparison<T> comparer, int a, int b)
+ {
+ if (a != b)
+ {
+ if (comparer(keys[a], keys[b]) > 0)
+ {
+ T key = keys[a];
+ keys[a] = keys[b];
+ keys[b] = key;
+ }
+ }
+ }
+
+ private static void Swap(T[] a, int i, int j)
+ {
+ if (i != j)
+ {
+ T t = a[i];
+ a[i] = a[j];
+ a[j] = t;
+ }
+ }
+
+ internal static void IntrospectiveSort(T[] keys, int left, int length, Comparison<T> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(left >= 0);
+ Debug.Assert(length >= 0);
+ Debug.Assert(length <= keys.Length);
+ Debug.Assert(length + left <= keys.Length);
+
+ if (length < 2)
+ return;
+
+ IntroSort(keys, left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2PlusOne(length), comparer);
+ }
+
+ private static void IntroSort(T[] keys, int lo, int hi, int depthLimit, Comparison<T> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi < keys.Length);
+
+ while (hi > lo)
+ {
+ int partitionSize = hi - lo + 1;
+ if (partitionSize <= IntrospectiveSortUtilities.IntrosortSizeThreshold)
+ {
+ if (partitionSize == 1)
+ {
+ return;
+ }
+ if (partitionSize == 2)
+ {
+ SwapIfGreater(keys, comparer, lo, hi);
+ return;
+ }
+ if (partitionSize == 3)
+ {
+ SwapIfGreater(keys, comparer, lo, hi - 1);
+ SwapIfGreater(keys, comparer, lo, hi);
+ SwapIfGreater(keys, comparer, hi - 1, hi);
+ return;
+ }
+
+ InsertionSort(keys, lo, hi, comparer);
+ return;
+ }
+
+ if (depthLimit == 0)
+ {
+ Heapsort(keys, lo, hi, comparer);
+ return;
+ }
+ depthLimit--;
+
+ int p = PickPivotAndPartition(keys, lo, hi, comparer);
+ // Note we've already partitioned around the pivot and do not have to move the pivot again.
+ IntroSort(keys, p + 1, hi, depthLimit, comparer);
+ hi = p - 1;
+ }
+ }
+
+ private static int PickPivotAndPartition(T[] keys, int lo, int hi, Comparison<T> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi > lo);
+ Debug.Assert(hi < keys.Length);
+
+ // Compute median-of-three. But also partition them, since we've done the comparison.
+ int middle = lo + ((hi - lo) / 2);
+
+ // Sort lo, mid and hi appropriately, then pick mid as the pivot.
+ SwapIfGreater(keys, comparer, lo, middle); // swap the low with the mid point
+ SwapIfGreater(keys, comparer, lo, hi); // swap the low with the high
+ SwapIfGreater(keys, comparer, middle, hi); // swap the middle with the high
+
+ T pivot = keys[middle];
+ Swap(keys, middle, hi - 1);
+ int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
+
+ while (left < right)
+ {
+ while (comparer(keys[++left], pivot) < 0) ;
+ while (comparer(pivot, keys[--right]) < 0) ;
+
+ if (left >= right)
+ break;
+
+ Swap(keys, left, right);
+ }
+
+ // Put pivot in the right location.
+ Swap(keys, left, (hi - 1));
+ return left;
+ }
+
+ private static void Heapsort(T[] keys, int lo, int hi, Comparison<T> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi > lo);
+ Debug.Assert(hi < keys.Length);
+
+ int n = hi - lo + 1;
+ for (int i = n / 2; i >= 1; i = i - 1)
+ {
+ DownHeap(keys, i, n, lo, comparer);
+ }
+ for (int i = n; i > 1; i = i - 1)
+ {
+ Swap(keys, lo, lo + i - 1);
+ DownHeap(keys, 1, i - 1, lo, comparer);
+ }
+ }
+
+ private static void DownHeap(T[] keys, int i, int n, int lo, Comparison<T> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(lo < keys.Length);
+
+ T d = keys[lo + i - 1];
+ int child;
+ while (i <= n / 2)
+ {
+ child = 2 * i;
+ if (child < n && comparer(keys[lo + child - 1], keys[lo + child]) < 0)
+ {
+ child++;
+ }
+ if (!(comparer(d, keys[lo + child - 1]) < 0))
+ break;
+ keys[lo + i - 1] = keys[lo + child - 1];
+ i = child;
+ }
+ keys[lo + i - 1] = d;
+ }
+
+ private static void InsertionSort(T[] keys, int lo, int hi, Comparison<T> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi >= lo);
+ Debug.Assert(hi <= keys.Length);
+
+ int i, j;
+ T t;
+ for (i = lo; i < hi; i++)
+ {
+ j = i;
+ t = keys[i + 1];
+ while (j >= lo && comparer(t, keys[j]) < 0)
+ {
+ keys[j + 1] = keys[j];
+ j--;
+ }
+ keys[j + 1] = t;
+ }
+ }
+ }
+
+ internal partial class GenericArraySortHelper<T>
+ where T : IComparable<T>
+ {
+ // Do not add a constructor to this class because ArraySortHelper<T>.CreateSortHelper will not execute it
+
+ #region IArraySortHelper<T> Members
+
+ public void Sort(T[] keys, int index, int length, IComparer<T> comparer)
+ {
+ Debug.Assert(keys != null, "Check the arguments in the caller!");
+ Debug.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!");
+
+ try
+ {
+ if (comparer == null || comparer == Comparer<T>.Default)
+ {
+ IntrospectiveSort(keys, index, length);
+ }
+ else
+ {
+ ArraySortHelper<T>.IntrospectiveSort(keys, index, length, comparer.Compare);
+ }
+ }
+ catch (IndexOutOfRangeException)
+ {
+ IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_IComparerFailed, e);
+ }
+ }
+
+ public int BinarySearch(T[] array, int index, int length, T value, IComparer<T> comparer)
+ {
+ Debug.Assert(array != null, "Check the arguments in the caller!");
+ Debug.Assert(index >= 0 && length >= 0 && (array.Length - index >= length), "Check the arguments in the caller!");
+
+ try
+ {
+ if (comparer == null || comparer == Comparer<T>.Default)
+ {
+ return BinarySearch(array, index, length, value);
+ }
+ else
+ {
+ return ArraySortHelper<T>.InternalBinarySearch(array, index, length, value, comparer);
+ }
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_IComparerFailed, e);
+ }
+ }
+
+ #endregion
+
+ // This function is called when the user doesn't specify any comparer.
+ // Since T is constrained here, we can call IComparable<T>.CompareTo here.
+ // We can avoid boxing for value type and casting for reference types.
+ private static int BinarySearch(T[] array, int index, int length, T value)
+ {
+ int lo = index;
+ int hi = index + length - 1;
+ while (lo <= hi)
+ {
+ int i = lo + ((hi - lo) >> 1);
+ int order;
+ if (array[i] == null)
+ {
+ order = (value == null) ? 0 : -1;
+ }
+ else
+ {
+ order = array[i].CompareTo(value);
+ }
+
+ if (order == 0)
+ {
+ return i;
+ }
+
+ if (order < 0)
+ {
+ lo = i + 1;
+ }
+ else
+ {
+ hi = i - 1;
+ }
+ }
+
+ return ~lo;
+ }
+
+ private static void SwapIfGreaterWithItems(T[] keys, int a, int b)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(0 <= a && a < keys.Length);
+ Debug.Assert(0 <= b && b < keys.Length);
+
+ if (a != b)
+ {
+ if (keys[a] != null && keys[a].CompareTo(keys[b]) > 0)
+ {
+ T key = keys[a];
+ keys[a] = keys[b];
+ keys[b] = key;
+ }
+ }
+ }
+
+ private static void Swap(T[] a, int i, int j)
+ {
+ if (i != j)
+ {
+ T t = a[i];
+ a[i] = a[j];
+ a[j] = t;
+ }
+ }
+
+ internal static void IntrospectiveSort(T[] keys, int left, int length)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(left >= 0);
+ Debug.Assert(length >= 0);
+ Debug.Assert(length <= keys.Length);
+ Debug.Assert(length + left <= keys.Length);
+
+ if (length < 2)
+ return;
+
+ IntroSort(keys, left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2PlusOne(length));
+ }
+
+ private static void IntroSort(T[] keys, int lo, int hi, int depthLimit)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi < keys.Length);
+
+ while (hi > lo)
+ {
+ int partitionSize = hi - lo + 1;
+ if (partitionSize <= IntrospectiveSortUtilities.IntrosortSizeThreshold)
+ {
+ if (partitionSize == 1)
+ {
+ return;
+ }
+ if (partitionSize == 2)
+ {
+ SwapIfGreaterWithItems(keys, lo, hi);
+ return;
+ }
+ if (partitionSize == 3)
+ {
+ SwapIfGreaterWithItems(keys, lo, hi - 1);
+ SwapIfGreaterWithItems(keys, lo, hi);
+ SwapIfGreaterWithItems(keys, hi - 1, hi);
+ return;
+ }
+
+ InsertionSort(keys, lo, hi);
+ return;
+ }
+
+ if (depthLimit == 0)
+ {
+ Heapsort(keys, lo, hi);
+ return;
+ }
+ depthLimit--;
+
+ int p = PickPivotAndPartition(keys, lo, hi);
+ // Note we've already partitioned around the pivot and do not have to move the pivot again.
+ IntroSort(keys, p + 1, hi, depthLimit);
+ hi = p - 1;
+ }
+ }
+
+ private static int PickPivotAndPartition(T[] keys, int lo, int hi)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi > lo);
+ Debug.Assert(hi < keys.Length);
+
+ // Compute median-of-three. But also partition them, since we've done the comparison.
+ int middle = lo + ((hi - lo) / 2);
+
+ // Sort lo, mid and hi appropriately, then pick mid as the pivot.
+ SwapIfGreaterWithItems(keys, lo, middle); // swap the low with the mid point
+ SwapIfGreaterWithItems(keys, lo, hi); // swap the low with the high
+ SwapIfGreaterWithItems(keys, middle, hi); // swap the middle with the high
+
+ T pivot = keys[middle];
+ Swap(keys, middle, hi - 1);
+ int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
+
+ while (left < right)
+ {
+ if (pivot == null)
+ {
+ while (left < (hi - 1) && keys[++left] == null) ;
+ while (right > lo && keys[--right] != null) ;
+ }
+ else
+ {
+ while (pivot.CompareTo(keys[++left]) > 0) ;
+ while (pivot.CompareTo(keys[--right]) < 0) ;
+ }
+
+ if (left >= right)
+ break;
+
+ Swap(keys, left, right);
+ }
+
+ // Put pivot in the right location.
+ Swap(keys, left, (hi - 1));
+ return left;
+ }
+
+ private static void Heapsort(T[] keys, int lo, int hi)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi > lo);
+ Debug.Assert(hi < keys.Length);
+
+ int n = hi - lo + 1;
+ for (int i = n / 2; i >= 1; i = i - 1)
+ {
+ DownHeap(keys, i, n, lo);
+ }
+ for (int i = n; i > 1; i = i - 1)
+ {
+ Swap(keys, lo, lo + i - 1);
+ DownHeap(keys, 1, i - 1, lo);
+ }
+ }
+
+ private static void DownHeap(T[] keys, int i, int n, int lo)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(lo < keys.Length);
+
+ T d = keys[lo + i - 1];
+ int child;
+ while (i <= n / 2)
+ {
+ child = 2 * i;
+ if (child < n && (keys[lo + child - 1] == null || keys[lo + child - 1].CompareTo(keys[lo + child]) < 0))
+ {
+ child++;
+ }
+ if (keys[lo + child - 1] == null || keys[lo + child - 1].CompareTo(d) < 0)
+ break;
+ keys[lo + i - 1] = keys[lo + child - 1];
+ i = child;
+ }
+ keys[lo + i - 1] = d;
+ }
+
+ private static void InsertionSort(T[] keys, int lo, int hi)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi >= lo);
+ Debug.Assert(hi <= keys.Length);
+
+ int i, j;
+ T t;
+ for (i = lo; i < hi; i++)
+ {
+ j = i;
+ t = keys[i + 1];
+ while (j >= lo && (t == null || t.CompareTo(keys[j]) < 0))
+ {
+ keys[j + 1] = keys[j];
+ j--;
+ }
+ keys[j + 1] = t;
+ }
+ }
+ }
+
+ #endregion
+
+ #region ArraySortHelper for paired key and value arrays
+
+ internal partial class ArraySortHelper<TKey, TValue>
+ {
+ public void Sort(TKey[] keys, TValue[] values, int index, int length, IComparer<TKey> comparer)
+ {
+ Debug.Assert(keys != null, "Check the arguments in the caller!"); // Precondition on interface method
+ Debug.Assert(values != null, "Check the arguments in the caller!");
+ Debug.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!");
+
+ // Add a try block here to detect IComparers (or their
+ // underlying IComparables, etc) that are bogus.
+ try
+ {
+ if (comparer == null || comparer == Comparer<TKey>.Default)
+ {
+ comparer = Comparer<TKey>.Default;
+ }
+
+ IntrospectiveSort(keys, values, index, length, comparer);
+ }
+ catch (IndexOutOfRangeException)
+ {
+ IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_IComparerFailed, e);
+ }
+ }
+
+ private static void SwapIfGreaterWithItems(TKey[] keys, TValue[] values, IComparer<TKey> comparer, int a, int b)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(0 <= a && a < keys.Length && a < values.Length);
+ Debug.Assert(0 <= b && b < keys.Length && b < values.Length);
+
+ if (a != b)
+ {
+ if (comparer.Compare(keys[a], keys[b]) > 0)
+ {
+ TKey key = keys[a];
+ keys[a] = keys[b];
+ keys[b] = key;
+
+ TValue value = values[a];
+ values[a] = values[b];
+ values[b] = value;
+ }
+ }
+ }
+
+ private static void Swap(TKey[] keys, TValue[] values, int i, int j)
+ {
+ if (i != j)
+ {
+ TKey k = keys[i];
+ keys[i] = keys[j];
+ keys[j] = k;
+
+ TValue v = values[i];
+ values[i] = values[j];
+ values[j] = v;
+ }
+ }
+
+ internal static void IntrospectiveSort(TKey[] keys, TValue[] values, int left, int length, IComparer<TKey> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(left >= 0);
+ Debug.Assert(length >= 0);
+ Debug.Assert(length <= keys.Length);
+ Debug.Assert(length + left <= keys.Length);
+ Debug.Assert(length + left <= values.Length);
+
+ if (length < 2)
+ return;
+
+ IntroSort(keys, values, left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2PlusOne(length), comparer);
+ }
+
+ private static void IntroSort(TKey[] keys, TValue[] values, int lo, int hi, int depthLimit, IComparer<TKey> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi < keys.Length);
+
+ while (hi > lo)
+ {
+ int partitionSize = hi - lo + 1;
+ if (partitionSize <= IntrospectiveSortUtilities.IntrosortSizeThreshold)
+ {
+ if (partitionSize == 1)
+ {
+ return;
+ }
+ if (partitionSize == 2)
+ {
+ SwapIfGreaterWithItems(keys, values, comparer, lo, hi);
+ return;
+ }
+ if (partitionSize == 3)
+ {
+ SwapIfGreaterWithItems(keys, values, comparer, lo, hi - 1);
+ SwapIfGreaterWithItems(keys, values, comparer, lo, hi);
+ SwapIfGreaterWithItems(keys, values, comparer, hi - 1, hi);
+ return;
+ }
+
+ InsertionSort(keys, values, lo, hi, comparer);
+ return;
+ }
+
+ if (depthLimit == 0)
+ {
+ Heapsort(keys, values, lo, hi, comparer);
+ return;
+ }
+ depthLimit--;
+
+ int p = PickPivotAndPartition(keys, values, lo, hi, comparer);
+ // Note we've already partitioned around the pivot and do not have to move the pivot again.
+ IntroSort(keys, values, p + 1, hi, depthLimit, comparer);
+ hi = p - 1;
+ }
+ }
+
+ private static int PickPivotAndPartition(TKey[] keys, TValue[] values, int lo, int hi, IComparer<TKey> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi > lo);
+ Debug.Assert(hi < keys.Length);
+
+ // Compute median-of-three. But also partition them, since we've done the comparison.
+ int middle = lo + ((hi - lo) / 2);
+
+ // Sort lo, mid and hi appropriately, then pick mid as the pivot.
+ SwapIfGreaterWithItems(keys, values, comparer, lo, middle); // swap the low with the mid point
+ SwapIfGreaterWithItems(keys, values, comparer, lo, hi); // swap the low with the high
+ SwapIfGreaterWithItems(keys, values, comparer, middle, hi); // swap the middle with the high
+
+ TKey pivot = keys[middle];
+ Swap(keys, values, middle, hi - 1);
+ int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
+
+ while (left < right)
+ {
+ while (comparer.Compare(keys[++left], pivot) < 0) ;
+ while (comparer.Compare(pivot, keys[--right]) < 0) ;
+
+ if (left >= right)
+ break;
+
+ Swap(keys, values, left, right);
+ }
+
+ // Put pivot in the right location.
+ Swap(keys, values, left, (hi - 1));
+ return left;
+ }
+
+ private static void Heapsort(TKey[] keys, TValue[] values, int lo, int hi, IComparer<TKey> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi > lo);
+ Debug.Assert(hi < keys.Length);
+
+ int n = hi - lo + 1;
+ for (int i = n / 2; i >= 1; i = i - 1)
+ {
+ DownHeap(keys, values, i, n, lo, comparer);
+ }
+ for (int i = n; i > 1; i = i - 1)
+ {
+ Swap(keys, values, lo, lo + i - 1);
+ DownHeap(keys, values, 1, i - 1, lo, comparer);
+ }
+ }
+
+ private static void DownHeap(TKey[] keys, TValue[] values, int i, int n, int lo, IComparer<TKey> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(lo < keys.Length);
+
+ TKey d = keys[lo + i - 1];
+ TValue dValue = values[lo + i - 1];
+ int child;
+ while (i <= n / 2)
+ {
+ child = 2 * i;
+ if (child < n && comparer.Compare(keys[lo + child - 1], keys[lo + child]) < 0)
+ {
+ child++;
+ }
+ if (!(comparer.Compare(d, keys[lo + child - 1]) < 0))
+ break;
+ keys[lo + i - 1] = keys[lo + child - 1];
+ values[lo + i - 1] = values[lo + child - 1];
+ i = child;
+ }
+ keys[lo + i - 1] = d;
+ values[lo + i - 1] = dValue;
+ }
+
+ private static void InsertionSort(TKey[] keys, TValue[] values, int lo, int hi, IComparer<TKey> comparer)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(comparer != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi >= lo);
+ Debug.Assert(hi <= keys.Length);
+
+ int i, j;
+ TKey t;
+ TValue tValue;
+ for (i = lo; i < hi; i++)
+ {
+ j = i;
+ t = keys[i + 1];
+ tValue = values[i + 1];
+ while (j >= lo && comparer.Compare(t, keys[j]) < 0)
+ {
+ keys[j + 1] = keys[j];
+ values[j + 1] = values[j];
+ j--;
+ }
+ keys[j + 1] = t;
+ values[j + 1] = tValue;
+ }
+ }
+ }
+
+ internal partial class GenericArraySortHelper<TKey, TValue>
+ where TKey : IComparable<TKey>
+ {
+ public void Sort(TKey[] keys, TValue[] values, int index, int length, IComparer<TKey> comparer)
+ {
+ Debug.Assert(keys != null, "Check the arguments in the caller!");
+ Debug.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!");
+
+ // Add a try block here to detect IComparers (or their
+ // underlying IComparables, etc) that are bogus.
+ try
+ {
+ if (comparer == null || comparer == Comparer<TKey>.Default)
+ {
+ IntrospectiveSort(keys, values, index, length);
+ }
+ else
+ {
+ ArraySortHelper<TKey, TValue>.IntrospectiveSort(keys, values, index, length, comparer);
+ }
+ }
+ catch (IndexOutOfRangeException)
+ {
+ IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_IComparerFailed, e);
+ }
+ }
+
+ private static void SwapIfGreaterWithItems(TKey[] keys, TValue[] values, int a, int b)
+ {
+ if (a != b)
+ {
+ if (keys[a] != null && keys[a].CompareTo(keys[b]) > 0)
+ {
+ TKey key = keys[a];
+ keys[a] = keys[b];
+ keys[b] = key;
+
+ TValue value = values[a];
+ values[a] = values[b];
+ values[b] = value;
+ }
+ }
+ }
+
+ private static void Swap(TKey[] keys, TValue[] values, int i, int j)
+ {
+ if (i != j)
+ {
+ TKey k = keys[i];
+ keys[i] = keys[j];
+ keys[j] = k;
+
+ TValue v = values[i];
+ values[i] = values[j];
+ values[j] = v;
+ }
+ }
+
+ internal static void IntrospectiveSort(TKey[] keys, TValue[] values, int left, int length)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(left >= 0);
+ Debug.Assert(length >= 0);
+ Debug.Assert(length <= keys.Length);
+ Debug.Assert(length + left <= keys.Length);
+ Debug.Assert(length + left <= values.Length);
+
+ if (length < 2)
+ return;
+
+ IntroSort(keys, values, left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2PlusOne(length));
+ }
+
+ private static void IntroSort(TKey[] keys, TValue[] values, int lo, int hi, int depthLimit)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi < keys.Length);
+
+ while (hi > lo)
+ {
+ int partitionSize = hi - lo + 1;
+ if (partitionSize <= IntrospectiveSortUtilities.IntrosortSizeThreshold)
+ {
+ if (partitionSize == 1)
+ {
+ return;
+ }
+ if (partitionSize == 2)
+ {
+ SwapIfGreaterWithItems(keys, values, lo, hi);
+ return;
+ }
+ if (partitionSize == 3)
+ {
+ SwapIfGreaterWithItems(keys, values, lo, hi - 1);
+ SwapIfGreaterWithItems(keys, values, lo, hi);
+ SwapIfGreaterWithItems(keys, values, hi - 1, hi);
+ return;
+ }
+
+ InsertionSort(keys, values, lo, hi);
+ return;
+ }
+
+ if (depthLimit == 0)
+ {
+ Heapsort(keys, values, lo, hi);
+ return;
+ }
+ depthLimit--;
+
+ int p = PickPivotAndPartition(keys, values, lo, hi);
+ // Note we've already partitioned around the pivot and do not have to move the pivot again.
+ IntroSort(keys, values, p + 1, hi, depthLimit);
+ hi = p - 1;
+ }
+ }
+
+ private static int PickPivotAndPartition(TKey[] keys, TValue[] values, int lo, int hi)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi > lo);
+ Debug.Assert(hi < keys.Length);
+
+ // Compute median-of-three. But also partition them, since we've done the comparison.
+ int middle = lo + ((hi - lo) / 2);
+
+ // Sort lo, mid and hi appropriately, then pick mid as the pivot.
+ SwapIfGreaterWithItems(keys, values, lo, middle); // swap the low with the mid point
+ SwapIfGreaterWithItems(keys, values, lo, hi); // swap the low with the high
+ SwapIfGreaterWithItems(keys, values, middle, hi); // swap the middle with the high
+
+ TKey pivot = keys[middle];
+ Swap(keys, values, middle, hi - 1);
+ int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
+
+ while (left < right)
+ {
+ if (pivot == null)
+ {
+ while (left < (hi - 1) && keys[++left] == null) ;
+ while (right > lo && keys[--right] != null) ;
+ }
+ else
+ {
+ while (pivot.CompareTo(keys[++left]) > 0) ;
+ while (pivot.CompareTo(keys[--right]) < 0) ;
+ }
+
+ if (left >= right)
+ break;
+
+ Swap(keys, values, left, right);
+ }
+
+ // Put pivot in the right location.
+ Swap(keys, values, left, (hi - 1));
+ return left;
+ }
+
+ private static void Heapsort(TKey[] keys, TValue[] values, int lo, int hi)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi > lo);
+ Debug.Assert(hi < keys.Length);
+
+ int n = hi - lo + 1;
+ for (int i = n / 2; i >= 1; i = i - 1)
+ {
+ DownHeap(keys, values, i, n, lo);
+ }
+ for (int i = n; i > 1; i = i - 1)
+ {
+ Swap(keys, values, lo, lo + i - 1);
+ DownHeap(keys, values, 1, i - 1, lo);
+ }
+ }
+
+ private static void DownHeap(TKey[] keys, TValue[] values, int i, int n, int lo)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(lo < keys.Length);
+
+ TKey d = keys[lo + i - 1];
+ TValue dValue = values[lo + i - 1];
+ int child;
+ while (i <= n / 2)
+ {
+ child = 2 * i;
+ if (child < n && (keys[lo + child - 1] == null || keys[lo + child - 1].CompareTo(keys[lo + child]) < 0))
+ {
+ child++;
+ }
+ if (keys[lo + child - 1] == null || keys[lo + child - 1].CompareTo(d) < 0)
+ break;
+ keys[lo + i - 1] = keys[lo + child - 1];
+ values[lo + i - 1] = values[lo + child - 1];
+ i = child;
+ }
+ keys[lo + i - 1] = d;
+ values[lo + i - 1] = dValue;
+ }
+
+ private static void InsertionSort(TKey[] keys, TValue[] values, int lo, int hi)
+ {
+ Debug.Assert(keys != null);
+ Debug.Assert(values != null);
+ Debug.Assert(lo >= 0);
+ Debug.Assert(hi >= lo);
+ Debug.Assert(hi <= keys.Length);
+
+ int i, j;
+ TKey t;
+ TValue tValue;
+ for (i = lo; i < hi; i++)
+ {
+ j = i;
+ t = keys[i + 1];
+ tValue = values[i + 1];
+ while (j >= lo && (t == null || t.CompareTo(keys[j]) < 0))
+ {
+ keys[j + 1] = keys[j];
+ values[j + 1] = values[j];
+ j--;
+ }
+ keys[j + 1] = t;
+ values[j + 1] = tValue;
+ }
+ }
+ }
+
+ #endregion
+}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Generic/Dictionary.cs b/src/System.Private.CoreLib/shared/System/Collections/Generic/Dictionary.cs
index 76fe546fb..623257d3c 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/Generic/Dictionary.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/Generic/Dictionary.cs
@@ -2,11 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-using System.Collections;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
+using System.Threading;
namespace System.Collections.Generic
{
@@ -35,7 +34,7 @@ namespace System.Collections.Generic
[DebuggerDisplay("Count = {Count}")]
[Serializable]
#if !MONO
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
#endif
public class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary, IReadOnlyDictionary<TKey, TValue>, ISerializable, IDeserializationCallback
{
@@ -221,7 +220,7 @@ namespace System.Collections.Generic
int i = FindEntry(key);
if (i >= 0) return _entries[i].value;
ThrowHelper.ThrowKeyNotFoundException(key);
- return default(TValue);
+ return default;
}
set
{
@@ -237,9 +236,7 @@ namespace System.Collections.Generic
}
void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> keyValuePair)
- {
- Add(keyValuePair.Key, keyValuePair.Value);
- }
+ => Add(keyValuePair.Key, keyValuePair.Value);
bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> keyValuePair)
{
@@ -272,30 +269,43 @@ namespace System.Collections.Generic
_count = 0;
_freeList = -1;
_freeCount = 0;
- _version++;
Array.Clear(_entries, 0, count);
}
}
public bool ContainsKey(TKey key)
- {
- return FindEntry(key) >= 0;
- }
+ => FindEntry(key) >= 0;
public bool ContainsValue(TValue value)
{
+ Entry[] entries = _entries;
if (value == null)
{
for (int i = 0; i < _count; i++)
{
- if (_entries[i].hashCode >= 0 && _entries[i].value == null) return true;
+ if (entries[i].hashCode >= 0 && entries[i].value == null) return true;
}
}
else
{
- for (int i = 0; i < _count; i++)
+ if (default(TValue) != null)
+ {
+ // ValueType: Devirtualize with EqualityComparer<TValue>.Default intrinsic
+ for (int i = 0; i < _count; i++)
+ {
+ if (entries[i].hashCode >= 0 && EqualityComparer<TValue>.Default.Equals(entries[i].value, value)) return true;
+ }
+ }
+ else
{
- if (_entries[i].hashCode >= 0 && EqualityComparer<TValue>.Default.Equals(_entries[i].value, value)) return true;
+ // Object type: Shared Generic, EqualityComparer<TValue>.Default won't devirtualize
+ // https://github.com/dotnet/coreclr/issues/17273
+ // So cache in a local rather than get EqualityComparer per loop iteration
+ EqualityComparer<TValue> defaultComparer = EqualityComparer<TValue>.Default;
+ for (int i = 0; i < _count; i++)
+ {
+ if (entries[i].hashCode >= 0 && defaultComparer.Equals(entries[i].value, value)) return true;
+ }
}
}
return false;
@@ -308,7 +318,7 @@ namespace System.Collections.Generic
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
}
- if (index < 0 || index > array.Length)
+ if ((uint)index > (uint)array.Length)
{
ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
}
@@ -330,14 +340,10 @@ namespace System.Collections.Generic
}
public Enumerator GetEnumerator()
- {
- return new Enumerator(this, Enumerator.KeyValuePair);
- }
+ => new Enumerator(this, Enumerator.KeyValuePair);
IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
- {
- return new Enumerator(this, Enumerator.KeyValuePair);
- }
+ => new Enumerator(this, Enumerator.KeyValuePair);
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
@@ -368,6 +374,7 @@ namespace System.Collections.Generic
int i = -1;
int[] buckets = _buckets;
Entry[] entries = _entries;
+ int collisionCount = 0;
if (buckets != null)
{
IEqualityComparer<TKey> comparer = _comparer;
@@ -376,17 +383,53 @@ namespace System.Collections.Generic
int hashCode = key.GetHashCode() & 0x7FFFFFFF;
// Value in _buckets is 1-based
i = buckets[hashCode % buckets.Length] - 1;
- do
+ if (default(TKey) != null)
{
- // Should be a while loop https://github.com/dotnet/coreclr/issues/15476
- // Test in if to drop range check for following array access
- if ((uint)i >= (uint)entries.Length || (entries[i].hashCode == hashCode && EqualityComparer<TKey>.Default.Equals(entries[i].key, key)))
+ // ValueType: Devirtualize with EqualityComparer<TValue>.Default intrinsic
+ do
{
- break;
- }
-
- i = entries[i].next;
- } while (true);
+ // Should be a while loop https://github.com/dotnet/coreclr/issues/15476
+ // Test in if to drop range check for following array access
+ if ((uint)i >= (uint)entries.Length || (entries[i].hashCode == hashCode && EqualityComparer<TKey>.Default.Equals(entries[i].key, key)))
+ {
+ break;
+ }
+
+ i = entries[i].next;
+ if (collisionCount >= entries.Length)
+ {
+ // The chain of entries forms a loop; which means a concurrent update has happened.
+ // Break out of the loop and throw, rather than looping forever.
+ ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
+ }
+ collisionCount++;
+ } while (true);
+ }
+ else
+ {
+ // Object type: Shared Generic, EqualityComparer<TValue>.Default won't devirtualize
+ // https://github.com/dotnet/coreclr/issues/17273
+ // So cache in a local rather than get EqualityComparer per loop iteration
+ EqualityComparer<TKey> defaultComparer = EqualityComparer<TKey>.Default;
+ do
+ {
+ // Should be a while loop https://github.com/dotnet/coreclr/issues/15476
+ // Test in if to drop range check for following array access
+ if ((uint)i >= (uint)entries.Length || (entries[i].hashCode == hashCode && defaultComparer.Equals(entries[i].key, key)))
+ {
+ break;
+ }
+
+ i = entries[i].next;
+ if (collisionCount >= entries.Length)
+ {
+ // The chain of entries forms a loop; which means a concurrent update has happened.
+ // Break out of the loop and throw, rather than looping forever.
+ ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
+ }
+ collisionCount++;
+ } while (true);
+ }
}
else
{
@@ -404,6 +447,13 @@ namespace System.Collections.Generic
}
i = entries[i].next;
+ if (collisionCount >= entries.Length)
+ {
+ // The chain of entries forms a loop; which means a concurrent update has happened.
+ // Break out of the loop and throw, rather than looping forever.
+ ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
+ }
+ collisionCount++;
} while (true);
}
}
@@ -446,35 +496,87 @@ namespace System.Collections.Generic
if (comparer == null)
{
- do
+ if (default(TKey) != null)
{
- // Should be a while loop https://github.com/dotnet/coreclr/issues/15476
- // Test uint in if rather than loop condition to drop range check for following array access
- if ((uint)i >= (uint)entries.Length)
+ // ValueType: Devirtualize with EqualityComparer<TValue>.Default intrinsic
+ do
{
- break;
- }
+ // Should be a while loop https://github.com/dotnet/coreclr/issues/15476
+ // Test uint in if rather than loop condition to drop range check for following array access
+ if ((uint)i >= (uint)entries.Length)
+ {
+ break;
+ }
- if (entries[i].hashCode == hashCode && EqualityComparer<TKey>.Default.Equals(entries[i].key, key))
- {
- if (behavior == InsertionBehavior.OverwriteExisting)
+ if (entries[i].hashCode == hashCode && EqualityComparer<TKey>.Default.Equals(entries[i].key, key))
{
- entries[i].value = value;
- _version++;
- return true;
+ if (behavior == InsertionBehavior.OverwriteExisting)
+ {
+ entries[i].value = value;
+ _version++;
+ return true;
+ }
+
+ if (behavior == InsertionBehavior.ThrowOnExisting)
+ {
+ ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(key);
+ }
+
+ return false;
}
- if (behavior == InsertionBehavior.ThrowOnExisting)
+ i = entries[i].next;
+ if (collisionCount >= entries.Length)
{
- ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(key);
+ // The chain of entries forms a loop; which means a concurrent update has happened.
+ // Break out of the loop and throw, rather than looping forever.
+ ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
+ }
+ collisionCount++;
+ } while (true);
+ }
+ else
+ {
+ // Object type: Shared Generic, EqualityComparer<TValue>.Default won't devirtualize
+ // https://github.com/dotnet/coreclr/issues/17273
+ // So cache in a local rather than get EqualityComparer per loop iteration
+ EqualityComparer<TKey> defaultComparer = EqualityComparer<TKey>.Default;
+ do
+ {
+ // Should be a while loop https://github.com/dotnet/coreclr/issues/15476
+ // Test uint in if rather than loop condition to drop range check for following array access
+ if ((uint)i >= (uint)entries.Length)
+ {
+ break;
}
- return false;
- }
+ if (entries[i].hashCode == hashCode && defaultComparer.Equals(entries[i].key, key))
+ {
+ if (behavior == InsertionBehavior.OverwriteExisting)
+ {
+ entries[i].value = value;
+ _version++;
+ return true;
+ }
+
+ if (behavior == InsertionBehavior.ThrowOnExisting)
+ {
+ ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(key);
+ }
+
+ return false;
+ }
- i = entries[i].next;
- collisionCount++;
- } while (true);
+ i = entries[i].next;
+ if (collisionCount >= entries.Length)
+ {
+ // The chain of entries forms a loop; which means a concurrent update has happened.
+ // Break out of the loop and throw, rather than looping forever.
+ ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
+ }
+ collisionCount++;
+ } while (true);
+ }
}
else
{
@@ -505,14 +607,17 @@ namespace System.Collections.Generic
}
i = entries[i].next;
+ if (collisionCount >= entries.Length)
+ {
+ // The chain of entries forms a loop; which means a concurrent update has happened.
+ // Break out of the loop and throw, rather than looping forever.
+ ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
+ }
collisionCount++;
} while (true);
}
- // Can be improved with "Ref Local Reassignment"
- // https://github.com/dotnet/csharplang/blob/master/proposals/ref-local-reassignment.md
- bool resized = false;
bool updateFreeList = false;
int index;
if (_freeCount > 0)
@@ -527,14 +632,13 @@ namespace System.Collections.Generic
if (count == entries.Length)
{
Resize();
- resized = true;
+ bucket = ref _buckets[hashCode % _buckets.Length];
}
index = count;
_count = count + 1;
entries = _entries;
}
- ref int targetBucket = ref resized ? ref _buckets[hashCode % _buckets.Length] : ref bucket;
ref Entry entry = ref entries[index];
if (updateFreeList)
@@ -543,11 +647,11 @@ namespace System.Collections.Generic
}
entry.hashCode = hashCode;
// Value in _buckets is 1-based
- entry.next = targetBucket - 1;
+ entry.next = bucket - 1;
entry.key = key;
entry.value = value;
// Value in _buckets is 1-based
- targetBucket = index + 1;
+ bucket = index + 1;
_version++;
#if !MONO
@@ -566,8 +670,7 @@ namespace System.Collections.Generic
public virtual void OnDeserialization(object sender)
{
- SerializationInfo siInfo;
- HashHelpers.SerializationInfoTable.TryGetValue(this, out siInfo);
+ HashHelpers.SerializationInfoTable.TryGetValue(this, out SerializationInfo siInfo);
if (siInfo == null)
{
@@ -611,9 +714,7 @@ namespace System.Collections.Generic
}
private void Resize()
- {
- Resize(HashHelpers.ExpandPrime(_count), false);
- }
+ => Resize(HashHelpers.ExpandPrime(_count), false);
private void Resize(int newSize, bool forceNewHashCodes)
{
@@ -665,47 +766,56 @@ namespace System.Collections.Generic
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
- if (_buckets != null)
+ int[] buckets = _buckets;
+ Entry[] entries = _entries;
+ int collisionCount = 0;
+ if (buckets != null)
{
int hashCode = (_comparer?.GetHashCode(key) ?? key.GetHashCode()) & 0x7FFFFFFF;
- int bucket = hashCode % _buckets.Length;
+ int bucket = hashCode % buckets.Length;
int last = -1;
- // Value in _buckets is 1-based
- int i = _buckets[bucket] - 1;
+ // Value in buckets is 1-based
+ int i = buckets[bucket] - 1;
while (i >= 0)
{
- ref Entry entry = ref _entries[i];
+ ref Entry entry = ref entries[i];
if (entry.hashCode == hashCode && (_comparer?.Equals(entry.key, key) ?? EqualityComparer<TKey>.Default.Equals(entry.key, key)))
{
if (last < 0)
{
- // Value in _buckets is 1-based
- _buckets[bucket] = entry.next + 1;
+ // Value in buckets is 1-based
+ buckets[bucket] = entry.next + 1;
}
else
{
- _entries[last].next = entry.next;
+ entries[last].next = entry.next;
}
entry.hashCode = -1;
entry.next = _freeList;
if (RuntimeHelpers.IsReferenceOrContainsReferences<TKey>())
{
- entry.key = default(TKey);
+ entry.key = default;
}
if (RuntimeHelpers.IsReferenceOrContainsReferences<TValue>())
{
- entry.value = default(TValue);
+ entry.value = default;
}
_freeList = i;
_freeCount++;
- _version++;
return true;
}
last = i;
i = entry.next;
+ if (collisionCount >= entries.Length)
+ {
+ // The chain of entries forms a loop; which means a concurrent update has happened.
+ // Break out of the loop and throw, rather than looping forever.
+ ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
+ }
+ collisionCount++;
}
}
return false;
@@ -721,27 +831,30 @@ namespace System.Collections.Generic
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
- if (_buckets != null)
+ int[] buckets = _buckets;
+ Entry[] entries = _entries;
+ int collisionCount = 0;
+ if (buckets != null)
{
int hashCode = (_comparer?.GetHashCode(key) ?? key.GetHashCode()) & 0x7FFFFFFF;
- int bucket = hashCode % _buckets.Length;
+ int bucket = hashCode % buckets.Length;
int last = -1;
- // Value in _buckets is 1-based
- int i = _buckets[bucket] - 1;
+ // Value in buckets is 1-based
+ int i = buckets[bucket] - 1;
while (i >= 0)
{
- ref Entry entry = ref _entries[i];
+ ref Entry entry = ref entries[i];
if (entry.hashCode == hashCode && (_comparer?.Equals(entry.key, key) ?? EqualityComparer<TKey>.Default.Equals(entry.key, key)))
{
if (last < 0)
{
- // Value in _buckets is 1-based
- _buckets[bucket] = entry.next + 1;
+ // Value in buckets is 1-based
+ buckets[bucket] = entry.next + 1;
}
else
{
- _entries[last].next = entry.next;
+ entries[last].next = entry.next;
}
value = entry.value;
@@ -751,23 +864,29 @@ namespace System.Collections.Generic
if (RuntimeHelpers.IsReferenceOrContainsReferences<TKey>())
{
- entry.key = default(TKey);
+ entry.key = default;
}
if (RuntimeHelpers.IsReferenceOrContainsReferences<TValue>())
{
- entry.value = default(TValue);
+ entry.value = default;
}
_freeList = i;
_freeCount++;
- _version++;
return true;
}
last = i;
i = entry.next;
+ if (collisionCount >= entries.Length)
+ {
+ // The chain of entries forms a loop; which means a concurrent update has happened.
+ // Break out of the loop and throw, rather than looping forever.
+ ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
+ }
+ collisionCount++;
}
}
- value = default(TValue);
+ value = default;
return false;
}
@@ -779,57 +898,37 @@ namespace System.Collections.Generic
value = _entries[i].value;
return true;
}
- value = default(TValue);
+ value = default;
return false;
}
- public bool TryAdd(TKey key, TValue value) => TryInsert(key, value, InsertionBehavior.None);
+ public bool TryAdd(TKey key, TValue value)
+ => TryInsert(key, value, InsertionBehavior.None);
- bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
- {
- get { return false; }
- }
+ bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly => false;
void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int index)
- {
- CopyTo(array, index);
- }
+ => CopyTo(array, index);
void ICollection.CopyTo(Array array, int index)
{
if (array == null)
- {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
- }
-
if (array.Rank != 1)
- {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
- }
-
if (array.GetLowerBound(0) != 0)
- {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
- }
-
- if (index < 0 || index > array.Length)
- {
+ if ((uint)index > (uint)array.Length)
ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
- }
-
if (array.Length - index < Count)
- {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
- }
- KeyValuePair<TKey, TValue>[] pairs = array as KeyValuePair<TKey, TValue>[];
- if (pairs != null)
+ if (array is KeyValuePair<TKey, TValue>[] pairs)
{
CopyTo(pairs, index);
}
- else if (array is DictionaryEntry[])
+ else if (array is DictionaryEntry[] dictEntryArray)
{
- DictionaryEntry[] dictEntryArray = array as DictionaryEntry[];
Entry[] entries = _entries;
for (int i = 0; i < _count; i++)
{
@@ -867,9 +966,7 @@ namespace System.Collections.Generic
}
IEnumerator IEnumerable.GetEnumerator()
- {
- return new Enumerator(this, Enumerator.KeyValuePair);
- }
+ => new Enumerator(this, Enumerator.KeyValuePair);
/// <summary>
/// Ensures that the dictionary can hold up to 'capacity' entries without any further expansion of its backing storage
@@ -881,6 +978,7 @@ namespace System.Collections.Generic
int currentCapacity = _entries == null ? 0 : _entries.Length;
if (currentCapacity >= capacity)
return currentCapacity;
+ _version++;
if (_buckets == null)
return Initialize(capacity);
int newSize = HashHelpers.GetPrime(capacity);
@@ -900,9 +998,7 @@ namespace System.Collections.Generic
/// dictionary.TrimExcess();
/// </summary>
public void TrimExcess()
- {
- TrimExcess(Count);
- }
+ => TrimExcess(Count);
/// <summary>
/// Sets the capacity of this dictionary to hold up 'capacity' entries without any further expansion of its backing storage
@@ -922,6 +1018,7 @@ namespace System.Collections.Generic
return;
int oldCount = _count;
+ _version++;
Initialize(newSize);
Entry[] entries = _entries;
int[] buckets = _buckets;
@@ -945,10 +1042,7 @@ namespace System.Collections.Generic
_freeCount = 0;
}
- bool ICollection.IsSynchronized
- {
- get { return false; }
- }
+ bool ICollection.IsSynchronized => false;
object ICollection.SyncRoot
{
@@ -956,31 +1050,19 @@ namespace System.Collections.Generic
{
if (_syncRoot == null)
{
- System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ Interlocked.CompareExchange<object>(ref _syncRoot, new object(), null);
}
return _syncRoot;
}
}
- bool IDictionary.IsFixedSize
- {
- get { return false; }
- }
+ bool IDictionary.IsFixedSize => false;
- bool IDictionary.IsReadOnly
- {
- get { return false; }
- }
+ bool IDictionary.IsReadOnly => false;
- ICollection IDictionary.Keys
- {
- get { return (ICollection)Keys; }
- }
+ ICollection IDictionary.Keys => (ICollection)Keys;
- ICollection IDictionary.Values
- {
- get { return (ICollection)Values; }
- }
+ ICollection IDictionary.Values => (ICollection)Values;
object IDictionary.this[object key]
{
@@ -1070,9 +1152,7 @@ namespace System.Collections.Generic
}
IDictionaryEnumerator IDictionary.GetEnumerator()
- {
- return new Enumerator(this, Enumerator.DictEntry);
- }
+ => new Enumerator(this, Enumerator.DictEntry);
void IDictionary.Remove(object key)
{
@@ -1088,11 +1168,11 @@ namespace System.Collections.Generic
public struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>,
IDictionaryEnumerator
{
- private Dictionary<TKey, TValue> _dictionary;
- private int _version;
+ private readonly Dictionary<TKey, TValue> _dictionary;
+ private readonly int _version;
private int _index;
private KeyValuePair<TKey, TValue> _current;
- private int _getEnumeratorRetType; // What should Enumerator.Current return?
+ private readonly int _getEnumeratorRetType; // What should Enumerator.Current return?
internal const int DictEntry = 1;
internal const int KeyValuePair = 2;
@@ -1114,7 +1194,7 @@ namespace System.Collections.Generic
}
// Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends.
- // dictionary.count+1 could be negative if dictionary.count is Int32.MaxValue
+ // dictionary.count+1 could be negative if dictionary.count is int.MaxValue
while ((uint)_index < (uint)_dictionary._count)
{
ref Entry entry = ref _dictionary._entries[_index++];
@@ -1131,10 +1211,7 @@ namespace System.Collections.Generic
return false;
}
- public KeyValuePair<TKey, TValue> Current
- {
- get { return _current; }
- }
+ public KeyValuePair<TKey, TValue> Current => _current;
public void Dispose()
{
@@ -1151,7 +1228,7 @@ namespace System.Collections.Generic
if (_getEnumeratorRetType == DictEntry)
{
- return new System.Collections.DictionaryEntry(_current.Key, _current.Value);
+ return new DictionaryEntry(_current.Key, _current.Value);
}
else
{
@@ -1230,9 +1307,7 @@ namespace System.Collections.Generic
}
public Enumerator GetEnumerator()
- {
- return new Enumerator(_dictionary);
- }
+ => new Enumerator(_dictionary);
public void CopyTo(TKey[] array, int index)
{
@@ -1259,30 +1334,18 @@ namespace System.Collections.Generic
}
}
- public int Count
- {
- get { return _dictionary.Count; }
- }
+ public int Count => _dictionary.Count;
- bool ICollection<TKey>.IsReadOnly
- {
- get { return true; }
- }
+ bool ICollection<TKey>.IsReadOnly => true;
void ICollection<TKey>.Add(TKey item)
- {
- ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet);
- }
+ => ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet);
void ICollection<TKey>.Clear()
- {
- ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet);
- }
+ => ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet);
bool ICollection<TKey>.Contains(TKey item)
- {
- return _dictionary.ContainsKey(item);
- }
+ => _dictionary.ContainsKey(item);
bool ICollection<TKey>.Remove(TKey item)
{
@@ -1291,44 +1354,25 @@ namespace System.Collections.Generic
}
IEnumerator<TKey> IEnumerable<TKey>.GetEnumerator()
- {
- return new Enumerator(_dictionary);
- }
+ => new Enumerator(_dictionary);
IEnumerator IEnumerable.GetEnumerator()
- {
- return new Enumerator(_dictionary);
- }
+ => new Enumerator(_dictionary);
void ICollection.CopyTo(Array array, int index)
{
if (array == null)
- {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
- }
-
if (array.Rank != 1)
- {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
- }
-
if (array.GetLowerBound(0) != 0)
- {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
- }
-
- if (index < 0 || index > array.Length)
- {
+ if ((uint)index > (uint)array.Length)
ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
- }
-
if (array.Length - index < _dictionary.Count)
- {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
- }
- TKey[] keys = array as TKey[];
- if (keys != null)
+ if (array is TKey[] keys)
{
CopyTo(keys, index);
}
@@ -1356,24 +1400,18 @@ namespace System.Collections.Generic
}
}
- bool ICollection.IsSynchronized
- {
- get { return false; }
- }
+ bool ICollection.IsSynchronized => false;
- object ICollection.SyncRoot
- {
- get { return ((ICollection)_dictionary).SyncRoot; }
- }
+ object ICollection.SyncRoot => ((ICollection)_dictionary).SyncRoot;
#if MONO
[Serializable]
#endif
- public struct Enumerator : IEnumerator<TKey>, System.Collections.IEnumerator
+ public struct Enumerator : IEnumerator<TKey>, IEnumerator
{
- private Dictionary<TKey, TValue> _dictionary;
+ private readonly Dictionary<TKey, TValue> _dictionary;
private int _index;
- private int _version;
+ private readonly int _version;
private TKey _currentKey;
internal Enumerator(Dictionary<TKey, TValue> dictionary)
@@ -1381,7 +1419,7 @@ namespace System.Collections.Generic
_dictionary = dictionary;
_version = dictionary._version;
_index = 0;
- _currentKey = default(TKey);
+ _currentKey = default;
}
public void Dispose()
@@ -1407,19 +1445,13 @@ namespace System.Collections.Generic
}
_index = _dictionary._count + 1;
- _currentKey = default(TKey);
+ _currentKey = default;
return false;
}
- public TKey Current
- {
- get
- {
- return _currentKey;
- }
- }
+ public TKey Current => _currentKey;
- object System.Collections.IEnumerator.Current
+ object IEnumerator.Current
{
get
{
@@ -1432,7 +1464,7 @@ namespace System.Collections.Generic
}
}
- void System.Collections.IEnumerator.Reset()
+ void IEnumerator.Reset()
{
if (_version != _dictionary._version)
{
@@ -1440,7 +1472,7 @@ namespace System.Collections.Generic
}
_index = 0;
- _currentKey = default(TKey);
+ _currentKey = default;
}
}
}
@@ -1464,9 +1496,7 @@ namespace System.Collections.Generic
}
public Enumerator GetEnumerator()
- {
- return new Enumerator(_dictionary);
- }
+ => new Enumerator(_dictionary);
public void CopyTo(TValue[] array, int index)
{
@@ -1493,20 +1523,12 @@ namespace System.Collections.Generic
}
}
- public int Count
- {
- get { return _dictionary.Count; }
- }
+ public int Count => _dictionary.Count;
- bool ICollection<TValue>.IsReadOnly
- {
- get { return true; }
- }
+ bool ICollection<TValue>.IsReadOnly => true;
void ICollection<TValue>.Add(TValue item)
- {
- ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet);
- }
+ => ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet);
bool ICollection<TValue>.Remove(TValue item)
{
@@ -1515,52 +1537,31 @@ namespace System.Collections.Generic
}
void ICollection<TValue>.Clear()
- {
- ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet);
- }
+ => ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet);
bool ICollection<TValue>.Contains(TValue item)
- {
- return _dictionary.ContainsValue(item);
- }
+ => _dictionary.ContainsValue(item);
IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator()
- {
- return new Enumerator(_dictionary);
- }
+ => new Enumerator(_dictionary);
IEnumerator IEnumerable.GetEnumerator()
- {
- return new Enumerator(_dictionary);
- }
+ => new Enumerator(_dictionary);
void ICollection.CopyTo(Array array, int index)
{
if (array == null)
- {
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
- }
-
if (array.Rank != 1)
- {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
- }
-
if (array.GetLowerBound(0) != 0)
- {
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
- }
-
- if (index < 0 || index > array.Length)
- {
+ if ((uint)index > (uint)array.Length)
ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
- }
-
if (array.Length - index < _dictionary.Count)
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
- TValue[] values = array as TValue[];
- if (values != null)
+ if (array is TValue[] values)
{
CopyTo(values, index);
}
@@ -1588,24 +1589,18 @@ namespace System.Collections.Generic
}
}
- bool ICollection.IsSynchronized
- {
- get { return false; }
- }
+ bool ICollection.IsSynchronized => false;
- object ICollection.SyncRoot
- {
- get { return ((ICollection)_dictionary).SyncRoot; }
- }
+ object ICollection.SyncRoot => ((ICollection)_dictionary).SyncRoot;
#if MONO
[Serializable]
#endif
- public struct Enumerator : IEnumerator<TValue>, System.Collections.IEnumerator
+ public struct Enumerator : IEnumerator<TValue>, IEnumerator
{
- private Dictionary<TKey, TValue> _dictionary;
+ private readonly Dictionary<TKey, TValue> _dictionary;
private int _index;
- private int _version;
+ private readonly int _version;
private TValue _currentValue;
internal Enumerator(Dictionary<TKey, TValue> dictionary)
@@ -1613,7 +1608,7 @@ namespace System.Collections.Generic
_dictionary = dictionary;
_version = dictionary._version;
_index = 0;
- _currentValue = default(TValue);
+ _currentValue = default;
}
public void Dispose()
@@ -1638,19 +1633,13 @@ namespace System.Collections.Generic
}
}
_index = _dictionary._count + 1;
- _currentValue = default(TValue);
+ _currentValue = default;
return false;
}
- public TValue Current
- {
- get
- {
- return _currentValue;
- }
- }
+ public TValue Current => _currentValue;
- object System.Collections.IEnumerator.Current
+ object IEnumerator.Current
{
get
{
@@ -1663,14 +1652,14 @@ namespace System.Collections.Generic
}
}
- void System.Collections.IEnumerator.Reset()
+ void IEnumerator.Reset()
{
if (_version != _dictionary._version)
{
ThrowHelper.ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion();
}
_index = 0;
- _currentValue = default(TValue);
+ _currentValue = default;
}
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Generic/KeyNotFoundException.cs b/src/System.Private.CoreLib/shared/System/Collections/Generic/KeyNotFoundException.cs
index 48eddb874..3990e1378 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/Generic/KeyNotFoundException.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/Generic/KeyNotFoundException.cs
@@ -17,13 +17,13 @@ namespace System.Collections.Generic
HResult = HResults.COR_E_KEYNOTFOUND;
}
- public KeyNotFoundException(String message)
+ public KeyNotFoundException(string message)
: base(message)
{
HResult = HResults.COR_E_KEYNOTFOUND;
}
- public KeyNotFoundException(String message, Exception innerException)
+ public KeyNotFoundException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_KEYNOTFOUND;
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Generic/List.cs b/src/System.Private.CoreLib/shared/System/Collections/Generic/List.cs
index 56bbea895..698abe9cf 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/Generic/List.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/Generic/List.cs
@@ -5,6 +5,7 @@
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
+using System.Threading;
namespace System.Collections.Generic
{
@@ -17,8 +18,8 @@ namespace System.Collections.Generic
[DebuggerTypeProxy(typeof(ICollectionDebugView<>))]
[DebuggerDisplay("Count = {Count}")]
[Serializable]
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public class List<T> : IList<T>, System.Collections.IList, IReadOnlyList<T>
+ [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public class List<T> : IList<T>, IList, IReadOnlyList<T>
{
private const int DefaultCapacity = 4;
@@ -63,8 +64,7 @@ namespace System.Collections.Generic
if (collection == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
- ICollection<T> c = collection as ICollection<T>;
- if (c != null)
+ if (collection is ICollection<T> c)
{
int count = c.Count;
if (count == 0)
@@ -123,44 +123,26 @@ namespace System.Collections.Generic
}
// Read-only property describing how many elements are in the List.
- public int Count
- {
- get
- {
- return _size;
- }
- }
+ public int Count => _size;
- bool System.Collections.IList.IsFixedSize
- {
- get { return false; }
- }
+ bool IList.IsFixedSize => false;
// Is this List read-only?
- bool ICollection<T>.IsReadOnly
- {
- get { return false; }
- }
+ bool ICollection<T>.IsReadOnly => false;
- bool System.Collections.IList.IsReadOnly
- {
- get { return false; }
- }
+ bool IList.IsReadOnly => false;
// Is this List synchronized (thread-safe)?
- bool System.Collections.ICollection.IsSynchronized
- {
- get { return false; }
- }
+ bool ICollection.IsSynchronized => false;
// Synchronization root for this object.
- object System.Collections.ICollection.SyncRoot
+ object ICollection.SyncRoot
{
get
{
if (_syncRoot == null)
{
- System.Threading.Interlocked.CompareExchange<object>(ref _syncRoot, new object(), null);
+ Interlocked.CompareExchange<object>(ref _syncRoot, new object(), null);
}
return _syncRoot;
}
@@ -197,7 +179,7 @@ namespace System.Collections.Generic
return ((value is T) || (value == null && default(T) == null));
}
- object System.Collections.IList.this[int index]
+ object IList.this[int index]
{
get
{
@@ -225,9 +207,9 @@ namespace System.Collections.Generic
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Add(T item)
{
- var array = _items;
- var size = _size;
_version++;
+ T[] array = _items;
+ int size = _size;
if ((uint)size < (uint)array.Length)
{
_size = size + 1;
@@ -243,13 +225,13 @@ namespace System.Collections.Generic
[MethodImpl(MethodImplOptions.NoInlining)]
private void AddWithResize(T item)
{
- var size = _size;
+ int size = _size;
EnsureCapacity(size + 1);
_size = size + 1;
_items[size] = item;
}
- int System.Collections.IList.Add(Object item)
+ int IList.Add(object item)
{
ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(item, ExceptionArgument.item);
@@ -270,14 +252,10 @@ namespace System.Collections.Generic
// capacity or the new size, whichever is larger.
//
public void AddRange(IEnumerable<T> collection)
- {
- InsertRange(_size, collection);
- }
+ => InsertRange(_size, collection);
public ReadOnlyCollection<T> AsReadOnly()
- {
- return new ReadOnlyCollection<T>(this);
- }
+ => new ReadOnlyCollection<T>(this);
// Searches a section of the list for a given element using a binary search
// algorithm. Elements of the list are compared to the search value using
@@ -312,25 +290,20 @@ namespace System.Collections.Generic
}
public int BinarySearch(T item)
- {
- return BinarySearch(0, Count, item, null);
- }
+ => BinarySearch(0, Count, item, null);
public int BinarySearch(T item, IComparer<T> comparer)
- {
- return BinarySearch(0, Count, item, comparer);
- }
-
+ => BinarySearch(0, Count, item, comparer);
// Clears the contents of List.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Clear()
{
+ _version++;
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
{
int size = _size;
_size = 0;
- _version++;
if (size > 0)
{
Array.Clear(_items, 0, size); // Clear the elements so that the gc can reclaim the references.
@@ -339,7 +312,6 @@ namespace System.Collections.Generic
else
{
_size = 0;
- _version++;
}
}
@@ -360,7 +332,7 @@ namespace System.Collections.Generic
return _size != 0 && IndexOf(item) != -1;
}
- bool System.Collections.IList.Contains(object item)
+ bool IList.Contains(object item)
{
if (IsCompatibleObject(item))
{
@@ -388,13 +360,11 @@ namespace System.Collections.Generic
// Copies this List into array, which must be of a
// compatible array type.
public void CopyTo(T[] array)
- {
- CopyTo(array, 0);
- }
+ => CopyTo(array, 0);
// Copies this List into array, which must be of a
// compatible array type.
- void System.Collections.ICollection.CopyTo(Array array, int arrayIndex)
+ void ICollection.CopyTo(Array array, int arrayIndex)
{
if ((array != null) && (array.Rank != 1))
{
@@ -452,9 +422,7 @@ namespace System.Collections.Generic
}
public bool Exists(Predicate<T> match)
- {
- return FindIndex(match) != -1;
- }
+ => FindIndex(match) != -1;
public T Find(Predicate<T> match)
{
@@ -470,7 +438,7 @@ namespace System.Collections.Generic
return _items[i];
}
}
- return default(T);
+ return default;
}
public List<T> FindAll(Predicate<T> match)
@@ -492,14 +460,10 @@ namespace System.Collections.Generic
}
public int FindIndex(Predicate<T> match)
- {
- return FindIndex(0, _size, match);
- }
+ => FindIndex(0, _size, match);
public int FindIndex(int startIndex, Predicate<T> match)
- {
- return FindIndex(startIndex, _size - startIndex, match);
- }
+ => FindIndex(startIndex, _size - startIndex, match);
public int FindIndex(int startIndex, int count, Predicate<T> match)
{
@@ -540,18 +504,14 @@ namespace System.Collections.Generic
return _items[i];
}
}
- return default(T);
+ return default;
}
public int FindLastIndex(Predicate<T> match)
- {
- return FindLastIndex(_size - 1, _size, match);
- }
+ => FindLastIndex(_size - 1, _size, match);
public int FindLastIndex(int startIndex, Predicate<T> match)
- {
- return FindLastIndex(startIndex, startIndex + 1, match);
- }
+ => FindLastIndex(startIndex, startIndex + 1, match);
public int FindLastIndex(int startIndex, int count, Predicate<T> match)
{
@@ -622,19 +582,13 @@ namespace System.Collections.Generic
// GetObject methods of the enumerator will throw an exception.
//
public Enumerator GetEnumerator()
- {
- return new Enumerator(this);
- }
+ => new Enumerator(this);
IEnumerator<T> IEnumerable<T>.GetEnumerator()
- {
- return new Enumerator(this);
- }
+ => new Enumerator(this);
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return new Enumerator(this);
- }
+ IEnumerator IEnumerable.GetEnumerator()
+ => new Enumerator(this);
public List<T> GetRange(int index, int count)
{
@@ -669,11 +623,9 @@ namespace System.Collections.Generic
// search.
//
public int IndexOf(T item)
- {
- return Array.IndexOf(_items, item, 0, _size);
- }
+ => Array.IndexOf(_items, item, 0, _size);
- int System.Collections.IList.IndexOf(object item)
+ int IList.IndexOf(object item)
{
if (IsCompatibleObject(item))
{
@@ -739,7 +691,7 @@ namespace System.Collections.Generic
_version++;
}
- void System.Collections.IList.Insert(int index, Object item)
+ void IList.Insert(int index, object item)
{
ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(item, ExceptionArgument.item);
@@ -770,9 +722,8 @@ namespace System.Collections.Generic
ThrowHelper.ThrowArgumentOutOfRange_IndexException();
}
- ICollection<T> c = collection as ICollection<T>;
- if (c != null)
- { // if collection is ICollection<T>
+ if (collection is ICollection<T> c)
+ {
int count = c.Count;
if (count > 0)
{
@@ -905,7 +856,7 @@ namespace System.Collections.Generic
return false;
}
- void System.Collections.IList.Remove(object item)
+ void IList.Remove(object item)
{
if (IsCompatibleObject(item))
{
@@ -967,7 +918,7 @@ namespace System.Collections.Generic
}
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
{
- _items[_size] = default(T);
+ _items[_size] = default;
}
_version++;
}
@@ -990,7 +941,6 @@ namespace System.Collections.Generic
if (count > 0)
{
- int i = _size;
_size -= count;
if (index < _size)
{
@@ -1007,9 +957,7 @@ namespace System.Collections.Generic
// Reverses the elements in this list.
public void Reverse()
- {
- Reverse(0, Count);
- }
+ => Reverse(0, Count);
// Reverses the elements in a range of this list. Following a call to this
// method, an element in the range given by index and count
@@ -1041,16 +989,12 @@ namespace System.Collections.Generic
// Sorts the elements in this list. Uses the default comparer and
// Array.Sort.
public void Sort()
- {
- Sort(0, Count, null);
- }
+ => Sort(0, Count, null);
// Sorts the elements in this list. Uses Array.Sort with the
// provided comparer.
public void Sort(IComparer<T> comparer)
- {
- Sort(0, Count, comparer);
- }
+ => Sort(0, Count, comparer);
// Sorts the elements in a section of this list. The sort compares the
// elements to each other using the given IComparer interface. If
@@ -1150,9 +1094,9 @@ namespace System.Collections.Generic
Debug.Assert(enumerable != null);
Debug.Assert(!(enumerable is ICollection<T>), "We should have optimized for this beforehand.");
+ _version++; // Even if the enumerable has no items, we can update _version.
using (IEnumerator<T> en = enumerable.GetEnumerator())
{
- _version++; // Even if the enumerable has no items, we can update _version.
while (en.MoveNext())
{
@@ -1170,11 +1114,11 @@ namespace System.Collections.Generic
}
}
- public struct Enumerator : IEnumerator<T>, System.Collections.IEnumerator
+ public struct Enumerator : IEnumerator<T>, IEnumerator
{
- private List<T> _list;
+ private readonly List<T> _list;
private int _index;
- private int _version;
+ private readonly int _version;
private T _current;
internal Enumerator(List<T> list)
@@ -1182,7 +1126,7 @@ namespace System.Collections.Generic
_list = list;
_index = 0;
_version = list._version;
- _current = default(T);
+ _current = default;
}
public void Dispose()
@@ -1210,19 +1154,13 @@ namespace System.Collections.Generic
}
_index = _list._size + 1;
- _current = default(T);
+ _current = default;
return false;
}
- public T Current
- {
- get
- {
- return _current;
- }
- }
+ public T Current => _current;
- object System.Collections.IEnumerator.Current
+ object IEnumerator.Current
{
get
{
@@ -1234,7 +1172,7 @@ namespace System.Collections.Generic
}
}
- void System.Collections.IEnumerator.Reset()
+ void IEnumerator.Reset()
{
if (_version != _list._version)
{
@@ -1242,7 +1180,7 @@ namespace System.Collections.Generic
}
_index = 0;
- _current = default(T);
+ _current = default;
}
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs b/src/System.Private.CoreLib/shared/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs
index 72f62c2b9..91b782061 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs
@@ -11,12 +11,8 @@ namespace System.Collections.Generic
// keeps the performance not affected till we hit collision threshold and then we switch to the comparer which is using
// randomized string hashing.
[Serializable] // Required for compatibility with .NET Core 2.0 as we exposed the NonRandomizedStringEqualityComparer inside the serialization blob
-#if CORERT
- public
-#else
- internal
-#endif
- sealed class NonRandomizedStringEqualityComparer : EqualityComparer<string>, ISerializable
+ // Needs to be public to support binary serialization compatibility
+ public sealed class NonRandomizedStringEqualityComparer : EqualityComparer<string>, ISerializable
{
internal static new IEqualityComparer<string> Default { get; } = new NonRandomizedStringEqualityComparer();
@@ -27,7 +23,7 @@ namespace System.Collections.Generic
public sealed override bool Equals(string x, string y) => string.Equals(x, y);
- public sealed override int GetHashCode(string obj) => obj?.GetLegacyNonRandomizedHashCode() ?? 0;
+ public sealed override int GetHashCode(string obj) => obj?.GetNonRandomizedHashCode() ?? 0;
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Generic/ValueListBuilder.cs b/src/System.Private.CoreLib/shared/System/Collections/Generic/ValueListBuilder.cs
index 72da4a9e1..aea6052f0 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/Generic/ValueListBuilder.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/Generic/ValueListBuilder.cs
@@ -21,7 +21,16 @@ namespace System.Collections.Generic
_pos = 0;
}
- public int Length => _pos;
+ public int Length
+ {
+ get => _pos;
+ set
+ {
+ Debug.Assert(value >= 0);
+ Debug.Assert(value <= _span.Length);
+ _pos = value;
+ }
+ }
public ref T this[int index]
{
diff --git a/src/System.Private.CoreLib/shared/System/Collections/HashHelpers.SerializationInfoTable.cs b/src/System.Private.CoreLib/shared/System/Collections/HashHelpers.SerializationInfoTable.cs
new file mode 100644
index 000000000..d91dfd878
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Collections/HashHelpers.SerializationInfoTable.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// Used by Hashtable and Dictionary's SeralizationInfo .ctor's to store the SeralizationInfo
+// object until OnDeserialization is called.
+
+using System.Threading;
+using System.Runtime.CompilerServices;
+using System.Runtime.Serialization;
+
+namespace System.Collections
+{
+ internal static partial class HashHelpers
+ {
+ private static ConditionalWeakTable<object, SerializationInfo> s_serializationInfoTable;
+
+ public static ConditionalWeakTable<object, SerializationInfo> SerializationInfoTable
+ {
+ get
+ {
+ if (s_serializationInfoTable == null)
+ Interlocked.CompareExchange(ref s_serializationInfoTable, new ConditionalWeakTable<object, SerializationInfo>(), null);
+
+ return s_serializationInfoTable;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Private.CoreLib/shared/System/Collections/HashHelpers.cs b/src/System.Private.CoreLib/shared/System/Collections/HashHelpers.cs
index 49cff85b5..ba2c75c89 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/HashHelpers.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/HashHelpers.cs
@@ -2,17 +2,18 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+
using System.Diagnostics;
-using System.Runtime.CompilerServices;
-using System.Runtime.Serialization;
-using System.Threading;
namespace System.Collections
{
- internal static class HashHelpers
+ internal static partial class HashHelpers
{
public const int HashCollisionThreshold = 100;
+ // This is the maximum prime smaller than Array.MaxArrayLength
+ public const int MaxPrimeArrayLength = 0x7FEFFFFD;
+
public const int HashPrime = 101;
// Table of prime numbers to use as hash table sizes.
@@ -26,12 +27,14 @@ namespace System.Collections
// hashtable operations such as add. Having a prime guarantees that double
// hashing does not lead to infinite loops. IE, your hash function will be
// h1(key) + i*h2(key), 0 <= i < size. h2 and the size must be relatively prime.
+ // We prefer the low computation costs of higher prime numbers over the increased
+ // memory allocation of a fixed prime number i.e. when right sizing a HashSet.
public static readonly int[] primes = {
3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919,
1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591,
17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437,
187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263,
- 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369};
+ 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369 };
public static bool IsPrime(int candidate)
{
@@ -56,12 +59,13 @@ namespace System.Collections
for (int i = 0; i < primes.Length; i++)
{
int prime = primes[i];
- if (prime >= min) return prime;
+ if (prime >= min)
+ return prime;
}
//outside of our predefined table.
//compute the hard way.
- for (int i = (min | 1); i < Int32.MaxValue; i += 2)
+ for (int i = (min | 1); i < int.MaxValue; i += 2)
{
if (IsPrime(i) && ((i - 1) % HashPrime != 0))
return i;
@@ -74,7 +78,7 @@ namespace System.Collections
{
int newSize = 2 * oldSize;
- // Allow the hashtables to grow to maximum possible size (~2G elements) before encoutering capacity overflow.
+ // Allow the hashtables to grow to maximum possible size (~2G elements) before encountering capacity overflow.
// Note that this check works even when _items.Length overflowed thanks to the (uint) cast
if ((uint)newSize > MaxPrimeArrayLength && MaxPrimeArrayLength > oldSize)
{
@@ -84,25 +88,5 @@ namespace System.Collections
return GetPrime(newSize);
}
-
-
- // This is the maximum prime smaller than Array.MaxArrayLength
- public const int MaxPrimeArrayLength = 0x7FEFFFFD;
-
-
- // Used by Hashtable and Dictionary's SeralizationInfo .ctor's to store the SeralizationInfo
- // object until OnDeserialization is called.
- private static ConditionalWeakTable<object, SerializationInfo> s_serializationInfoTable;
-
- internal static ConditionalWeakTable<object, SerializationInfo> SerializationInfoTable
- {
- get
- {
- if (s_serializationInfoTable == null)
- Interlocked.CompareExchange(ref s_serializationInfoTable, new ConditionalWeakTable<object, SerializationInfo>(), null);
-
- return s_serializationInfoTable;
- }
- }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/Hashtable.cs b/src/System.Private.CoreLib/shared/System/Collections/Hashtable.cs
new file mode 100644
index 000000000..1c3139d27
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Collections/Hashtable.cs
@@ -0,0 +1,1650 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Class: Hashtable
+**
+** Purpose: Represents a collection of key/value pairs
+** that are organized based on the hash code
+** of the key.
+**
+===========================================================*/
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.Serialization;
+using System.Threading;
+
+namespace System.Collections
+{
+ // The Hashtable class represents a dictionary of associated keys and values
+ // with constant lookup time.
+ //
+ // Objects used as keys in a hashtable must implement the GetHashCode
+ // and Equals methods (or they can rely on the default implementations
+ // inherited from Object if key equality is simply reference
+ // equality). Furthermore, the GetHashCode and Equals methods of
+ // a key object must produce the same results given the same parameters for the
+ // entire time the key is present in the hashtable. In practical terms, this
+ // means that key objects should be immutable, at least for the time they are
+ // used as keys in a hashtable.
+ //
+ // When entries are added to a hashtable, they are placed into
+ // buckets based on the hashcode of their keys. Subsequent lookups of
+ // keys will use the hashcode of the keys to only search a particular bucket,
+ // thus substantially reducing the number of key comparisons required to find
+ // an entry. A hashtable's maximum load factor, which can be specified
+ // when the hashtable is instantiated, determines the maximum ratio of
+ // hashtable entries to hashtable buckets. Smaller load factors cause faster
+ // average lookup times at the cost of increased memory consumption. The
+ // default maximum load factor of 1.0 generally provides the best balance
+ // between speed and size. As entries are added to a hashtable, the hashtable's
+ // actual load factor increases, and when the actual load factor reaches the
+ // maximum load factor value, the number of buckets in the hashtable is
+ // automatically increased by approximately a factor of two (to be precise, the
+ // number of hashtable buckets is increased to the smallest prime number that
+ // is larger than twice the current number of hashtable buckets).
+ //
+ // Each object provides their own hash function, accessed by calling
+ // GetHashCode(). However, one can write their own object
+ // implementing IEqualityComparer and pass it to a constructor on
+ // the Hashtable. That hash function (and the equals method on the
+ // IEqualityComparer) would be used for all objects in the table.
+ //
+ [DebuggerTypeProxy(typeof(System.Collections.Hashtable.HashtableDebugView))]
+ [DebuggerDisplay("Count = {Count}")]
+ [Serializable]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public class Hashtable : IDictionary, ISerializable, IDeserializationCallback, ICloneable
+ {
+ /*
+ This Hashtable uses double hashing. There are hashsize buckets in the
+ table, and each bucket can contain 0 or 1 element. We use a bit to mark
+ whether there's been a collision when we inserted multiple elements
+ (ie, an inserted item was hashed at least a second time and we probed
+ this bucket, but it was already in use). Using the collision bit, we
+ can terminate lookups & removes for elements that aren't in the hash
+ table more quickly. We steal the most significant bit from the hash code
+ to store the collision bit.
+
+ Our hash function is of the following form:
+
+ h(key, n) = h1(key) + n*h2(key)
+
+ where n is the number of times we've hit a collided bucket and rehashed
+ (on this particular lookup). Here are our hash functions:
+
+ h1(key) = GetHash(key); // default implementation calls key.GetHashCode();
+ h2(key) = 1 + (((h1(key) >> 5) + 1) % (hashsize - 1));
+
+ The h1 can return any number. h2 must return a number between 1 and
+ hashsize - 1 that is relatively prime to hashsize (not a problem if
+ hashsize is prime). (Knuth's Art of Computer Programming, Vol. 3, p. 528-9)
+ If this is true, then we are guaranteed to visit every bucket in exactly
+ hashsize probes, since the least common multiple of hashsize and h2(key)
+ will be hashsize * h2(key). (This is the first number where adding h2 to
+ h1 mod hashsize will be 0 and we will search the same bucket twice).
+
+ We previously used a different h2(key, n) that was not constant. That is a
+ horrifically bad idea, unless you can prove that series will never produce
+ any identical numbers that overlap when you mod them by hashsize, for all
+ subranges from i to i+hashsize, for all i. It's not worth investigating,
+ since there was no clear benefit from using that hash function, and it was
+ broken.
+
+ For efficiency reasons, we've implemented this by storing h1 and h2 in a
+ temporary, and setting a variable called seed equal to h1. We do a probe,
+ and if we collided, we simply add h2 to seed each time through the loop.
+
+ A good test for h2() is to subclass Hashtable, provide your own implementation
+ of GetHash() that returns a constant, then add many items to the hash table.
+ Make sure Count equals the number of items you inserted.
+
+ Note that when we remove an item from the hash table, we set the key
+ equal to buckets, if there was a collision in this bucket. Otherwise
+ we'd either wipe out the collision bit, or we'd still have an item in
+ the hash table.
+
+ --
+ */
+
+ private const int InitialSize = 3;
+
+ private const string LoadFactorName = "LoadFactor"; // Do not rename (binary serialization)
+ private const string VersionName = "Version"; // Do not rename (binary serialization)
+ private const string ComparerName = "Comparer"; // Do not rename (binary serialization)
+ private const string HashCodeProviderName = "HashCodeProvider"; // Do not rename (binary serialization)
+ private const string HashSizeName = "HashSize"; // Must save buckets.Length. Do not rename (binary serialization)
+ private const string KeysName = "Keys"; // Do not rename (binary serialization)
+ private const string ValuesName = "Values"; // Do not rename (binary serialization)
+ private const string KeyComparerName = "KeyComparer"; // Do not rename (binary serialization)
+
+ // Deleted entries have their key set to buckets
+
+ // The hash table data.
+ // This cannot be serialized
+ private struct bucket
+ {
+ public object key;
+ public object val;
+ public int hash_coll; // Store hash code; sign bit means there was a collision.
+ }
+
+ private bucket[] _buckets;
+
+ // The total number of entries in the hash table.
+ private int _count;
+
+ // The total number of collision bits set in the hashtable
+ private int _occupancy;
+
+ private int _loadsize;
+ private float _loadFactor;
+
+ private volatile int _version;
+ private volatile bool _isWriterInProgress;
+
+ private ICollection _keys;
+ private ICollection _values;
+
+ private IEqualityComparer _keycomparer;
+ private object _syncRoot;
+
+ [Obsolete("Please use EqualityComparer property.")]
+ protected IHashCodeProvider hcp
+ {
+ get
+ {
+ if (_keycomparer is CompatibleComparer)
+ {
+ return ((CompatibleComparer)_keycomparer).HashCodeProvider;
+ }
+ else if (_keycomparer == null)
+ {
+ return null;
+ }
+ else
+ {
+ throw new ArgumentException(SR.Arg_CannotMixComparisonInfrastructure);
+ }
+ }
+ set
+ {
+ if (_keycomparer is CompatibleComparer)
+ {
+ CompatibleComparer keyComparer = (CompatibleComparer)_keycomparer;
+ _keycomparer = new CompatibleComparer(value, keyComparer.Comparer);
+ }
+ else if (_keycomparer == null)
+ {
+ _keycomparer = new CompatibleComparer(value, (IComparer)null);
+ }
+ else
+ {
+ throw new ArgumentException(SR.Arg_CannotMixComparisonInfrastructure);
+ }
+ }
+ }
+
+ [Obsolete("Please use KeyComparer properties.")]
+ protected IComparer comparer
+ {
+ get
+ {
+ if (_keycomparer is CompatibleComparer)
+ {
+ return ((CompatibleComparer)_keycomparer).Comparer;
+ }
+ else if (_keycomparer == null)
+ {
+ return null;
+ }
+ else
+ {
+ throw new ArgumentException(SR.Arg_CannotMixComparisonInfrastructure);
+ }
+ }
+ set
+ {
+ if (_keycomparer is CompatibleComparer)
+ {
+ CompatibleComparer keyComparer = (CompatibleComparer)_keycomparer;
+ _keycomparer = new CompatibleComparer(keyComparer.HashCodeProvider, value);
+ }
+ else if (_keycomparer == null)
+ {
+ _keycomparer = new CompatibleComparer((IHashCodeProvider)null, value);
+ }
+ else
+ {
+ throw new ArgumentException(SR.Arg_CannotMixComparisonInfrastructure);
+ }
+ }
+ }
+
+
+ protected IEqualityComparer EqualityComparer
+ {
+ get
+ {
+ return _keycomparer;
+ }
+ }
+
+ // Note: this constructor is a bogus constructor that does nothing
+ // and is for use only with SyncHashtable.
+ internal Hashtable(bool trash)
+ {
+ }
+
+ // Constructs a new hashtable. The hashtable is created with an initial
+ // capacity of zero and a load factor of 1.0.
+ public Hashtable() : this(0, 1.0f)
+ {
+ }
+
+ // Constructs a new hashtable with the given initial capacity and a load
+ // factor of 1.0. The capacity argument serves as an indication of
+ // the number of entries the hashtable will contain. When this number (or
+ // an approximation) is known, specifying it in the constructor can
+ // eliminate a number of resizing operations that would otherwise be
+ // performed when elements are added to the hashtable.
+ //
+ public Hashtable(int capacity) : this(capacity, 1.0f)
+ {
+ }
+
+ // Constructs a new hashtable with the given initial capacity and load
+ // factor. The capacity argument serves as an indication of the
+ // number of entries the hashtable will contain. When this number (or an
+ // approximation) is known, specifying it in the constructor can eliminate
+ // a number of resizing operations that would otherwise be performed when
+ // elements are added to the hashtable. The loadFactor argument
+ // indicates the maximum ratio of hashtable entries to hashtable buckets.
+ // Smaller load factors cause faster average lookup times at the cost of
+ // increased memory consumption. A load factor of 1.0 generally provides
+ // the best balance between speed and size.
+ //
+ public Hashtable(int capacity, float loadFactor)
+ {
+ if (capacity < 0)
+ throw new ArgumentOutOfRangeException(nameof(capacity), SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (!(loadFactor >= 0.1f && loadFactor <= 1.0f))
+ throw new ArgumentOutOfRangeException(nameof(loadFactor), SR.Format(SR.ArgumentOutOfRange_HashtableLoadFactor, .1, 1.0));
+
+ // Based on perf work, .72 is the optimal load factor for this table.
+ _loadFactor = 0.72f * loadFactor;
+
+ double rawsize = capacity / _loadFactor;
+ if (rawsize > int.MaxValue)
+ throw new ArgumentException(SR.Arg_HTCapacityOverflow, nameof(capacity));
+
+ // Avoid awfully small sizes
+ int hashsize = (rawsize > InitialSize) ? HashHelpers.GetPrime((int)rawsize) : InitialSize;
+ _buckets = new bucket[hashsize];
+
+ _loadsize = (int)(_loadFactor * hashsize);
+ _isWriterInProgress = false;
+ // Based on the current algorithm, loadsize must be less than hashsize.
+ Debug.Assert(_loadsize < hashsize, "Invalid hashtable loadsize!");
+ }
+
+ public Hashtable(int capacity, float loadFactor, IEqualityComparer equalityComparer) : this(capacity, loadFactor)
+ {
+ _keycomparer = equalityComparer;
+ }
+
+ [Obsolete("Please use Hashtable(IEqualityComparer) instead.")]
+ public Hashtable(IHashCodeProvider hcp, IComparer comparer)
+ : this(0, 1.0f, hcp, comparer)
+ {
+ }
+
+ public Hashtable(IEqualityComparer equalityComparer) : this(0, 1.0f, equalityComparer)
+ {
+ }
+
+ [Obsolete("Please use Hashtable(int, IEqualityComparer) instead.")]
+ public Hashtable(int capacity, IHashCodeProvider hcp, IComparer comparer)
+ : this(capacity, 1.0f, hcp, comparer)
+ {
+ }
+
+ public Hashtable(int capacity, IEqualityComparer equalityComparer)
+ : this(capacity, 1.0f, equalityComparer)
+ {
+ }
+
+ // Constructs a new hashtable containing a copy of the entries in the given
+ // dictionary. The hashtable is created with a load factor of 1.0.
+ //
+ public Hashtable(IDictionary d) : this(d, 1.0f)
+ {
+ }
+
+ // Constructs a new hashtable containing a copy of the entries in the given
+ // dictionary. The hashtable is created with the given load factor.
+ //
+ public Hashtable(IDictionary d, float loadFactor)
+ : this(d, loadFactor, (IEqualityComparer)null)
+ {
+ }
+
+ [Obsolete("Please use Hashtable(IDictionary, IEqualityComparer) instead.")]
+ public Hashtable(IDictionary d, IHashCodeProvider hcp, IComparer comparer)
+ : this(d, 1.0f, hcp, comparer)
+ {
+ }
+
+ public Hashtable(IDictionary d, IEqualityComparer equalityComparer)
+ : this(d, 1.0f, equalityComparer)
+ {
+ }
+
+ [Obsolete("Please use Hashtable(int, float, IEqualityComparer) instead.")]
+ public Hashtable(int capacity, float loadFactor, IHashCodeProvider hcp, IComparer comparer)
+ : this(capacity, loadFactor)
+ {
+ if (hcp != null || comparer != null)
+ {
+ _keycomparer = new CompatibleComparer(hcp, comparer);
+ }
+ }
+
+ [Obsolete("Please use Hashtable(IDictionary, float, IEqualityComparer) instead.")]
+ public Hashtable(IDictionary d, float loadFactor, IHashCodeProvider hcp, IComparer comparer)
+ : this((d != null ? d.Count : 0), loadFactor, hcp, comparer)
+ {
+ if (d == null)
+ throw new ArgumentNullException(nameof(d), SR.ArgumentNull_Dictionary);
+
+ IDictionaryEnumerator e = d.GetEnumerator();
+ while (e.MoveNext())
+ Add(e.Key, e.Value);
+ }
+
+ public Hashtable(IDictionary d, float loadFactor, IEqualityComparer equalityComparer)
+ : this((d != null ? d.Count : 0), loadFactor, equalityComparer)
+ {
+ if (d == null)
+ throw new ArgumentNullException(nameof(d), SR.ArgumentNull_Dictionary);
+
+ IDictionaryEnumerator e = d.GetEnumerator();
+ while (e.MoveNext())
+ Add(e.Key, e.Value);
+ }
+
+ protected Hashtable(SerializationInfo info, StreamingContext context)
+ {
+ //We can't do anything with the keys and values until the entire graph has been deserialized
+ //and we have a reasonable estimate that GetHashCode is not going to fail. For the time being,
+ //we'll just cache this. The graph is not valid until OnDeserialization has been called.
+ HashHelpers.SerializationInfoTable.Add(this, info);
+ }
+
+ // ?InitHash? is basically an implementation of classic DoubleHashing (see http://en.wikipedia.org/wiki/Double_hashing)
+ //
+ // 1) The only ?correctness? requirement is that the ?increment? used to probe
+ // a. Be non-zero
+ // b. Be relatively prime to the table size ?hashSize?. (This is needed to insure you probe all entries in the table before you ?wrap? and visit entries already probed)
+ // 2) Because we choose table sizes to be primes, we just need to insure that the increment is 0 < incr < hashSize
+ //
+ // Thus this function would work: Incr = 1 + (seed % (hashSize-1))
+ //
+ // While this works well for ?uniformly distributed? keys, in practice, non-uniformity is common.
+ // In particular in practice we can see ?mostly sequential? where you get long clusters of keys that ?pack?.
+ // To avoid bad behavior you want it to be the case that the increment is ?large? even for ?small? values (because small
+ // values tend to happen more in practice). Thus we multiply ?seed? by a number that will make these small values
+ // bigger (and not hurt large values). We picked HashPrime (101) because it was prime, and if ?hashSize-1? is not a multiple of HashPrime
+ // (enforced in GetPrime), then incr has the potential of being every value from 1 to hashSize-1. The choice was largely arbitrary.
+ //
+ // Computes the hash function: H(key, i) = h1(key) + i*h2(key, hashSize).
+ // The out parameter seed is h1(key), while the out parameter
+ // incr is h2(key, hashSize). Callers of this function should
+ // add incr each time through a loop.
+ private uint InitHash(object key, int hashsize, out uint seed, out uint incr)
+ {
+ // Hashcode must be positive. Also, we must not use the sign bit, since
+ // that is used for the collision bit.
+ uint hashcode = (uint)GetHash(key) & 0x7FFFFFFF;
+ seed = (uint)hashcode;
+ // Restriction: incr MUST be between 1 and hashsize - 1, inclusive for
+ // the modular arithmetic to work correctly. This guarantees you'll
+ // visit every bucket in the table exactly once within hashsize
+ // iterations. Violate this and it'll cause obscure bugs forever.
+ // If you change this calculation for h2(key), update putEntry too!
+ incr = (uint)(1 + ((seed * HashHelpers.HashPrime) % ((uint)hashsize - 1)));
+ return hashcode;
+ }
+
+ // Adds an entry with the given key and value to this hashtable. An
+ // ArgumentException is thrown if the key is null or if the key is already
+ // present in the hashtable.
+ //
+ public virtual void Add(object key, object value)
+ {
+ Insert(key, value, true);
+ }
+
+ // Removes all entries from this hashtable.
+ public virtual void Clear()
+ {
+ Debug.Assert(!_isWriterInProgress, "Race condition detected in usages of Hashtable - multiple threads appear to be writing to a Hashtable instance simultaneously! Don't do that - use Hashtable.Synchronized.");
+
+ if (_count == 0 && _occupancy == 0)
+ return;
+
+ _isWriterInProgress = true;
+ for (int i = 0; i < _buckets.Length; i++)
+ {
+ _buckets[i].hash_coll = 0;
+ _buckets[i].key = null;
+ _buckets[i].val = null;
+ }
+
+ _count = 0;
+ _occupancy = 0;
+ UpdateVersion();
+ _isWriterInProgress = false;
+ }
+
+ // Clone returns a virtually identical copy of this hash table. This does
+ // a shallow copy - the Objects in the table aren't cloned, only the references
+ // to those Objects.
+ public virtual object Clone()
+ {
+ bucket[] lbuckets = _buckets;
+ Hashtable ht = new Hashtable(_count, _keycomparer);
+ ht._version = _version;
+ ht._loadFactor = _loadFactor;
+ ht._count = 0;
+
+ int bucket = lbuckets.Length;
+ while (bucket > 0)
+ {
+ bucket--;
+ object keyv = lbuckets[bucket].key;
+ if ((keyv != null) && (keyv != lbuckets))
+ {
+ ht[keyv] = lbuckets[bucket].val;
+ }
+ }
+
+ return ht;
+ }
+
+ // Checks if this hashtable contains the given key.
+ public virtual bool Contains(object key)
+ {
+ return ContainsKey(key);
+ }
+
+ // Checks if this hashtable contains an entry with the given key. This is
+ // an O(1) operation.
+ //
+ public virtual bool ContainsKey(object key)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key), SR.ArgumentNull_Key);
+ }
+
+ uint seed;
+ uint incr;
+ // Take a snapshot of buckets, in case another thread resizes table
+ bucket[] lbuckets = _buckets;
+ uint hashcode = InitHash(key, lbuckets.Length, out seed, out incr);
+ int ntry = 0;
+
+ bucket b;
+ int bucketNumber = (int)(seed % (uint)lbuckets.Length);
+ do
+ {
+ b = lbuckets[bucketNumber];
+ if (b.key == null)
+ {
+ return false;
+ }
+ if (((b.hash_coll & 0x7FFFFFFF) == hashcode) &&
+ KeyEquals(b.key, key))
+ return true;
+ bucketNumber = (int)(((long)bucketNumber + incr) % (uint)lbuckets.Length);
+ } while (b.hash_coll < 0 && ++ntry < lbuckets.Length);
+ return false;
+ }
+
+
+
+ // Checks if this hashtable contains an entry with the given value. The
+ // values of the entries of the hashtable are compared to the given value
+ // using the Object.Equals method. This method performs a linear
+ // search and is thus be substantially slower than the ContainsKey
+ // method.
+ //
+ public virtual bool ContainsValue(object value)
+ {
+ if (value == null)
+ {
+ for (int i = _buckets.Length; --i >= 0;)
+ {
+ if (_buckets[i].key != null && _buckets[i].key != _buckets && _buckets[i].val == null)
+ return true;
+ }
+ }
+ else
+ {
+ for (int i = _buckets.Length; --i >= 0;)
+ {
+ object val = _buckets[i].val;
+ if (val != null && val.Equals(value))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Copies the keys of this hashtable to a given array starting at a given
+ // index. This method is used by the implementation of the CopyTo method in
+ // the KeyCollection class.
+ private void CopyKeys(Array array, int arrayIndex)
+ {
+ Debug.Assert(array != null);
+ Debug.Assert(array.Rank == 1);
+
+ bucket[] lbuckets = _buckets;
+ for (int i = lbuckets.Length; --i >= 0;)
+ {
+ object keyv = lbuckets[i].key;
+ if ((keyv != null) && (keyv != _buckets))
+ {
+ array.SetValue(keyv, arrayIndex++);
+ }
+ }
+ }
+
+ // Copies the keys of this hashtable to a given array starting at a given
+ // index. This method is used by the implementation of the CopyTo method in
+ // the KeyCollection class.
+ private void CopyEntries(Array array, int arrayIndex)
+ {
+ Debug.Assert(array != null);
+ Debug.Assert(array.Rank == 1);
+
+ bucket[] lbuckets = _buckets;
+ for (int i = lbuckets.Length; --i >= 0;)
+ {
+ object keyv = lbuckets[i].key;
+ if ((keyv != null) && (keyv != _buckets))
+ {
+ DictionaryEntry entry = new DictionaryEntry(keyv, lbuckets[i].val);
+ array.SetValue(entry, arrayIndex++);
+ }
+ }
+ }
+
+ // Copies the values in this hash table to an array at
+ // a given index. Note that this only copies values, and not keys.
+ public virtual void CopyTo(Array array, int arrayIndex)
+ {
+ if (array == null)
+ throw new ArgumentNullException(nameof(array), SR.ArgumentNull_Array);
+ if (array.Rank != 1)
+ throw new ArgumentException(SR.Arg_RankMultiDimNotSupported, nameof(array));
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(arrayIndex), SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (array.Length - arrayIndex < Count)
+ throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall);
+
+ CopyEntries(array, arrayIndex);
+ }
+
+ // Copies the values in this Hashtable to an KeyValuePairs array.
+ // KeyValuePairs is different from Dictionary Entry in that it has special
+ // debugger attributes on its fields.
+
+ internal virtual KeyValuePairs[] ToKeyValuePairsArray()
+ {
+ KeyValuePairs[] array = new KeyValuePairs[_count];
+ int index = 0;
+ bucket[] lbuckets = _buckets;
+ for (int i = lbuckets.Length; --i >= 0;)
+ {
+ object keyv = lbuckets[i].key;
+ if ((keyv != null) && (keyv != _buckets))
+ {
+ array[index++] = new KeyValuePairs(keyv, lbuckets[i].val);
+ }
+ }
+
+ return array;
+ }
+
+
+ // Copies the values of this hashtable to a given array starting at a given
+ // index. This method is used by the implementation of the CopyTo method in
+ // the ValueCollection class.
+ private void CopyValues(Array array, int arrayIndex)
+ {
+ Debug.Assert(array != null);
+ Debug.Assert(array.Rank == 1);
+
+ bucket[] lbuckets = _buckets;
+ for (int i = lbuckets.Length; --i >= 0;)
+ {
+ object keyv = lbuckets[i].key;
+ if ((keyv != null) && (keyv != _buckets))
+ {
+ array.SetValue(lbuckets[i].val, arrayIndex++);
+ }
+ }
+ }
+
+ // Returns the value associated with the given key. If an entry with the
+ // given key is not found, the returned value is null.
+ //
+ public virtual object this[object key]
+ {
+ get
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key), SR.ArgumentNull_Key);
+ }
+
+ uint seed;
+ uint incr;
+
+
+ // Take a snapshot of buckets, in case another thread does a resize
+ bucket[] lbuckets = _buckets;
+ uint hashcode = InitHash(key, lbuckets.Length, out seed, out incr);
+ int ntry = 0;
+
+ bucket b;
+ int bucketNumber = (int)(seed % (uint)lbuckets.Length);
+ do
+ {
+ int currentversion;
+
+ // A read operation on hashtable has three steps:
+ // (1) calculate the hash and find the slot number.
+ // (2) compare the hashcode, if equal, go to step 3. Otherwise end.
+ // (3) compare the key, if equal, go to step 4. Otherwise end.
+ // (4) return the value contained in the bucket.
+ // After step 3 and before step 4. A writer can kick in a remove the old item and add a new one
+ // in the same bucket. So in the reader we need to check if the hash table is modified during above steps.
+ //
+ // Writers (Insert, Remove, Clear) will set 'isWriterInProgress' flag before it starts modifying
+ // the hashtable and will ckear the flag when it is done. When the flag is cleared, the 'version'
+ // will be increased. We will repeat the reading if a writer is in progress or done with the modification
+ // during the read.
+ //
+ // Our memory model guarantee if we pick up the change in bucket from another processor,
+ // we will see the 'isWriterProgress' flag to be true or 'version' is changed in the reader.
+ //
+ SpinWait spin = new SpinWait();
+ while (true)
+ {
+ // this is volatile read, following memory accesses can not be moved ahead of it.
+ currentversion = _version;
+ b = lbuckets[bucketNumber];
+
+ if (!_isWriterInProgress && (currentversion == _version))
+ break;
+
+ spin.SpinOnce();
+ }
+
+ if (b.key == null)
+ {
+ return null;
+ }
+ if (((b.hash_coll & 0x7FFFFFFF) == hashcode) &&
+ KeyEquals(b.key, key))
+ return b.val;
+ bucketNumber = (int)(((long)bucketNumber + incr) % (uint)lbuckets.Length);
+ } while (b.hash_coll < 0 && ++ntry < lbuckets.Length);
+ return null;
+ }
+
+ set
+ {
+ Insert(key, value, false);
+ }
+ }
+
+ // Increases the bucket count of this hashtable. This method is called from
+ // the Insert method when the actual load factor of the hashtable reaches
+ // the upper limit specified when the hashtable was constructed. The number
+ // of buckets in the hashtable is increased to the smallest prime number
+ // that is larger than twice the current number of buckets, and the entries
+ // in the hashtable are redistributed into the new buckets using the cached
+ // hashcodes.
+ private void expand()
+ {
+ int rawsize = HashHelpers.ExpandPrime(_buckets.Length);
+ rehash(rawsize);
+ }
+
+ // We occasionally need to rehash the table to clean up the collision bits.
+ private void rehash()
+ {
+ rehash(_buckets.Length);
+ }
+
+ private void UpdateVersion()
+ {
+ // Version might become negative when version is int.MaxValue, but the oddity will be still be correct.
+ // So we don't need to special case this.
+ _version++;
+ }
+
+ private void rehash(int newsize)
+ {
+ // reset occupancy
+ _occupancy = 0;
+
+ // Don't replace any internal state until we've finished adding to the
+ // new bucket[]. This serves two purposes:
+ // 1) Allow concurrent readers to see valid hashtable contents
+ // at all times
+ // 2) Protect against an OutOfMemoryException while allocating this
+ // new bucket[].
+ bucket[] newBuckets = new bucket[newsize];
+
+ // rehash table into new buckets
+ int nb;
+ for (nb = 0; nb < _buckets.Length; nb++)
+ {
+ bucket oldb = _buckets[nb];
+ if ((oldb.key != null) && (oldb.key != _buckets))
+ {
+ int hashcode = oldb.hash_coll & 0x7FFFFFFF;
+ putEntry(newBuckets, oldb.key, oldb.val, hashcode);
+ }
+ }
+
+ // New bucket[] is good to go - replace buckets and other internal state.
+ _isWriterInProgress = true;
+ _buckets = newBuckets;
+ _loadsize = (int)(_loadFactor * newsize);
+ UpdateVersion();
+ _isWriterInProgress = false;
+ // minimum size of hashtable is 3 now and maximum loadFactor is 0.72 now.
+ Debug.Assert(_loadsize < newsize, "Our current implementation means this is not possible.");
+ }
+
+ // Returns an enumerator for this hashtable.
+ // If modifications made to the hashtable while an enumeration is
+ // in progress, the MoveNext and Current methods of the
+ // enumerator will throw an exception.
+ //
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return new HashtableEnumerator(this, HashtableEnumerator.DictEntry);
+ }
+
+ // Returns a dictionary enumerator for this hashtable.
+ // If modifications made to the hashtable while an enumeration is
+ // in progress, the MoveNext and Current methods of the
+ // enumerator will throw an exception.
+ //
+ public virtual IDictionaryEnumerator GetEnumerator()
+ {
+ return new HashtableEnumerator(this, HashtableEnumerator.DictEntry);
+ }
+
+ // Internal method to get the hash code for an Object. This will call
+ // GetHashCode() on each object if you haven't provided an IHashCodeProvider
+ // instance. Otherwise, it calls hcp.GetHashCode(obj).
+ protected virtual int GetHash(object key)
+ {
+ if (_keycomparer != null)
+ return _keycomparer.GetHashCode(key);
+ return key.GetHashCode();
+ }
+
+ // Is this Hashtable read-only?
+ public virtual bool IsReadOnly
+ {
+ get { return false; }
+ }
+
+ public virtual bool IsFixedSize
+ {
+ get { return false; }
+ }
+
+ // Is this Hashtable synchronized? See SyncRoot property
+ public virtual bool IsSynchronized
+ {
+ get { return false; }
+ }
+
+ // Internal method to compare two keys. If you have provided an IComparer
+ // instance in the constructor, this method will call comparer.Compare(item, key).
+ // Otherwise, it will call item.Equals(key).
+ //
+ protected virtual bool KeyEquals(object item, object key)
+ {
+ Debug.Assert(key != null, "key can't be null here!");
+ if (object.ReferenceEquals(_buckets, item))
+ {
+ return false;
+ }
+
+ if (object.ReferenceEquals(item, key))
+ return true;
+
+ if (_keycomparer != null)
+ return _keycomparer.Equals(item, key);
+ return item == null ? false : item.Equals(key);
+ }
+
+ // Returns a collection representing the keys of this hashtable. The order
+ // in which the returned collection represents the keys is unspecified, but
+ // it is guaranteed to be buckets = newBuckets; the same order in which a collection returned by
+ // GetValues represents the values of the hashtable.
+ //
+ // The returned collection is live in the sense that any changes
+ // to the hash table are reflected in this collection. It is not
+ // a static copy of all the keys in the hash table.
+ //
+ public virtual ICollection Keys
+ {
+ get
+ {
+ if (_keys == null)
+ _keys = new KeyCollection(this);
+ return _keys;
+ }
+ }
+
+ // Returns a collection representing the values of this hashtable. The
+ // order in which the returned collection represents the values is
+ // unspecified, but it is guaranteed to be the same order in which a
+ // collection returned by GetKeys represents the keys of the
+ // hashtable.
+ //
+ // The returned collection is live in the sense that any changes
+ // to the hash table are reflected in this collection. It is not
+ // a static copy of all the keys in the hash table.
+ //
+ public virtual ICollection Values
+ {
+ get
+ {
+ if (_values == null)
+ _values = new ValueCollection(this);
+ return _values;
+ }
+ }
+
+ // Inserts an entry into this hashtable. This method is called from the Set
+ // and Add methods. If the add parameter is true and the given key already
+ // exists in the hashtable, an exception is thrown.
+ private void Insert(object key, object nvalue, bool add)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key), SR.ArgumentNull_Key);
+ }
+
+ if (_count >= _loadsize)
+ {
+ expand();
+ }
+ else if (_occupancy > _loadsize && _count > 100)
+ {
+ rehash();
+ }
+
+ uint seed;
+ uint incr;
+ // Assume we only have one thread writing concurrently. Modify
+ // buckets to contain new data, as long as we insert in the right order.
+ uint hashcode = InitHash(key, _buckets.Length, out seed, out incr);
+ int ntry = 0;
+ int emptySlotNumber = -1; // We use the empty slot number to cache the first empty slot. We chose to reuse slots
+ // create by remove that have the collision bit set over using up new slots.
+ int bucketNumber = (int)(seed % (uint)_buckets.Length);
+ do
+ {
+ // Set emptySlot number to current bucket if it is the first available bucket that we have seen
+ // that once contained an entry and also has had a collision.
+ // We need to search this entire collision chain because we have to ensure that there are no
+ // duplicate entries in the table.
+ if (emptySlotNumber == -1 && (_buckets[bucketNumber].key == _buckets) && (_buckets[bucketNumber].hash_coll < 0))//(((buckets[bucketNumber].hash_coll & unchecked(0x80000000))!=0)))
+ emptySlotNumber = bucketNumber;
+
+ // Insert the key/value pair into this bucket if this bucket is empty and has never contained an entry
+ // OR
+ // This bucket once contained an entry but there has never been a collision
+ if ((_buckets[bucketNumber].key == null) ||
+ (_buckets[bucketNumber].key == _buckets && ((_buckets[bucketNumber].hash_coll & unchecked(0x80000000)) == 0)))
+ {
+ // If we have found an available bucket that has never had a collision, but we've seen an available
+ // bucket in the past that has the collision bit set, use the previous bucket instead
+ if (emptySlotNumber != -1) // Reuse slot
+ bucketNumber = emptySlotNumber;
+
+ // We pretty much have to insert in this order. Don't set hash
+ // code until the value & key are set appropriately.
+ _isWriterInProgress = true;
+ _buckets[bucketNumber].val = nvalue;
+ _buckets[bucketNumber].key = key;
+ _buckets[bucketNumber].hash_coll |= (int)hashcode;
+ _count++;
+ UpdateVersion();
+ _isWriterInProgress = false;
+
+ return;
+ }
+
+ // The current bucket is in use
+ // OR
+ // it is available, but has had the collision bit set and we have already found an available bucket
+ if (((_buckets[bucketNumber].hash_coll & 0x7FFFFFFF) == hashcode) &&
+ KeyEquals(_buckets[bucketNumber].key, key))
+ {
+ if (add)
+ {
+ throw new ArgumentException(SR.Format(SR.Argument_AddingDuplicate__, _buckets[bucketNumber].key, key));
+ }
+ _isWriterInProgress = true;
+ _buckets[bucketNumber].val = nvalue;
+ UpdateVersion();
+ _isWriterInProgress = false;
+
+ return;
+ }
+
+ // The current bucket is full, and we have therefore collided. We need to set the collision bit
+ // unless we have remembered an available slot previously.
+ if (emptySlotNumber == -1)
+ {// We don't need to set the collision bit here since we already have an empty slot
+ if (_buckets[bucketNumber].hash_coll >= 0)
+ {
+ _buckets[bucketNumber].hash_coll |= unchecked((int)0x80000000);
+ _occupancy++;
+ }
+ }
+
+ bucketNumber = (int)(((long)bucketNumber + incr) % (uint)_buckets.Length);
+ } while (++ntry < _buckets.Length);
+
+ // This code is here if and only if there were no buckets without a collision bit set in the entire table
+ if (emptySlotNumber != -1)
+ {
+ // We pretty much have to insert in this order. Don't set hash
+ // code until the value & key are set appropriately.
+ _isWriterInProgress = true;
+ _buckets[emptySlotNumber].val = nvalue;
+ _buckets[emptySlotNumber].key = key;
+ _buckets[emptySlotNumber].hash_coll |= (int)hashcode;
+ _count++;
+ UpdateVersion();
+ _isWriterInProgress = false;
+
+ return;
+ }
+
+ // If you see this assert, make sure load factor & count are reasonable.
+ // Then verify that our double hash function (h2, described at top of file)
+ // meets the requirements described above. You should never see this assert.
+ Debug.Fail("hash table insert failed! Load factor too high, or our double hashing function is incorrect.");
+ throw new InvalidOperationException(SR.InvalidOperation_HashInsertFailed);
+ }
+
+ private void putEntry(bucket[] newBuckets, object key, object nvalue, int hashcode)
+ {
+ Debug.Assert(hashcode >= 0, "hashcode >= 0"); // make sure collision bit (sign bit) wasn't set.
+
+ uint seed = (uint)hashcode;
+ uint incr = unchecked((uint)(1 + ((seed * HashHelpers.HashPrime) % ((uint)newBuckets.Length - 1))));
+ int bucketNumber = (int)(seed % (uint)newBuckets.Length);
+ do
+ {
+ if ((newBuckets[bucketNumber].key == null) || (newBuckets[bucketNumber].key == _buckets))
+ {
+ newBuckets[bucketNumber].val = nvalue;
+ newBuckets[bucketNumber].key = key;
+ newBuckets[bucketNumber].hash_coll |= hashcode;
+ return;
+ }
+
+ if (newBuckets[bucketNumber].hash_coll >= 0)
+ {
+ newBuckets[bucketNumber].hash_coll |= unchecked((int)0x80000000);
+ _occupancy++;
+ }
+ bucketNumber = (int)(((long)bucketNumber + incr) % (uint)newBuckets.Length);
+ } while (true);
+ }
+
+ // Removes an entry from this hashtable. If an entry with the specified
+ // key exists in the hashtable, it is removed. An ArgumentException is
+ // thrown if the key is null.
+ //
+ public virtual void Remove(object key)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key), SR.ArgumentNull_Key);
+ }
+
+ Debug.Assert(!_isWriterInProgress, "Race condition detected in usages of Hashtable - multiple threads appear to be writing to a Hashtable instance simultaneously! Don't do that - use Hashtable.Synchronized.");
+
+ uint seed;
+ uint incr;
+ // Assuming only one concurrent writer, write directly into buckets.
+ uint hashcode = InitHash(key, _buckets.Length, out seed, out incr);
+ int ntry = 0;
+
+ bucket b;
+ int bn = (int)(seed % (uint)_buckets.Length); // bucketNumber
+ do
+ {
+ b = _buckets[bn];
+ if (((b.hash_coll & 0x7FFFFFFF) == hashcode) &&
+ KeyEquals(b.key, key))
+ {
+ _isWriterInProgress = true;
+ // Clear hash_coll field, then key, then value
+ _buckets[bn].hash_coll &= unchecked((int)0x80000000);
+ if (_buckets[bn].hash_coll != 0)
+ {
+ _buckets[bn].key = _buckets;
+ }
+ else
+ {
+ _buckets[bn].key = null;
+ }
+ _buckets[bn].val = null; // Free object references sooner & simplify ContainsValue.
+ _count--;
+ UpdateVersion();
+ _isWriterInProgress = false;
+ return;
+ }
+ bn = (int)(((long)bn + incr) % (uint)_buckets.Length);
+ } while (b.hash_coll < 0 && ++ntry < _buckets.Length);
+ }
+
+ // Returns the object to synchronize on for this hash table.
+ public virtual object SyncRoot
+ {
+ get
+ {
+ if (_syncRoot == null)
+ {
+ System.Threading.Interlocked.CompareExchange<object>(ref _syncRoot, new object(), null);
+ }
+ return _syncRoot;
+ }
+ }
+
+ // Returns the number of associations in this hashtable.
+ //
+ public virtual int Count
+ {
+ get { return _count; }
+ }
+
+ // Returns a thread-safe wrapper for a Hashtable.
+ //
+ public static Hashtable Synchronized(Hashtable table)
+ {
+ if (table == null)
+ throw new ArgumentNullException(nameof(table));
+ return new SyncHashtable(table);
+ }
+
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ {
+ throw new ArgumentNullException(nameof(info));
+ }
+
+ // This is imperfect - it only works well if all other writes are
+ // also using our synchronized wrapper. But it's still a good idea.
+ lock (SyncRoot)
+ {
+ // This method hasn't been fully tweaked to be safe for a concurrent writer.
+ int oldVersion = _version;
+ info.AddValue(LoadFactorName, _loadFactor);
+ info.AddValue(VersionName, _version);
+
+ //
+ // We need to maintain serialization compatibility with Everett and RTM.
+ // If the comparer is null or a compatible comparer, serialize Hashtable
+ // in a format that can be deserialized on Everett and RTM.
+ //
+ // Also, if the Hashtable is using randomized hashing, serialize the old
+ // view of the _keycomparer so perevious frameworks don't see the new types
+#pragma warning disable 618
+ IEqualityComparer keyComparerForSerilization = _keycomparer;
+
+ if (keyComparerForSerilization == null)
+ {
+ info.AddValue(ComparerName, null, typeof(IComparer));
+ info.AddValue(HashCodeProviderName, null, typeof(IHashCodeProvider));
+ }
+ else if (keyComparerForSerilization is CompatibleComparer)
+ {
+ CompatibleComparer c = keyComparerForSerilization as CompatibleComparer;
+ info.AddValue(ComparerName, c.Comparer, typeof(IComparer));
+ info.AddValue(HashCodeProviderName, c.HashCodeProvider, typeof(IHashCodeProvider));
+ }
+ else
+ {
+ info.AddValue(KeyComparerName, keyComparerForSerilization, typeof(IEqualityComparer));
+ }
+#pragma warning restore 618
+
+ info.AddValue(HashSizeName, _buckets.Length); //This is the length of the bucket array.
+ object[] serKeys = new object[_count];
+ object[] serValues = new object[_count];
+ CopyKeys(serKeys, 0);
+ CopyValues(serValues, 0);
+ info.AddValue(KeysName, serKeys, typeof(object[]));
+ info.AddValue(ValuesName, serValues, typeof(object[]));
+
+ // Explicitly check to see if anyone changed the Hashtable while we
+ // were serializing it. That's a race in their code.
+ if (_version != oldVersion)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+ }
+ }
+ }
+
+ //
+ // DeserializationEvent Listener
+ //
+ public virtual void OnDeserialization(object sender)
+ {
+ if (_buckets != null)
+ {
+ // Somebody had a dependency on this hashtable and fixed us up before the ObjectManager got to it.
+ return;
+ }
+
+ SerializationInfo siInfo;
+ HashHelpers.SerializationInfoTable.TryGetValue(this, out siInfo);
+
+ if (siInfo == null)
+ {
+ throw new SerializationException(SR.Serialization_InvalidOnDeser);
+ }
+
+ int hashsize = 0;
+ IComparer c = null;
+
+#pragma warning disable 618
+ IHashCodeProvider hcp = null;
+#pragma warning restore 618
+
+ object[] serKeys = null;
+ object[] serValues = null;
+
+ SerializationInfoEnumerator enumerator = siInfo.GetEnumerator();
+
+ while (enumerator.MoveNext())
+ {
+ switch (enumerator.Name)
+ {
+ case LoadFactorName:
+ _loadFactor = siInfo.GetSingle(LoadFactorName);
+ break;
+ case HashSizeName:
+ hashsize = siInfo.GetInt32(HashSizeName);
+ break;
+ case KeyComparerName:
+ _keycomparer = (IEqualityComparer)siInfo.GetValue(KeyComparerName, typeof(IEqualityComparer));
+ break;
+ case ComparerName:
+ c = (IComparer)siInfo.GetValue(ComparerName, typeof(IComparer));
+ break;
+ case HashCodeProviderName:
+#pragma warning disable 618
+ hcp = (IHashCodeProvider)siInfo.GetValue(HashCodeProviderName, typeof(IHashCodeProvider));
+#pragma warning restore 618
+ break;
+ case KeysName:
+ serKeys = (object[])siInfo.GetValue(KeysName, typeof(object[]));
+ break;
+ case ValuesName:
+ serValues = (object[])siInfo.GetValue(ValuesName, typeof(object[]));
+ break;
+ }
+ }
+
+ _loadsize = (int)(_loadFactor * hashsize);
+
+ // V1 object doesn't has _keycomparer field.
+ if ((_keycomparer == null) && ((c != null) || (hcp != null)))
+ {
+ _keycomparer = new CompatibleComparer(hcp, c);
+ }
+
+ _buckets = new bucket[hashsize];
+
+ if (serKeys == null)
+ {
+ throw new SerializationException(SR.Serialization_MissingKeys);
+ }
+ if (serValues == null)
+ {
+ throw new SerializationException(SR.Serialization_MissingValues);
+ }
+ if (serKeys.Length != serValues.Length)
+ {
+ throw new SerializationException(SR.Serialization_KeyValueDifferentSizes);
+ }
+ for (int i = 0; i < serKeys.Length; i++)
+ {
+ if (serKeys[i] == null)
+ {
+ throw new SerializationException(SR.Serialization_NullKey);
+ }
+ Insert(serKeys[i], serValues[i], true);
+ }
+
+ _version = siInfo.GetInt32(VersionName);
+
+ HashHelpers.SerializationInfoTable.Remove(this);
+ }
+
+ // Implements a Collection for the keys of a hashtable. An instance of this
+ // class is created by the GetKeys method of a hashtable.
+ private class KeyCollection : ICollection
+ {
+ private Hashtable _hashtable;
+
+ internal KeyCollection(Hashtable hashtable)
+ {
+ _hashtable = hashtable;
+ }
+
+ public virtual void CopyTo(Array array, int arrayIndex)
+ {
+ if (array == null)
+ throw new ArgumentNullException(nameof(array));
+ if (array.Rank != 1)
+ throw new ArgumentException(SR.Arg_RankMultiDimNotSupported, nameof(array));
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(arrayIndex), SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (array.Length - arrayIndex < _hashtable._count)
+ throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall);
+ _hashtable.CopyKeys(array, arrayIndex);
+ }
+
+ public virtual IEnumerator GetEnumerator()
+ {
+ return new HashtableEnumerator(_hashtable, HashtableEnumerator.Keys);
+ }
+
+ public virtual bool IsSynchronized
+ {
+ get { return _hashtable.IsSynchronized; }
+ }
+
+ public virtual object SyncRoot
+ {
+ get { return _hashtable.SyncRoot; }
+ }
+
+ public virtual int Count
+ {
+ get { return _hashtable._count; }
+ }
+ }
+
+ // Implements a Collection for the values of a hashtable. An instance of
+ // this class is created by the GetValues method of a hashtable.
+ private class ValueCollection : ICollection
+ {
+ private Hashtable _hashtable;
+
+ internal ValueCollection(Hashtable hashtable)
+ {
+ _hashtable = hashtable;
+ }
+
+ public virtual void CopyTo(Array array, int arrayIndex)
+ {
+ if (array == null)
+ throw new ArgumentNullException(nameof(array));
+ if (array.Rank != 1)
+ throw new ArgumentException(SR.Arg_RankMultiDimNotSupported, nameof(array));
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException(nameof(arrayIndex), SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (array.Length - arrayIndex < _hashtable._count)
+ throw new ArgumentException(SR.Arg_ArrayPlusOffTooSmall);
+ _hashtable.CopyValues(array, arrayIndex);
+ }
+
+ public virtual IEnumerator GetEnumerator()
+ {
+ return new HashtableEnumerator(_hashtable, HashtableEnumerator.Values);
+ }
+
+ public virtual bool IsSynchronized
+ {
+ get { return _hashtable.IsSynchronized; }
+ }
+
+ public virtual object SyncRoot
+ {
+ get { return _hashtable.SyncRoot; }
+ }
+
+ public virtual int Count
+ {
+ get { return _hashtable._count; }
+ }
+ }
+
+ // Synchronized wrapper for hashtable
+ private class SyncHashtable : Hashtable, IEnumerable
+ {
+ protected Hashtable _table;
+
+ internal SyncHashtable(Hashtable table) : base(false)
+ {
+ _table = table;
+ }
+
+ internal SyncHashtable(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ public override int Count
+ {
+ get { return _table.Count; }
+ }
+
+ public override bool IsReadOnly
+ {
+ get { return _table.IsReadOnly; }
+ }
+
+ public override bool IsFixedSize
+ {
+ get { return _table.IsFixedSize; }
+ }
+
+ public override bool IsSynchronized
+ {
+ get { return true; }
+ }
+
+ public override object this[object key]
+ {
+ get
+ {
+ return _table[key];
+ }
+ set
+ {
+ lock (_table.SyncRoot)
+ {
+ _table[key] = value;
+ }
+ }
+ }
+
+ public override object SyncRoot
+ {
+ get { return _table.SyncRoot; }
+ }
+
+ public override void Add(object key, object value)
+ {
+ lock (_table.SyncRoot)
+ {
+ _table.Add(key, value);
+ }
+ }
+
+ public override void Clear()
+ {
+ lock (_table.SyncRoot)
+ {
+ _table.Clear();
+ }
+ }
+
+ public override bool Contains(object key)
+ {
+ return _table.Contains(key);
+ }
+
+ public override bool ContainsKey(object key)
+ {
+ if (key == null)
+ {
+ throw new ArgumentNullException(nameof(key), SR.ArgumentNull_Key);
+ }
+ return _table.ContainsKey(key);
+ }
+
+ public override bool ContainsValue(object key)
+ {
+ lock (_table.SyncRoot)
+ {
+ return _table.ContainsValue(key);
+ }
+ }
+
+ public override void CopyTo(Array array, int arrayIndex)
+ {
+ lock (_table.SyncRoot)
+ {
+ _table.CopyTo(array, arrayIndex);
+ }
+ }
+
+ public override object Clone()
+ {
+ lock (_table.SyncRoot)
+ {
+ return Hashtable.Synchronized((Hashtable)_table.Clone());
+ }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return _table.GetEnumerator();
+ }
+
+ public override IDictionaryEnumerator GetEnumerator()
+ {
+ return _table.GetEnumerator();
+ }
+
+ public override ICollection Keys
+ {
+ get
+ {
+ lock (_table.SyncRoot)
+ {
+ return _table.Keys;
+ }
+ }
+ }
+
+ public override ICollection Values
+ {
+ get
+ {
+ lock (_table.SyncRoot)
+ {
+ return _table.Values;
+ }
+ }
+ }
+
+ public override void Remove(object key)
+ {
+ lock (_table.SyncRoot)
+ {
+ _table.Remove(key);
+ }
+ }
+
+ public override void OnDeserialization(object sender)
+ {
+ // Does nothing. We have to implement this because our parent HT implements it,
+ // but it doesn't do anything meaningful. The real work will be done when we
+ // call OnDeserialization on our parent table.
+ }
+
+ internal override KeyValuePairs[] ToKeyValuePairsArray()
+ {
+ return _table.ToKeyValuePairsArray();
+ }
+ }
+
+
+ // Implements an enumerator for a hashtable. The enumerator uses the
+ // internal version number of the hashtable to ensure that no modifications
+ // are made to the hashtable while an enumeration is in progress.
+ private class HashtableEnumerator : IDictionaryEnumerator, ICloneable
+ {
+ private Hashtable _hashtable;
+ private int _bucket;
+ private int _version;
+ private bool _current;
+ private int _getObjectRetType; // What should GetObject return?
+ private object _currentKey;
+ private object _currentValue;
+
+ internal const int Keys = 1;
+ internal const int Values = 2;
+ internal const int DictEntry = 3;
+
+ internal HashtableEnumerator(Hashtable hashtable, int getObjRetType)
+ {
+ _hashtable = hashtable;
+ _bucket = hashtable._buckets.Length;
+ _version = hashtable._version;
+ _current = false;
+ _getObjectRetType = getObjRetType;
+ }
+
+ public object Clone() => MemberwiseClone();
+
+ public virtual object Key
+ {
+ get
+ {
+ if (_current == false)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted);
+ return _currentKey;
+ }
+ }
+
+ public virtual bool MoveNext()
+ {
+ if (_version != _hashtable._version)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+ while (_bucket > 0)
+ {
+ _bucket--;
+ object keyv = _hashtable._buckets[_bucket].key;
+ if ((keyv != null) && (keyv != _hashtable._buckets))
+ {
+ _currentKey = keyv;
+ _currentValue = _hashtable._buckets[_bucket].val;
+ _current = true;
+ return true;
+ }
+ }
+ _current = false;
+ return false;
+ }
+
+ public virtual DictionaryEntry Entry
+ {
+ get
+ {
+ if (_current == false)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
+ return new DictionaryEntry(_currentKey, _currentValue);
+ }
+ }
+
+
+ public virtual object Current
+ {
+ get
+ {
+ if (_current == false)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
+
+ if (_getObjectRetType == Keys)
+ return _currentKey;
+ else if (_getObjectRetType == Values)
+ return _currentValue;
+ else
+ return new DictionaryEntry(_currentKey, _currentValue);
+ }
+ }
+
+ public virtual object Value
+ {
+ get
+ {
+ if (_current == false)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumOpCantHappen);
+ return _currentValue;
+ }
+ }
+
+ public virtual void Reset()
+ {
+ if (_version != _hashtable._version)
+ throw new InvalidOperationException(SR.InvalidOperation_EnumFailedVersion);
+ _current = false;
+ _bucket = _hashtable._buckets.Length;
+ _currentKey = null;
+ _currentValue = null;
+ }
+ }
+
+ // internal debug view class for hashtable
+ internal class HashtableDebugView
+ {
+ private Hashtable _hashtable;
+
+ public HashtableDebugView(Hashtable hashtable)
+ {
+ if (hashtable == null)
+ {
+ throw new ArgumentNullException(nameof(hashtable));
+ }
+
+ _hashtable = hashtable;
+ }
+
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public KeyValuePairs[] Items
+ {
+ get
+ {
+ return _hashtable.ToKeyValuePairsArray();
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/ICollection.cs b/src/System.Private.CoreLib/shared/System/Collections/ICollection.cs
index f0149020d..65e37c738 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/ICollection.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/ICollection.cs
@@ -10,7 +10,7 @@ namespace System.Collections
// synchronization methods.
public interface ICollection : IEnumerable
{
- // Interfaces are not serialable
+ // Interfaces are not serializable
// CopyTo copies a collection into an Array, starting at a particular
// index into the array.
//
@@ -49,12 +49,12 @@ namespace System.Collections
// or your language's equivalent to the C# lock keyword as mentioned
// above.
//
- // For collections with no publically available underlying store, the
+ // For collections with no publicly available underlying store, the
// expected implementation is to simply return the this pointer. Note
// that the this pointer may not be sufficient for collections that
// wrap other collections; those should return the underlying
// collection's SyncRoot property.
- Object SyncRoot
+ object SyncRoot
{ get; }
// Is this collection synchronized (i.e., thread-safe)? If you want a
diff --git a/src/System.Private.CoreLib/shared/System/Collections/IComparer.cs b/src/System.Private.CoreLib/shared/System/Collections/IComparer.cs
index cef91c3ff..38bab78b3 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/IComparer.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/IComparer.cs
@@ -17,6 +17,6 @@ namespace System.Collections
// value less than zero if x is less than y, zero if x is equal to y, or a
// value greater than zero if x is greater than y.
//
- int Compare(Object x, Object y);
+ int Compare(object x, object y);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/IDictionary.cs b/src/System.Private.CoreLib/shared/System/Collections/IDictionary.cs
index b934c2399..b077c9192 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/IDictionary.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/IDictionary.cs
@@ -15,7 +15,7 @@ namespace System.Collections
// Interfaces are not serializable
// The Item property provides methods to read and edit entries
// in the Dictionary.
- Object this[Object key]
+ object this[object key]
{
get;
set;
@@ -35,11 +35,11 @@ namespace System.Collections
// Returns whether this dictionary contains a particular key.
//
- bool Contains(Object key);
+ bool Contains(object key);
// Adds a key-value pair to the dictionary.
//
- void Add(Object key, Object value);
+ void Add(object key, object value);
// Removes all pairs from the dictionary.
void Clear();
@@ -55,6 +55,6 @@ namespace System.Collections
// Removes a particular key from the dictionary.
//
- void Remove(Object key);
+ void Remove(object key);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/IDictionaryEnumerator.cs b/src/System.Private.CoreLib/shared/System/Collections/IDictionaryEnumerator.cs
index 451cf6897..0cf6aaa15 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/IDictionaryEnumerator.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/IDictionaryEnumerator.cs
@@ -39,7 +39,7 @@ namespace System.Collections
// GetKey with no intervening calls to GetNext will return
// the same object.
//
- Object Key
+ object Key
{
get;
}
@@ -50,7 +50,7 @@ namespace System.Collections
// to GetValue with no intervening calls to GetNext will
// return the same object.
//
- Object Value
+ object Value
{
get;
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/IEnumerator.cs b/src/System.Private.CoreLib/shared/System/Collections/IEnumerator.cs
index 2c2c2e4a9..29a6f475b 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/IEnumerator.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/IEnumerator.cs
@@ -25,7 +25,7 @@ namespace System.Collections
// GetCurrent with no intervening calls to MoveNext
// will return the same object.
//
- Object Current
+ object Current
{
get;
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/IEqualityComparer.cs b/src/System.Private.CoreLib/shared/System/Collections/IEqualityComparer.cs
index 35513f577..9b5476896 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/IEqualityComparer.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/IEqualityComparer.cs
@@ -10,7 +10,7 @@ namespace System.Collections
// that can be consumed by some of the common collections.
public interface IEqualityComparer
{
- bool Equals(Object x, Object y);
- int GetHashCode(Object obj);
+ bool Equals(object x, object y);
+ int GetHashCode(object obj);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/IHashCodeProvider.cs b/src/System.Private.CoreLib/shared/System/Collections/IHashCodeProvider.cs
new file mode 100644
index 000000000..7d6c63f9f
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Collections/IHashCodeProvider.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Collections
+{
+ /// <summary>
+ /// Provides a mechanism for a <see cref="Hashtable"/> user to override the default
+ /// GetHashCode() function on Objects, providing their own hash function.
+ /// </summary>
+ [Obsolete("Please use IEqualityComparer instead.")]
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public interface IHashCodeProvider
+ {
+ /// <summary>Returns a hash code for the given object.</summary>
+ int GetHashCode(object obj);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/IList.cs b/src/System.Private.CoreLib/shared/System/Collections/IList.cs
index 0110eca1f..25d3b1922 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/IList.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/IList.cs
@@ -12,7 +12,7 @@ namespace System.Collections
public interface IList : ICollection
{
// The Item property provides methods to read and edit entries in the List.
- Object this[int index]
+ object this[int index]
{
get;
set;
@@ -22,10 +22,10 @@ namespace System.Collections
// implementation-dependent, so while ArrayList may always insert
// in the last available location, a SortedList most likely would not.
// The return value is the position the new element was inserted in.
- int Add(Object value);
+ int Add(object value);
// Returns whether the list contains a particular item.
- bool Contains(Object value);
+ bool Contains(object value);
// Removes all items from the list.
void Clear();
@@ -42,16 +42,16 @@ namespace System.Collections
// Returns the index of a particular item, if it is in the list.
// Returns -1 if the item isn't in the list.
- int IndexOf(Object value);
+ int IndexOf(object value);
// Inserts value into the list at position index.
// index must be non-negative and less than or equal to the
// number of elements in the list. If index equals the number
// of items in the list, then value is appended to the end.
- void Insert(int index, Object value);
+ void Insert(int index, object value);
// Removes an item from the list.
- void Remove(Object value);
+ void Remove(object value);
// Removes the item at position index.
void RemoveAt(int index);
diff --git a/src/System.Private.CoreLib/shared/System/Collections/IStructuralComparable.cs b/src/System.Private.CoreLib/shared/System/Collections/IStructuralComparable.cs
index a5e4834b9..9041e0d5f 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/IStructuralComparable.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/IStructuralComparable.cs
@@ -8,6 +8,6 @@ namespace System.Collections
{
public interface IStructuralComparable
{
- Int32 CompareTo(Object other, IComparer comparer);
+ int CompareTo(object other, IComparer comparer);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/IStructuralEquatable.cs b/src/System.Private.CoreLib/shared/System/Collections/IStructuralEquatable.cs
index 4e61d5e75..1784da58c 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/IStructuralEquatable.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/IStructuralEquatable.cs
@@ -6,7 +6,7 @@ namespace System.Collections
{
public interface IStructuralEquatable
{
- Boolean Equals(Object other, IEqualityComparer comparer);
+ bool Equals(object other, IEqualityComparer comparer);
int GetHashCode(IEqualityComparer comparer);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/KeyValuePairs.cs b/src/System.Private.CoreLib/shared/System/Collections/KeyValuePairs.cs
new file mode 100644
index 000000000..9ec6365b9
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Collections/KeyValuePairs.cs
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Class: KeyValuePairs
+**
+** Purpose: Defines key/value pairs for displaying items
+** in a collection class under the debugger.
+**
+===========================================================*/
+
+using System.Diagnostics;
+
+namespace System.Collections
+{
+ [DebuggerDisplay("{_value}", Name = "[{_key}]")]
+ internal class KeyValuePairs
+ {
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private readonly object _key;
+
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private readonly object _value;
+
+ public KeyValuePairs(object key, object value)
+ {
+ _value = value;
+ _key = key;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/ListDictionaryInternal.cs b/src/System.Private.CoreLib/shared/System/Collections/ListDictionaryInternal.cs
index a8b7a187d..6045778ab 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/ListDictionaryInternal.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/ListDictionaryInternal.cs
@@ -20,24 +20,20 @@ namespace System.Collections
/// This should not be used if performance is important for large numbers of elements.
[Serializable]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
-#if CORERT
- public
-#else
- internal
-#endif
- class ListDictionaryInternal : IDictionary
+ // Needs to be public to support binary serialization compatibility
+ public class ListDictionaryInternal : IDictionary
{
private DictionaryNode head; // Do not rename (binary serialization)
private int version; // Do not rename (binary serialization)
private int count; // Do not rename (binary serialization)
[NonSerialized]
- private Object _syncRoot;
+ private object _syncRoot;
public ListDictionaryInternal()
{
}
- public Object this[Object key]
+ public object this[object key]
{
get
{
@@ -138,13 +134,13 @@ namespace System.Collections
}
}
- public Object SyncRoot
+ public object SyncRoot
{
get
{
if (_syncRoot == null)
{
- System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ System.Threading.Interlocked.CompareExchange<object>(ref _syncRoot, new object(), null);
}
return _syncRoot;
}
@@ -158,7 +154,7 @@ namespace System.Collections
}
}
- public void Add(Object key, Object value)
+ public void Add(object key, object value)
{
if (key == null)
{
@@ -205,7 +201,7 @@ namespace System.Collections
version++;
}
- public bool Contains(Object key)
+ public bool Contains(object key)
{
if (key == null)
{
@@ -252,7 +248,7 @@ namespace System.Collections
return new NodeEnumerator(this);
}
- public void Remove(Object key)
+ public void Remove(object key)
{
if (key == null)
{
@@ -300,7 +296,7 @@ namespace System.Collections
current = null;
}
- public Object Current
+ public object Current
{
get
{
@@ -320,7 +316,7 @@ namespace System.Collections
}
}
- public Object Key
+ public object Key
{
get
{
@@ -332,7 +328,7 @@ namespace System.Collections
}
}
- public Object Value
+ public object Value
{
get
{
@@ -426,7 +422,7 @@ namespace System.Collections
}
}
- Object ICollection.SyncRoot
+ object ICollection.SyncRoot
{
get
{
@@ -457,7 +453,7 @@ namespace System.Collections
current = null;
}
- public Object Current
+ public object Current
{
get
{
@@ -505,8 +501,8 @@ namespace System.Collections
[Serializable]
private class DictionaryNode
{
- public Object key;
- public Object value;
+ public object key;
+ public object value;
public DictionaryNode next;
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Collections/ObjectModel/Collection.cs b/src/System.Private.CoreLib/shared/System/Collections/ObjectModel/Collection.cs
index 1e1b2c795..53272b386 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/ObjectModel/Collection.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/ObjectModel/Collection.cs
@@ -15,7 +15,7 @@ namespace System.Collections.ObjectModel
{
private IList<T> items; // Do not rename (binary serialization)
[NonSerialized]
- private Object _syncRoot;
+ private object _syncRoot;
public Collection()
{
@@ -195,7 +195,7 @@ namespace System.Collections.ObjectModel
}
else
{
- System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ System.Threading.Interlocked.CompareExchange<object>(ref _syncRoot, new object(), null);
}
}
return _syncRoot;
diff --git a/src/System.Private.CoreLib/shared/System/Collections/ObjectModel/ReadOnlyCollection.cs b/src/System.Private.CoreLib/shared/System/Collections/ObjectModel/ReadOnlyCollection.cs
index dbf88d8b8..3c4eda204 100644
--- a/src/System.Private.CoreLib/shared/System/Collections/ObjectModel/ReadOnlyCollection.cs
+++ b/src/System.Private.CoreLib/shared/System/Collections/ObjectModel/ReadOnlyCollection.cs
@@ -15,7 +15,7 @@ namespace System.Collections.ObjectModel
{
private IList<T> list; // Do not rename (binary serialization)
[NonSerialized]
- private Object _syncRoot;
+ private object _syncRoot;
public ReadOnlyCollection(IList<T> list)
{
@@ -127,7 +127,7 @@ namespace System.Collections.ObjectModel
}
else
{
- System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ System.Threading.Interlocked.CompareExchange<object>(ref _syncRoot, new object(), null);
}
}
return _syncRoot;
diff --git a/src/System.Private.CoreLib/shared/System/ComponentModel/DefaultValueAttribute.cs b/src/System.Private.CoreLib/shared/System/ComponentModel/DefaultValueAttribute.cs
index 3cdc90729..5f7108a52 100644
--- a/src/System.Private.CoreLib/shared/System/ComponentModel/DefaultValueAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/ComponentModel/DefaultValueAttribute.cs
@@ -2,11 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-using System.ComponentModel;
-using System.Diagnostics;
using System.Globalization;
-using System.Runtime.InteropServices;
+using System.Threading;
namespace System.ComponentModel
{
@@ -23,6 +20,9 @@ namespace System.ComponentModel
/// </devdoc>
private object _value;
+ // Delegate ad hoc created 'TypeDescriptor.ConvertFromInvariantString' reflection object cache
+ static object s_convertFromInvariantString;
+
/// <devdoc>
/// <para>Initializes a new instance of the <see cref='System.ComponentModel.DefaultValueAttribute'/> class, converting the
/// specified value to the
@@ -36,7 +36,11 @@ namespace System.ComponentModel
// load an otherwise normal class.
try
{
- if (type.IsSubclassOf(typeof(Enum)))
+ if (TryConvertFromInvariantString(type, value, out object convertedValue))
+ {
+ _value = convertedValue;
+ }
+ else if (type.IsSubclassOf(typeof(Enum)))
{
_value = Enum.Parse(type, value, true);
}
@@ -48,6 +52,28 @@ namespace System.ComponentModel
{
_value = Convert.ChangeType(value, type, CultureInfo.InvariantCulture);
}
+
+ return;
+
+ // Looking for ad hoc created TypeDescriptor.ConvertFromInvariantString(Type, string)
+ bool TryConvertFromInvariantString(Type typeToConvert, string stringValue, out object conversionResult)
+ {
+ conversionResult = null;
+
+ // lazy init reflection objects
+ if (s_convertFromInvariantString == null)
+ {
+ Type typeDescriptorType = Type.GetType("System.ComponentModel.TypeDescriptor, System.ComponentModel.TypeConverter", throwOnError: false);
+ Volatile.Write(ref s_convertFromInvariantString, typeDescriptorType == null ? new object() : Delegate.CreateDelegate(typeof(Func<Type, string, object>), typeDescriptorType, "ConvertFromInvariantString", ignoreCase: false));
+ }
+
+ if (!(s_convertFromInvariantString is Func<Type, string, object> convertFromInvariantString))
+ return false;
+
+ conversionResult = convertFromInvariantString(typeToConvert, stringValue);
+
+ return true;
+ }
}
catch
{
diff --git a/src/System.Private.CoreLib/shared/System/Convert.Base64.cs b/src/System.Private.CoreLib/shared/System/Convert.Base64.cs
new file mode 100644
index 000000000..7e2aee31b
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Convert.Base64.cs
@@ -0,0 +1,217 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Internal.Runtime.CompilerServices;
+
+namespace System
+{
+ public static partial class Convert
+ {
+ /// <summary>
+ /// Decode the span of UTF-16 encoded text represented as base 64 into binary data.
+ /// If the input is not a multiple of 4, or contains illegal characters, it will decode as much as it can, to the largest possible multiple of 4.
+ /// This invariant allows continuation of the parse with a slower, whitespace-tolerant algorithm.
+ ///
+ /// <param name="utf16">The input span which contains UTF-16 encoded text in base 64 that needs to be decoded.</param>
+ /// <param name="bytes">The output span which contains the result of the operation, i.e. the decoded binary data.</param>
+ /// <param name="consumed">The number of input bytes consumed during the operation. This can be used to slice the input for subsequent calls, if necessary.</param>
+ /// <param name="written">The number of bytes written into the output span. This can be used to slice the output for subsequent calls, if necessary.</param>
+ /// <returns>Returns:
+ /// - true - The entire input span was successfully parsed.
+ /// - false - Only a part of the input span was successfully parsed. Failure causes may include embedded or trailing whitespace,
+ /// other illegal Base64 characters, trailing characters after an encoding pad ('='), an input span whose length is not divisible by 4
+ /// or a destination span that's too small. <paramref name="consumed"/> and <paramref name="written"/> are set so that
+ /// parsing can continue with a slower whitespace-tolerant algorithm.
+ ///
+ /// Note: This is a cut down version of the implementation of Base64.DecodeFromUtf8(), modified the accept UTF16 chars and act as a fast-path
+ /// helper for the Convert routines when the input string contains no whitespace.
+ ///
+ /// </summary>
+ private static bool TryDecodeFromUtf16(ReadOnlySpan<char> utf16, Span<byte> bytes, out int consumed, out int written)
+ {
+ ref char srcChars = ref MemoryMarshal.GetReference(utf16);
+ ref byte destBytes = ref MemoryMarshal.GetReference(bytes);
+
+ int srcLength = utf16.Length & ~0x3; // only decode input up to the closest multiple of 4.
+ int destLength = bytes.Length;
+
+ int sourceIndex = 0;
+ int destIndex = 0;
+
+ if (utf16.Length == 0)
+ goto DoneExit;
+
+ ref sbyte decodingMap = ref s_decodingMap[0];
+
+ // Last bytes could have padding characters, so process them separately and treat them as valid.
+ const int skipLastChunk = 4;
+
+ int maxSrcLength;
+ if (destLength >= (srcLength >> 2) * 3)
+ {
+ maxSrcLength = srcLength - skipLastChunk;
+ }
+ else
+ {
+ // This should never overflow since destLength here is less than int.MaxValue / 4 * 3 (i.e. 1610612733)
+ // Therefore, (destLength / 3) * 4 will always be less than 2147483641
+ maxSrcLength = (destLength / 3) * 4;
+ }
+
+ while (sourceIndex < maxSrcLength)
+ {
+ int result = Decode(ref Unsafe.Add(ref srcChars, sourceIndex), ref decodingMap);
+ if (result < 0)
+ goto InvalidExit;
+ WriteThreeLowOrderBytes(ref Unsafe.Add(ref destBytes, destIndex), result);
+ destIndex += 3;
+ sourceIndex += 4;
+ }
+
+ if (maxSrcLength != srcLength - skipLastChunk)
+ goto InvalidExit;
+
+ // If input is less than 4 bytes, srcLength == sourceIndex == 0
+ // If input is not a multiple of 4, sourceIndex == srcLength != 0
+ if (sourceIndex == srcLength)
+ {
+ goto InvalidExit;
+ }
+
+ int i0 = Unsafe.Add(ref srcChars, srcLength - 4);
+ int i1 = Unsafe.Add(ref srcChars, srcLength - 3);
+ int i2 = Unsafe.Add(ref srcChars, srcLength - 2);
+ int i3 = Unsafe.Add(ref srcChars, srcLength - 1);
+ if (((i0 | i1 | i2 | i3) & 0xffffff00) != 0)
+ goto InvalidExit;
+
+ i0 = Unsafe.Add(ref decodingMap, i0);
+ i1 = Unsafe.Add(ref decodingMap, i1);
+
+ i0 <<= 18;
+ i1 <<= 12;
+
+ i0 |= i1;
+
+ if (i3 != EncodingPad)
+ {
+ i2 = Unsafe.Add(ref decodingMap, i2);
+ i3 = Unsafe.Add(ref decodingMap, i3);
+
+ i2 <<= 6;
+
+ i0 |= i3;
+ i0 |= i2;
+
+ if (i0 < 0)
+ goto InvalidExit;
+ if (destIndex > destLength - 3)
+ goto InvalidExit;
+ WriteThreeLowOrderBytes(ref Unsafe.Add(ref destBytes, destIndex), i0);
+ destIndex += 3;
+ }
+ else if (i2 != EncodingPad)
+ {
+ i2 = Unsafe.Add(ref decodingMap, i2);
+
+ i2 <<= 6;
+
+ i0 |= i2;
+
+ if (i0 < 0)
+ goto InvalidExit;
+ if (destIndex > destLength - 2)
+ goto InvalidExit;
+ Unsafe.Add(ref destBytes, destIndex) = (byte)(i0 >> 16);
+ Unsafe.Add(ref destBytes, destIndex + 1) = (byte)(i0 >> 8);
+ destIndex += 2;
+ }
+ else
+ {
+ if (i0 < 0)
+ goto InvalidExit;
+ if (destIndex > destLength - 1)
+ goto InvalidExit;
+ Unsafe.Add(ref destBytes, destIndex) = (byte)(i0 >> 16);
+ destIndex += 1;
+ }
+
+ sourceIndex += 4;
+
+ if (srcLength != utf16.Length)
+ goto InvalidExit;
+
+ DoneExit:
+ consumed = sourceIndex;
+ written = destIndex;
+ return true;
+
+ InvalidExit:
+ consumed = sourceIndex;
+ written = destIndex;
+ Debug.Assert((consumed % 4) == 0);
+ return false;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static int Decode(ref char encodedChars, ref sbyte decodingMap)
+ {
+ int i0 = encodedChars;
+ int i1 = Unsafe.Add(ref encodedChars, 1);
+ int i2 = Unsafe.Add(ref encodedChars, 2);
+ int i3 = Unsafe.Add(ref encodedChars, 3);
+
+ if (((i0 | i1 | i2 | i3) & 0xffffff00) != 0)
+ return -1; // One or more chars falls outside the 00..ff range. This cannot be a valid Base64 character.
+
+ i0 = Unsafe.Add(ref decodingMap, i0);
+ i1 = Unsafe.Add(ref decodingMap, i1);
+ i2 = Unsafe.Add(ref decodingMap, i2);
+ i3 = Unsafe.Add(ref decodingMap, i3);
+
+ i0 <<= 18;
+ i1 <<= 12;
+ i2 <<= 6;
+
+ i0 |= i3;
+ i1 |= i2;
+
+ i0 |= i1;
+ return i0;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void WriteThreeLowOrderBytes(ref byte destination, int value)
+ {
+ destination = (byte)(value >> 16);
+ Unsafe.Add(ref destination, 1) = (byte)(value >> 8);
+ Unsafe.Add(ref destination, 2) = (byte)value;
+ }
+
+ // Pre-computing this table using a custom string(s_characters) and GenerateDecodingMapAndVerify (found in tests)
+ private static readonly sbyte[] s_decodingMap = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, //62 is placed at index 43 (for +), 63 at index 47 (for /)
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, //52-61 are placed at index 48-57 (for 0-9), 64 at index 61 (for =)
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, //0-25 are placed at index 65-90 (for A-Z)
+ -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, //26-51 are placed at index 97-122 (for a-z)
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Bytes over 122 ('z') are invalid and cannot be decoded
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // Hence, padding the map with 255, which indicates invalid input
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ };
+
+ private const byte EncodingPad = (byte)'='; // '=', for padding
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Convert.cs b/src/System.Private.CoreLib/shared/System/Convert.cs
index 756bf17fc..1c303d248 100644
--- a/src/System.Private.CoreLib/shared/System/Convert.cs
+++ b/src/System.Private.CoreLib/shared/System/Convert.cs
@@ -96,31 +96,31 @@ namespace System
// When passed Value.DBNull, the Value.ToXXX() methods all throw an
// InvalidCastException.
- public static class Convert
+ public static partial class Convert
{
//A typeof operation is fairly expensive (does a system call), so we'll cache these here
//statically. These are exactly lined up with the TypeCode, eg. ConvertType[TypeCode.Int16]
- //will give you the type of an Int16.
+ //will give you the type of an short.
internal static readonly Type[] ConvertTypes = {
typeof(System.Empty),
- typeof(Object),
+ typeof(object),
typeof(System.DBNull),
- typeof(Boolean),
- typeof(Char),
- typeof(SByte),
- typeof(Byte),
- typeof(Int16),
- typeof(UInt16),
- typeof(Int32),
- typeof(UInt32),
- typeof(Int64),
- typeof(UInt64),
- typeof(Single),
- typeof(Double),
- typeof(Decimal),
+ typeof(bool),
+ typeof(char),
+ typeof(sbyte),
+ typeof(byte),
+ typeof(short),
+ typeof(ushort),
+ typeof(int),
+ typeof(uint),
+ typeof(long),
+ typeof(ulong),
+ typeof(float),
+ typeof(double),
+ typeof(decimal),
typeof(DateTime),
- typeof(Object), //TypeCode is discontinuous so we need a placeholder.
- typeof(String)
+ typeof(object), //TypeCode is discontinuous so we need a placeholder.
+ typeof(string)
};
// Need to special case Enum because typecode will be underlying type, e.g. Int32
@@ -132,7 +132,7 @@ namespace System
't','u','v','w','x','y','z','0','1','2','3','4','5','6','7',
'8','9','+','/','=' };
- private const Int32 base64LineBreakPosition = 76;
+ private const int base64LineBreakPosition = 76;
#if DEBUG
private static bool TriggerAsserts = DoAsserts();
@@ -142,7 +142,7 @@ namespace System
Debug.Assert(ConvertTypes.Length == ((int)TypeCode.String + 1), "[Convert.cctor]ConvertTypes.Length == ((int)TypeCode.String + 1)");
Debug.Assert(ConvertTypes[(int)TypeCode.Empty] == typeof(System.Empty),
"[Convert.cctor]ConvertTypes[(int)TypeCode.Empty]==typeof(System.Empty)");
- Debug.Assert(ConvertTypes[(int)TypeCode.String] == typeof(String),
+ Debug.Assert(ConvertTypes[(int)TypeCode.String] == typeof(string),
"[Convert.cctor]ConvertTypes[(int)TypeCode.String]==typeof(System.String)");
Debug.Assert(ConvertTypes[(int)TypeCode.Int32] == typeof(int),
"[Convert.cctor]ConvertTypes[(int)TypeCode.Int32]==typeof(int)");
@@ -150,7 +150,7 @@ namespace System
}
#endif
- public static readonly Object DBNull = System.DBNull.Value;
+ public static readonly object DBNull = System.DBNull.Value;
// Returns the type code for the given object. If the argument is null,
// the result is TypeCode.Empty. If the argument is not a value (i.e. if
@@ -189,12 +189,12 @@ namespace System
// object already has the given type code, in which case the object is
// simply returned. Otherwise, the appropriate ToXXX() is invoked on the
// object's implementation of IConvertible.
- public static Object ChangeType(Object value, TypeCode typeCode)
+ public static object ChangeType(object value, TypeCode typeCode)
{
return ChangeType(value, typeCode, CultureInfo.CurrentCulture);
}
- public static Object ChangeType(Object value, TypeCode typeCode, IFormatProvider provider)
+ public static object ChangeType(object value, TypeCode typeCode, IFormatProvider provider)
{
if (value == null && (typeCode == TypeCode.Empty || typeCode == TypeCode.String || typeCode == TypeCode.Object))
{
@@ -208,7 +208,7 @@ namespace System
}
// This line is invalid for things like Enums that return a TypeCode
- // of Int32, but the object can't actually be cast to an Int32.
+ // of int, but the object can't actually be cast to an int.
// if (v.GetTypeCode() == typeCode) return value;
switch (typeCode)
{
@@ -253,7 +253,7 @@ namespace System
}
}
- internal static Object DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
+ internal static object DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
{
Debug.Assert(value != null, "[Convert.DefaultToType]value!=null");
if (targetType == null)
@@ -297,7 +297,7 @@ namespace System
if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.String]))
return value.ToString(provider);
if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.Object]))
- return (Object)value;
+ return (object)value;
// Need to special case Enum because typecode will be underlying type, e.g. Int32
if (ReferenceEquals(targetType, EnumType))
return (Enum)value;
@@ -309,14 +309,14 @@ namespace System
throw new InvalidCastException(string.Format(SR.InvalidCast_FromTo, value.GetType().FullName, targetType.FullName));
}
- public static Object ChangeType(Object value, Type conversionType)
+ public static object ChangeType(object value, Type conversionType)
{
return ChangeType(value, conversionType, CultureInfo.CurrentCulture);
}
- public static Object ChangeType(Object value, Type conversionType, IFormatProvider provider)
+ public static object ChangeType(object value, Type conversionType, IFormatProvider provider)
{
- if (ReferenceEquals(conversionType, null))
+ if (conversionType is null)
{
throw new ArgumentNullException(nameof(conversionType));
}
@@ -371,45 +371,36 @@ namespace System
if (ReferenceEquals(conversionType, ConvertTypes[(int)TypeCode.String]))
return ic.ToString(provider);
if (ReferenceEquals(conversionType, ConvertTypes[(int)TypeCode.Object]))
- return (Object)value;
+ return (object)value;
return ic.ToType(conversionType, provider);
}
- [MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowCharOverflowException() { throw new OverflowException(SR.Overflow_Char); }
- [MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowByteOverflowException() { throw new OverflowException(SR.Overflow_Byte); }
- [MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowSByteOverflowException() { throw new OverflowException(SR.Overflow_SByte); }
- [MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowInt16OverflowException() { throw new OverflowException(SR.Overflow_Int16); }
- [MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowUInt16OverflowException() { throw new OverflowException(SR.Overflow_UInt16); }
- [MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowInt32OverflowException() { throw new OverflowException(SR.Overflow_Int32); }
- [MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowUInt32OverflowException() { throw new OverflowException(SR.Overflow_UInt32); }
- [MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowInt64OverflowException() { throw new OverflowException(SR.Overflow_Int64); }
- [MethodImpl(MethodImplOptions.NoInlining)]
private static void ThrowUInt64OverflowException() { throw new OverflowException(SR.Overflow_UInt64); }
// Conversions to Boolean
- public static bool ToBoolean(Object value)
+ public static bool ToBoolean(object value)
{
return value == null ? false : ((IConvertible)value).ToBoolean(null);
}
- public static bool ToBoolean(Object value, IFormatProvider provider)
+ public static bool ToBoolean(object value, IFormatProvider provider)
{
return value == null ? false : ((IConvertible)value).ToBoolean(provider);
}
@@ -472,18 +463,18 @@ namespace System
return value != 0;
}
- public static bool ToBoolean(String value)
+ public static bool ToBoolean(string value)
{
if (value == null)
return false;
- return Boolean.Parse(value);
+ return bool.Parse(value);
}
- public static bool ToBoolean(String value, IFormatProvider provider)
+ public static bool ToBoolean(string value, IFormatProvider provider)
{
if (value == null)
return false;
- return Boolean.Parse(value);
+ return bool.Parse(value);
}
public static bool ToBoolean(float value)
@@ -558,27 +549,27 @@ namespace System
public static char ToChar(int value)
{
- if (value < 0 || value > Char.MaxValue) ThrowCharOverflowException();
+ if (value < 0 || value > char.MaxValue) ThrowCharOverflowException();
return (char)value;
}
[CLSCompliant(false)]
public static char ToChar(uint value)
{
- if (value > Char.MaxValue) ThrowCharOverflowException();
+ if (value > char.MaxValue) ThrowCharOverflowException();
return (char)value;
}
public static char ToChar(long value)
{
- if (value < 0 || value > Char.MaxValue) ThrowCharOverflowException();
+ if (value < 0 || value > char.MaxValue) ThrowCharOverflowException();
return (char)value;
}
[CLSCompliant(false)]
public static char ToChar(ulong value)
{
- if (value > Char.MaxValue) ThrowCharOverflowException();
+ if (value > char.MaxValue) ThrowCharOverflowException();
return (char)value;
}
@@ -586,12 +577,12 @@ namespace System
// @VariantSwitch
// Remove FormatExceptions;
//
- public static char ToChar(String value)
+ public static char ToChar(string value)
{
return ToChar(value, null);
}
- public static char ToChar(String value, IFormatProvider provider)
+ public static char ToChar(string value, IFormatProvider provider)
{
if (value == null)
throw new ArgumentNullException(nameof(value));
@@ -649,7 +640,7 @@ namespace System
[CLSCompliant(false)]
public static sbyte ToSByte(bool value)
{
- return value ? (sbyte)Boolean.True : (sbyte)Boolean.False;
+ return value ? (sbyte)bool.True : (sbyte)bool.False;
}
[CLSCompliant(false)]
@@ -661,56 +652,56 @@ namespace System
[CLSCompliant(false)]
public static sbyte ToSByte(char value)
{
- if (value > SByte.MaxValue) ThrowSByteOverflowException();
+ if (value > sbyte.MaxValue) ThrowSByteOverflowException();
return (sbyte)value;
}
[CLSCompliant(false)]
public static sbyte ToSByte(byte value)
{
- if (value > SByte.MaxValue) ThrowSByteOverflowException();
+ if (value > sbyte.MaxValue) ThrowSByteOverflowException();
return (sbyte)value;
}
[CLSCompliant(false)]
public static sbyte ToSByte(short value)
{
- if (value < SByte.MinValue || value > SByte.MaxValue) ThrowSByteOverflowException();
+ if (value < sbyte.MinValue || value > sbyte.MaxValue) ThrowSByteOverflowException();
return (sbyte)value;
}
[CLSCompliant(false)]
public static sbyte ToSByte(ushort value)
{
- if (value > SByte.MaxValue) ThrowSByteOverflowException();
+ if (value > sbyte.MaxValue) ThrowSByteOverflowException();
return (sbyte)value;
}
[CLSCompliant(false)]
public static sbyte ToSByte(int value)
{
- if (value < SByte.MinValue || value > SByte.MaxValue) ThrowSByteOverflowException();
+ if (value < sbyte.MinValue || value > sbyte.MaxValue) ThrowSByteOverflowException();
return (sbyte)value;
}
[CLSCompliant(false)]
public static sbyte ToSByte(uint value)
{
- if (value > SByte.MaxValue) ThrowSByteOverflowException();
+ if (value > sbyte.MaxValue) ThrowSByteOverflowException();
return (sbyte)value;
}
[CLSCompliant(false)]
public static sbyte ToSByte(long value)
{
- if (value < SByte.MinValue || value > SByte.MaxValue) ThrowSByteOverflowException();
+ if (value < sbyte.MinValue || value > sbyte.MaxValue) ThrowSByteOverflowException();
return (sbyte)value;
}
[CLSCompliant(false)]
public static sbyte ToSByte(ulong value)
{
- if (value > (ulong)SByte.MaxValue) ThrowSByteOverflowException();
+ if (value > (ulong)sbyte.MaxValue) ThrowSByteOverflowException();
return (sbyte)value;
}
@@ -729,21 +720,21 @@ namespace System
[CLSCompliant(false)]
public static sbyte ToSByte(decimal value)
{
- return Decimal.ToSByte(Decimal.Round(value, 0));
+ return decimal.ToSByte(decimal.Round(value, 0));
}
[CLSCompliant(false)]
- public static sbyte ToSByte(String value)
+ public static sbyte ToSByte(string value)
{
if (value == null)
return 0;
- return SByte.Parse(value, CultureInfo.CurrentCulture);
+ return sbyte.Parse(value, CultureInfo.CurrentCulture);
}
[CLSCompliant(false)]
- public static sbyte ToSByte(String value, IFormatProvider provider)
+ public static sbyte ToSByte(string value, IFormatProvider provider)
{
- return SByte.Parse(value, NumberStyles.Integer, provider);
+ return sbyte.Parse(value, NumberStyles.Integer, provider);
}
[CLSCompliant(false)]
@@ -769,7 +760,7 @@ namespace System
public static byte ToByte(bool value)
{
- return value ? (byte)Boolean.True : (byte)Boolean.False;
+ return value ? (byte)bool.True : (byte)bool.False;
}
public static byte ToByte(byte value)
@@ -779,53 +770,53 @@ namespace System
public static byte ToByte(char value)
{
- if (value > Byte.MaxValue) ThrowByteOverflowException();
+ if (value > byte.MaxValue) ThrowByteOverflowException();
return (byte)value;
}
[CLSCompliant(false)]
public static byte ToByte(sbyte value)
{
- if (value < Byte.MinValue) ThrowByteOverflowException();
+ if (value < byte.MinValue) ThrowByteOverflowException();
return (byte)value;
}
public static byte ToByte(short value)
{
- if (value < Byte.MinValue || value > Byte.MaxValue) ThrowByteOverflowException();
+ if (value < byte.MinValue || value > byte.MaxValue) ThrowByteOverflowException();
return (byte)value;
}
[CLSCompliant(false)]
public static byte ToByte(ushort value)
{
- if (value > Byte.MaxValue) ThrowByteOverflowException();
+ if (value > byte.MaxValue) ThrowByteOverflowException();
return (byte)value;
}
public static byte ToByte(int value)
{
- if (value < Byte.MinValue || value > Byte.MaxValue) ThrowByteOverflowException();
+ if (value < byte.MinValue || value > byte.MaxValue) ThrowByteOverflowException();
return (byte)value;
}
[CLSCompliant(false)]
public static byte ToByte(uint value)
{
- if (value > Byte.MaxValue) ThrowByteOverflowException();
+ if (value > byte.MaxValue) ThrowByteOverflowException();
return (byte)value;
}
public static byte ToByte(long value)
{
- if (value < Byte.MinValue || value > Byte.MaxValue) ThrowByteOverflowException();
+ if (value < byte.MinValue || value > byte.MaxValue) ThrowByteOverflowException();
return (byte)value;
}
[CLSCompliant(false)]
public static byte ToByte(ulong value)
{
- if (value > Byte.MaxValue) ThrowByteOverflowException();
+ if (value > byte.MaxValue) ThrowByteOverflowException();
return (byte)value;
}
@@ -841,21 +832,21 @@ namespace System
public static byte ToByte(decimal value)
{
- return Decimal.ToByte(Decimal.Round(value, 0));
+ return decimal.ToByte(decimal.Round(value, 0));
}
- public static byte ToByte(String value)
+ public static byte ToByte(string value)
{
if (value == null)
return 0;
- return Byte.Parse(value, CultureInfo.CurrentCulture);
+ return byte.Parse(value, CultureInfo.CurrentCulture);
}
- public static byte ToByte(String value, IFormatProvider provider)
+ public static byte ToByte(string value, IFormatProvider provider)
{
if (value == null)
return 0;
- return Byte.Parse(value, NumberStyles.Integer, provider);
+ return byte.Parse(value, NumberStyles.Integer, provider);
}
public static byte ToByte(DateTime value)
@@ -881,12 +872,12 @@ namespace System
public static short ToInt16(bool value)
{
- return value ? (short)Boolean.True : (short)Boolean.False;
+ return value ? (short)bool.True : (short)bool.False;
}
public static short ToInt16(char value)
{
- if (value > Int16.MaxValue) ThrowInt16OverflowException();
+ if (value > short.MaxValue) ThrowInt16OverflowException();
return (short)value;
}
@@ -904,20 +895,20 @@ namespace System
[CLSCompliant(false)]
public static short ToInt16(ushort value)
{
- if (value > Int16.MaxValue) ThrowInt16OverflowException();
+ if (value > short.MaxValue) ThrowInt16OverflowException();
return (short)value;
}
public static short ToInt16(int value)
{
- if (value < Int16.MinValue || value > Int16.MaxValue) ThrowInt16OverflowException();
+ if (value < short.MinValue || value > short.MaxValue) ThrowInt16OverflowException();
return (short)value;
}
[CLSCompliant(false)]
public static short ToInt16(uint value)
{
- if (value > Int16.MaxValue) ThrowInt16OverflowException();
+ if (value > short.MaxValue) ThrowInt16OverflowException();
return (short)value;
}
@@ -928,14 +919,14 @@ namespace System
public static short ToInt16(long value)
{
- if (value < Int16.MinValue || value > Int16.MaxValue) ThrowInt16OverflowException();
+ if (value < short.MinValue || value > short.MaxValue) ThrowInt16OverflowException();
return (short)value;
}
[CLSCompliant(false)]
public static short ToInt16(ulong value)
{
- if (value > (ulong)Int16.MaxValue) ThrowInt16OverflowException();
+ if (value > (ulong)short.MaxValue) ThrowInt16OverflowException();
return (short)value;
}
@@ -951,21 +942,21 @@ namespace System
public static short ToInt16(decimal value)
{
- return Decimal.ToInt16(Decimal.Round(value, 0));
+ return decimal.ToInt16(decimal.Round(value, 0));
}
- public static short ToInt16(String value)
+ public static short ToInt16(string value)
{
if (value == null)
return 0;
- return Int16.Parse(value, CultureInfo.CurrentCulture);
+ return short.Parse(value, CultureInfo.CurrentCulture);
}
- public static short ToInt16(String value, IFormatProvider provider)
+ public static short ToInt16(string value, IFormatProvider provider)
{
if (value == null)
return 0;
- return Int16.Parse(value, NumberStyles.Integer, provider);
+ return short.Parse(value, NumberStyles.Integer, provider);
}
public static short ToInt16(DateTime value)
@@ -995,7 +986,7 @@ namespace System
[CLSCompliant(false)]
public static ushort ToUInt16(bool value)
{
- return value ? (ushort)Boolean.True : (ushort)Boolean.False;
+ return value ? (ushort)bool.True : (ushort)bool.False;
}
[CLSCompliant(false)]
@@ -1027,7 +1018,7 @@ namespace System
[CLSCompliant(false)]
public static ushort ToUInt16(int value)
{
- if (value < 0 || value > UInt16.MaxValue) ThrowUInt16OverflowException();
+ if (value < 0 || value > ushort.MaxValue) ThrowUInt16OverflowException();
return (ushort)value;
}
@@ -1040,7 +1031,7 @@ namespace System
[CLSCompliant(false)]
public static ushort ToUInt16(uint value)
{
- if (value > UInt16.MaxValue) ThrowUInt16OverflowException();
+ if (value > ushort.MaxValue) ThrowUInt16OverflowException();
return (ushort)value;
}
@@ -1048,14 +1039,14 @@ namespace System
[CLSCompliant(false)]
public static ushort ToUInt16(long value)
{
- if (value < 0 || value > UInt16.MaxValue) ThrowUInt16OverflowException();
+ if (value < 0 || value > ushort.MaxValue) ThrowUInt16OverflowException();
return (ushort)value;
}
[CLSCompliant(false)]
public static ushort ToUInt16(ulong value)
{
- if (value > UInt16.MaxValue) ThrowUInt16OverflowException();
+ if (value > ushort.MaxValue) ThrowUInt16OverflowException();
return (ushort)value;
}
@@ -1074,23 +1065,23 @@ namespace System
[CLSCompliant(false)]
public static ushort ToUInt16(decimal value)
{
- return Decimal.ToUInt16(Decimal.Round(value, 0));
+ return decimal.ToUInt16(decimal.Round(value, 0));
}
[CLSCompliant(false)]
- public static ushort ToUInt16(String value)
+ public static ushort ToUInt16(string value)
{
if (value == null)
return 0;
- return UInt16.Parse(value, CultureInfo.CurrentCulture);
+ return ushort.Parse(value, CultureInfo.CurrentCulture);
}
[CLSCompliant(false)]
- public static ushort ToUInt16(String value, IFormatProvider provider)
+ public static ushort ToUInt16(string value, IFormatProvider provider)
{
if (value == null)
return 0;
- return UInt16.Parse(value, NumberStyles.Integer, provider);
+ return ushort.Parse(value, NumberStyles.Integer, provider);
}
[CLSCompliant(false)]
@@ -1117,7 +1108,7 @@ namespace System
public static int ToInt32(bool value)
{
- return value ? Boolean.True : Boolean.False;
+ return value ? bool.True : bool.False;
}
public static int ToInt32(char value)
@@ -1150,7 +1141,7 @@ namespace System
[CLSCompliant(false)]
public static int ToInt32(uint value)
{
- if (value > Int32.MaxValue) ThrowInt32OverflowException();
+ if (value > int.MaxValue) ThrowInt32OverflowException();
return (int)value;
}
@@ -1161,14 +1152,14 @@ namespace System
public static int ToInt32(long value)
{
- if (value < Int32.MinValue || value > Int32.MaxValue) ThrowInt32OverflowException();
+ if (value < int.MinValue || value > int.MaxValue) ThrowInt32OverflowException();
return (int)value;
}
[CLSCompliant(false)]
public static int ToInt32(ulong value)
{
- if (value > Int32.MaxValue) ThrowInt32OverflowException();
+ if (value > int.MaxValue) ThrowInt32OverflowException();
return (int)value;
}
@@ -1204,21 +1195,21 @@ namespace System
public static int ToInt32(decimal value)
{
- return Decimal.ToInt32(Decimal.Round(value, 0));
+ return decimal.ToInt32(decimal.Round(value, 0));
}
- public static int ToInt32(String value)
+ public static int ToInt32(string value)
{
if (value == null)
return 0;
- return Int32.Parse(value, CultureInfo.CurrentCulture);
+ return int.Parse(value, CultureInfo.CurrentCulture);
}
- public static int ToInt32(String value, IFormatProvider provider)
+ public static int ToInt32(string value, IFormatProvider provider)
{
if (value == null)
return 0;
- return Int32.Parse(value, NumberStyles.Integer, provider);
+ return int.Parse(value, NumberStyles.Integer, provider);
}
public static int ToInt32(DateTime value)
@@ -1248,7 +1239,7 @@ namespace System
[CLSCompliant(false)]
public static uint ToUInt32(bool value)
{
- return value ? (uint)Boolean.True : (uint)Boolean.False;
+ return value ? (uint)bool.True : (uint)bool.False;
}
[CLSCompliant(false)]
@@ -1299,14 +1290,14 @@ namespace System
[CLSCompliant(false)]
public static uint ToUInt32(long value)
{
- if (value < 0 || value > UInt32.MaxValue) ThrowUInt32OverflowException();
+ if (value < 0 || value > uint.MaxValue) ThrowUInt32OverflowException();
return (uint)value;
}
[CLSCompliant(false)]
public static uint ToUInt32(ulong value)
{
- if (value > UInt32.MaxValue) ThrowUInt32OverflowException();
+ if (value > uint.MaxValue) ThrowUInt32OverflowException();
return (uint)value;
}
@@ -1332,23 +1323,23 @@ namespace System
[CLSCompliant(false)]
public static uint ToUInt32(decimal value)
{
- return Decimal.ToUInt32(Decimal.Round(value, 0));
+ return decimal.ToUInt32(decimal.Round(value, 0));
}
[CLSCompliant(false)]
- public static uint ToUInt32(String value)
+ public static uint ToUInt32(string value)
{
if (value == null)
return 0;
- return UInt32.Parse(value, CultureInfo.CurrentCulture);
+ return uint.Parse(value, CultureInfo.CurrentCulture);
}
[CLSCompliant(false)]
- public static uint ToUInt32(String value, IFormatProvider provider)
+ public static uint ToUInt32(string value, IFormatProvider provider)
{
if (value == null)
return 0;
- return UInt32.Parse(value, NumberStyles.Integer, provider);
+ return uint.Parse(value, NumberStyles.Integer, provider);
}
[CLSCompliant(false)]
@@ -1375,7 +1366,7 @@ namespace System
public static long ToInt64(bool value)
{
- return value ? Boolean.True : Boolean.False;
+ return value ? bool.True : bool.False;
}
public static long ToInt64(char value)
@@ -1419,7 +1410,7 @@ namespace System
[CLSCompliant(false)]
public static long ToInt64(ulong value)
{
- if (value > Int64.MaxValue) ThrowInt64OverflowException();
+ if (value > long.MaxValue) ThrowInt64OverflowException();
return (long)value;
}
@@ -1441,21 +1432,21 @@ namespace System
public static long ToInt64(decimal value)
{
- return Decimal.ToInt64(Decimal.Round(value, 0));
+ return decimal.ToInt64(decimal.Round(value, 0));
}
public static long ToInt64(string value)
{
if (value == null)
return 0;
- return Int64.Parse(value, CultureInfo.CurrentCulture);
+ return long.Parse(value, CultureInfo.CurrentCulture);
}
- public static long ToInt64(String value, IFormatProvider provider)
+ public static long ToInt64(string value, IFormatProvider provider)
{
if (value == null)
return 0;
- return Int64.Parse(value, NumberStyles.Integer, provider);
+ return long.Parse(value, NumberStyles.Integer, provider);
}
public static long ToInt64(DateTime value)
@@ -1483,7 +1474,7 @@ namespace System
[CLSCompliant(false)]
public static ulong ToUInt64(bool value)
{
- return value ? (ulong)Boolean.True : (ulong)Boolean.False;
+ return value ? (ulong)bool.True : (ulong)bool.False;
}
[CLSCompliant(false)]
@@ -1540,7 +1531,7 @@ namespace System
}
[CLSCompliant(false)]
- public static ulong ToUInt64(UInt64 value)
+ public static ulong ToUInt64(ulong value)
{
return value;
}
@@ -1560,23 +1551,23 @@ namespace System
[CLSCompliant(false)]
public static ulong ToUInt64(decimal value)
{
- return Decimal.ToUInt64(Decimal.Round(value, 0));
+ return decimal.ToUInt64(decimal.Round(value, 0));
}
[CLSCompliant(false)]
- public static ulong ToUInt64(String value)
+ public static ulong ToUInt64(string value)
{
if (value == null)
return 0;
- return UInt64.Parse(value, CultureInfo.CurrentCulture);
+ return ulong.Parse(value, CultureInfo.CurrentCulture);
}
[CLSCompliant(false)]
- public static ulong ToUInt64(String value, IFormatProvider provider)
+ public static ulong ToUInt64(string value, IFormatProvider provider)
{
if (value == null)
return 0;
- return UInt64.Parse(value, NumberStyles.Integer, provider);
+ return ulong.Parse(value, NumberStyles.Integer, provider);
}
[CLSCompliant(false)]
@@ -1664,24 +1655,24 @@ namespace System
return (float)value;
}
- public static float ToSingle(String value)
+ public static float ToSingle(string value)
{
if (value == null)
return 0;
- return Single.Parse(value, CultureInfo.CurrentCulture);
+ return float.Parse(value, CultureInfo.CurrentCulture);
}
- public static float ToSingle(String value, IFormatProvider provider)
+ public static float ToSingle(string value, IFormatProvider provider)
{
if (value == null)
return 0;
- return Single.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider);
+ return float.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider);
}
public static float ToSingle(bool value)
{
- return value ? Boolean.True : Boolean.False;
+ return value ? bool.True : bool.False;
}
public static float ToSingle(DateTime value)
@@ -1769,23 +1760,23 @@ namespace System
return (double)value;
}
- public static double ToDouble(String value)
+ public static double ToDouble(string value)
{
if (value == null)
return 0;
- return Double.Parse(value, CultureInfo.CurrentCulture);
+ return double.Parse(value, CultureInfo.CurrentCulture);
}
- public static double ToDouble(String value, IFormatProvider provider)
+ public static double ToDouble(string value, IFormatProvider provider)
{
if (value == null)
return 0;
- return Double.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider);
+ return double.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider);
}
public static double ToDouble(bool value)
{
- return value ? Boolean.True : Boolean.False;
+ return value ? bool.True : bool.False;
}
public static double ToDouble(DateTime value)
@@ -1867,18 +1858,18 @@ namespace System
return (decimal)value;
}
- public static decimal ToDecimal(String value)
+ public static decimal ToDecimal(string value)
{
if (value == null)
return 0m;
- return Decimal.Parse(value, CultureInfo.CurrentCulture);
+ return decimal.Parse(value, CultureInfo.CurrentCulture);
}
- public static Decimal ToDecimal(String value, IFormatProvider provider)
+ public static decimal ToDecimal(string value, IFormatProvider provider)
{
if (value == null)
return 0m;
- return Decimal.Parse(value, NumberStyles.Number, provider);
+ return decimal.Parse(value, NumberStyles.Number, provider);
}
public static decimal ToDecimal(decimal value)
@@ -1888,7 +1879,7 @@ namespace System
public static decimal ToDecimal(bool value)
{
- return value ? Boolean.True : Boolean.False;
+ return value ? bool.True : bool.False;
}
public static decimal ToDecimal(DateTime value)
@@ -1916,14 +1907,14 @@ namespace System
return value == null ? DateTime.MinValue : ((IConvertible)value).ToDateTime(provider);
}
- public static DateTime ToDateTime(String value)
+ public static DateTime ToDateTime(string value)
{
if (value == null)
return new DateTime(0);
return DateTime.Parse(value, CultureInfo.CurrentCulture);
}
- public static DateTime ToDateTime(String value, IFormatProvider provider)
+ public static DateTime ToDateTime(string value, IFormatProvider provider)
{
if (value == null)
return new DateTime(0);
@@ -2004,12 +1995,12 @@ namespace System
// Conversions to String
- public static string ToString(Object value)
+ public static string ToString(object value)
{
return ToString(value, null);
}
- public static string ToString(Object value, IFormatProvider provider)
+ public static string ToString(object value, IFormatProvider provider)
{
IConvertible ic = value as IConvertible;
if (ic != null)
@@ -2017,7 +2008,7 @@ namespace System
IFormattable formattable = value as IFormattable;
if (formattable != null)
return formattable.ToString(null, provider);
- return value == null ? String.Empty : value.ToString();
+ return value == null ? string.Empty : value.ToString();
}
public static string ToString(bool value)
@@ -2032,7 +2023,7 @@ namespace System
public static string ToString(char value)
{
- return Char.ToString(value);
+ return char.ToString(value);
}
public static string ToString(char value, IFormatProvider provider)
@@ -2153,7 +2144,7 @@ namespace System
return value.ToString(CultureInfo.CurrentCulture);
}
- public static string ToString(Decimal value, IFormatProvider provider)
+ public static string ToString(decimal value, IFormatProvider provider)
{
return value.ToString(provider);
}
@@ -2168,12 +2159,12 @@ namespace System
return value.ToString(provider);
}
- public static String ToString(String value)
+ public static string ToString(string value)
{
return value;
}
- public static String ToString(String value, IFormatProvider provider)
+ public static string ToString(string value, IFormatProvider provider)
{
return value; // avoid the null check
}
@@ -2186,7 +2177,7 @@ namespace System
// be 2, 8, 10, or 16. If base is 16, the number may be preceded
// by 0x; any other leading or trailing characters cause an error.
//
- public static byte ToByte(String value, int fromBase)
+ public static byte ToByte(string value, int fromBase)
{
if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
{
@@ -2199,7 +2190,7 @@ namespace System
}
int r = ParseNumbers.StringToInt(value.AsSpan(), fromBase, ParseNumbers.IsTight | ParseNumbers.TreatAsUnsigned);
- if (r < Byte.MinValue || r > Byte.MaxValue)
+ if (r < byte.MinValue || r > byte.MaxValue)
ThrowByteOverflowException();
return (byte)r;
}
@@ -2209,7 +2200,7 @@ namespace System
// by 0x; any other leading or trailing characters cause an error.
//
[CLSCompliant(false)]
- public static sbyte ToSByte(String value, int fromBase)
+ public static sbyte ToSByte(string value, int fromBase)
{
if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
{
@@ -2222,10 +2213,10 @@ namespace System
}
int r = ParseNumbers.StringToInt(value.AsSpan(), fromBase, ParseNumbers.IsTight | ParseNumbers.TreatAsI1);
- if (fromBase != 10 && r <= Byte.MaxValue)
+ if (fromBase != 10 && r <= byte.MaxValue)
return (sbyte)r;
- if (r < SByte.MinValue || r > SByte.MaxValue)
+ if (r < sbyte.MinValue || r > sbyte.MaxValue)
ThrowSByteOverflowException();
return (sbyte)r;
}
@@ -2234,7 +2225,7 @@ namespace System
// be 2, 8, 10, or 16. If fromBase is 16, the number may be preceded
// by 0x; any other leading or trailing characters cause an error.
//
- public static short ToInt16(String value, int fromBase)
+ public static short ToInt16(string value, int fromBase)
{
if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
{
@@ -2247,10 +2238,10 @@ namespace System
}
int r = ParseNumbers.StringToInt(value.AsSpan(), fromBase, ParseNumbers.IsTight | ParseNumbers.TreatAsI2);
- if (fromBase != 10 && r <= UInt16.MaxValue)
+ if (fromBase != 10 && r <= ushort.MaxValue)
return (short)r;
- if (r < Int16.MinValue || r > Int16.MaxValue)
+ if (r < short.MinValue || r > short.MaxValue)
ThrowInt16OverflowException();
return (short)r;
}
@@ -2260,7 +2251,7 @@ namespace System
// by 0x; any other leading or trailing characters cause an error.
//
[CLSCompliant(false)]
- public static ushort ToUInt16(String value, int fromBase)
+ public static ushort ToUInt16(string value, int fromBase)
{
if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
{
@@ -2273,7 +2264,7 @@ namespace System
}
int r = ParseNumbers.StringToInt(value.AsSpan(), fromBase, ParseNumbers.IsTight | ParseNumbers.TreatAsUnsigned);
- if (r < UInt16.MinValue || r > UInt16.MaxValue)
+ if (r < ushort.MinValue || r > ushort.MaxValue)
ThrowUInt16OverflowException();
return (ushort)r;
}
@@ -2282,7 +2273,7 @@ namespace System
// be 2, 8, 10, or 16. If fromBase is 16, the number may be preceded
// by 0x; any other leading or trailing characters cause an error.
//
- public static int ToInt32(String value, int fromBase)
+ public static int ToInt32(string value, int fromBase)
{
if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
{
@@ -2298,7 +2289,7 @@ namespace System
// by 0x; any other leading or trailing characters cause an error.
//
[CLSCompliant(false)]
- public static uint ToUInt32(String value, int fromBase)
+ public static uint ToUInt32(string value, int fromBase)
{
if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
{
@@ -2313,7 +2304,7 @@ namespace System
// be 2, 8, 10, or 16. If fromBase is 16, the number may be preceded
// by 0x; any other leading or trailing characters cause an error.
//
- public static long ToInt64(String value, int fromBase)
+ public static long ToInt64(string value, int fromBase)
{
if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
{
@@ -2329,7 +2320,7 @@ namespace System
// by 0x; any other leading or trailing characters cause an error.
//
[CLSCompliant(false)]
- public static ulong ToUInt64(String value, int fromBase)
+ public static ulong ToUInt64(string value, int fromBase)
{
if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
{
@@ -2341,7 +2332,7 @@ namespace System
}
// Convert the byte value to a string in base fromBase
- public static String ToString(byte value, int toBase)
+ public static string ToString(byte value, int toBase)
{
if (toBase != 2 && toBase != 8 && toBase != 10 && toBase != 16)
{
@@ -2351,7 +2342,7 @@ namespace System
}
// Convert the Int16 value to a string in base fromBase
- public static String ToString(short value, int toBase)
+ public static string ToString(short value, int toBase)
{
if (toBase != 2 && toBase != 8 && toBase != 10 && toBase != 16)
{
@@ -2361,7 +2352,7 @@ namespace System
}
// Convert the Int32 value to a string in base toBase
- public static String ToString(int value, int toBase)
+ public static string ToString(int value, int toBase)
{
if (toBase != 2 && toBase != 8 && toBase != 10 && toBase != 16)
{
@@ -2371,7 +2362,7 @@ namespace System
}
// Convert the Int64 value to a string in base toBase
- public static String ToString(long value, int toBase)
+ public static string ToString(long value, int toBase)
{
if (toBase != 2 && toBase != 8 && toBase != 10 && toBase != 16)
{
@@ -2380,7 +2371,7 @@ namespace System
return ParseNumbers.LongToString(value, toBase, -1, ' ', 0);
}
- public static String ToBase64String(byte[] inArray)
+ public static string ToBase64String(byte[] inArray)
{
if (inArray == null)
{
@@ -2389,7 +2380,7 @@ namespace System
return ToBase64String(new ReadOnlySpan<byte>(inArray), Base64FormattingOptions.None);
}
- public static String ToBase64String(byte[] inArray, Base64FormattingOptions options)
+ public static string ToBase64String(byte[] inArray, Base64FormattingOptions options)
{
if (inArray == null)
{
@@ -2398,12 +2389,12 @@ namespace System
return ToBase64String(new ReadOnlySpan<byte>(inArray), options);
}
- public static String ToBase64String(byte[] inArray, int offset, int length)
+ public static string ToBase64String(byte[] inArray, int offset, int length)
{
return ToBase64String(inArray, offset, length, Base64FormattingOptions.None);
}
- public static String ToBase64String(byte[] inArray, int offset, int length, Base64FormattingOptions options)
+ public static string ToBase64String(byte[] inArray, int offset, int length, Base64FormattingOptions options)
{
if (inArray == null)
throw new ArgumentNullException(nameof(inArray));
@@ -2629,7 +2620,7 @@ namespace System
/// </summary>
/// <param name="s">The string to convert</param>
/// <returns>The array of bytes represented by the specified Base64 string.</returns>
- public static Byte[] FromBase64String(String s)
+ public static byte[] FromBase64String(string s)
{
// "s" is an unfortunate parameter name, but we need to keep it for backward compat.
@@ -2639,7 +2630,7 @@ namespace System
unsafe
{
- fixed (Char* sPtr = s)
+ fixed (char* sPtr = s)
{
return FromBase64CharPtr(sPtr, s.Length);
}
@@ -2656,44 +2647,124 @@ namespace System
return TryFromBase64Chars(s.AsSpan(), bytes, out bytesWritten);
}
- public static unsafe bool TryFromBase64Chars(ReadOnlySpan<char> chars, Span<byte> bytes, out int bytesWritten)
+ public static bool TryFromBase64Chars(ReadOnlySpan<char> chars, Span<byte> bytes, out int bytesWritten)
{
- if (chars.Length == 0)
- {
- bytesWritten = 0;
- return true;
- }
+ // This is actually local to one of the nested blocks but is being declared at the top as we don't want multiple stackallocs
+ // for each iteraton of the loop.
+ Span<char> tempBuffer = stackalloc char[4]; // Note: The tempBuffer size could be made larger than 4 but the size must be a multiple of 4.
- // We need to get rid of any trailing white spaces.
- // Otherwise we would be rejecting input such as "abc= ":
- while (chars.Length > 0)
+ bytesWritten = 0;
+
+ while (chars.Length != 0)
{
- char lastChar = chars[chars.Length - 1];
- if (lastChar != ' ' && lastChar != '\n' && lastChar != '\r' && lastChar != '\t')
+ // Attempt to decode a segment that doesn't contain whitespace.
+ bool complete = TryDecodeFromUtf16(chars, bytes, out int consumedInThisIteration, out int bytesWrittenInThisIteration);
+ bytesWritten += bytesWrittenInThisIteration;
+ if (complete)
+ return true;
+
+ chars = chars.Slice(consumedInThisIteration);
+ bytes = bytes.Slice(bytesWrittenInThisIteration);
+
+ Debug.Assert(chars.Length != 0); // If TryDecodeFromUtf16() consumed the entire buffer, it could not have returned false.
+ if (chars[0].IsSpace())
{
- break;
- }
- chars = chars.Slice(0, chars.Length - 1);
- }
+ // If we got here, the very first character not consumed was a whitespace. We can skip past any consecutive whitespace, then continue decoding.
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
- {
- int resultLength = FromBase64_ComputeResultLength(charsPtr, chars.Length);
- Debug.Assert(resultLength >= 0);
- if (resultLength > bytes.Length)
+ int indexOfFirstNonSpace = 1;
+ for (; ; )
+ {
+ if (indexOfFirstNonSpace == chars.Length)
+ break;
+ if (!chars[indexOfFirstNonSpace].IsSpace())
+ break;
+ indexOfFirstNonSpace++;
+ }
+
+ chars = chars.Slice(indexOfFirstNonSpace);
+
+ if ((bytesWrittenInThisIteration % 3) != 0 && chars.Length != 0)
+ {
+ // If we got here, the last successfully decoded block encountered an end-marker, yet we have trailing non-whitespace characters.
+ // That is not allowed.
+ bytesWritten = default;
+ return false;
+ }
+
+ // We now loop again to decode the next run of non-space characters.
+ }
+ else
{
- bytesWritten = 0;
- return false;
+ Debug.Assert(chars.Length != 0 && !chars[0].IsSpace());
+
+ // If we got here, it is possible that there is whitespace that occurred in the middle of a 4-byte chunk. That is, we still have
+ // up to three Base64 characters that were left undecoded by the fast-path helper because they didn't form a complete 4-byte chunk.
+ // This is hopefully the rare case (multiline-formatted base64 message with a non-space character width that's not a multiple of 4.)
+ // We'll filter out whitespace and copy the remaining characters into a temporary buffer.
+ CopyToTempBufferWithoutWhiteSpace(chars, tempBuffer, out int consumedFromChars, out int charsWritten);
+ if ((charsWritten & 0x3) != 0)
+ {
+ // Even after stripping out whitespace, the number of characters is not divisible by 4. This cannot be a legal Base64 string.
+ bytesWritten = default;
+ return false;
+ }
+
+ tempBuffer = tempBuffer.Slice(0, charsWritten);
+ if (!TryDecodeFromUtf16(tempBuffer, bytes, out int consumedFromTempBuffer, out int bytesWrittenFromTempBuffer))
+ {
+ bytesWritten = default;
+ return false;
+ }
+ bytesWritten += bytesWrittenFromTempBuffer;
+ chars = chars.Slice(consumedFromChars);
+ bytes = bytes.Slice(bytesWrittenFromTempBuffer);
+
+ if ((bytesWrittenFromTempBuffer % 3) != 0)
+ {
+ // If we got here, this decode contained one or more padding characters ('='). We can accept trailing whitespace after this
+ // but nothing else.
+ for (int i = 0; i < chars.Length; i++)
+ {
+ if (!chars[i].IsSpace())
+ {
+ bytesWritten = default;
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // We now loop again to decode the next run of non-space characters.
}
+ }
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
+ return true;
+ }
+
+ private static void CopyToTempBufferWithoutWhiteSpace(ReadOnlySpan<char> chars, Span<char> tempBuffer, out int consumed, out int charsWritten)
+ {
+ Debug.Assert(tempBuffer.Length != 0); // We only bound-check after writing a character to the tempBuffer.
+
+ charsWritten = 0;
+ for (int i = 0; i < chars.Length; i++)
+ {
+ char c = chars[i];
+ if (!c.IsSpace())
{
- bytesWritten = FromBase64_Decode(charsPtr, chars.Length, bytesPtr, bytes.Length);
- return true;
+ tempBuffer[charsWritten++] = c;
+ if (charsWritten == tempBuffer.Length)
+ {
+ consumed = i + 1;
+ return;
+ }
}
}
+ consumed = chars.Length;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static bool IsSpace(this char c) => c == ' ' || c == '\t' || c == '\r' || c == '\n';
+
/// <summary>
/// Converts the specified range of a Char array, which encodes binary data as Base64 digits, to the equivalent byte array.
/// </summary>
@@ -2701,7 +2772,7 @@ namespace System
/// <param name="offset">A position within the input array.</param>
/// <param name="length">Number of element to convert.</param>
/// <returns>The array of bytes represented by the specified Base64 encoding characters.</returns>
- public static Byte[] FromBase64CharArray(Char[] inArray, Int32 offset, Int32 length)
+ public static byte[] FromBase64CharArray(char[] inArray, int offset, int length)
{
if (inArray == null)
throw new ArgumentNullException(nameof(inArray));
@@ -2723,15 +2794,13 @@ namespace System
unsafe
{
- fixed (Char* inArrayPtr = &inArray[0])
+ fixed (char* inArrayPtr = &inArray[0])
{
return FromBase64CharPtr(inArrayPtr + offset, length);
}
}
}
-
-
/// <summary>
/// Convert Base64 encoding characters to bytes:
/// - Compute result length exactly by actually walking the input;
@@ -2741,7 +2810,7 @@ namespace System
/// <param name="inputPtr">Pointer to the first input char</param>
/// <param name="inputLength">Number of input chars</param>
/// <returns></returns>
- private static unsafe Byte[] FromBase64CharPtr(Char* inputPtr, Int32 inputLength)
+ private static unsafe byte[] FromBase64CharPtr(char* inputPtr, int inputLength)
{
// The validity of parameters much be checked by callers, thus we are Critical here.
@@ -2751,14 +2820,14 @@ namespace System
// Otherwise we would be rejecting input such as "abc= ":
while (inputLength > 0)
{
- Int32 lastChar = inputPtr[inputLength - 1];
- if (lastChar != (Int32)' ' && lastChar != (Int32)'\n' && lastChar != (Int32)'\r' && lastChar != (Int32)'\t')
+ int lastChar = inputPtr[inputLength - 1];
+ if (lastChar != (int)' ' && lastChar != (int)'\n' && lastChar != (int)'\r' && lastChar != (int)'\t')
break;
inputLength--;
}
// Compute the output length:
- Int32 resultLength = FromBase64_ComputeResultLength(inputPtr, inputLength);
+ int resultLength = FromBase64_ComputeResultLength(inputPtr, inputLength);
Debug.Assert(0 <= resultLength);
@@ -2766,14 +2835,13 @@ namespace System
// It may either simply write no bytes (e.g. input = " ") or throw (e.g. input = "ab").
// Create result byte blob:
- Byte[] decodedBytes = new Byte[resultLength];
+ byte[] decodedBytes = new byte[resultLength];
// Convert Base64 chars into bytes:
- Int32 actualResultLength;
- fixed (Byte* decodedBytesPtr = decodedBytes)
- actualResultLength = FromBase64_Decode(inputPtr, inputLength, decodedBytesPtr, resultLength);
+ if (!TryFromBase64Chars(new ReadOnlySpan<char>(inputPtr, inputLength), decodedBytes, out int _))
+ throw new FormatException(SR.Format_BadBase64Char);
- // Note that actualResultLength can differ from resultLength if the caller is modifying the array
+ // Note that the number of bytes written can differ from resultLength if the caller is modifying the array
// as it is being converted. Silently ignore the failure.
// Consider throwing exception in an non in-place release.
@@ -2781,218 +2849,25 @@ namespace System
return decodedBytes;
}
-
- /// <summary>
- /// Decode characters representing a Base64 encoding into bytes:
- /// Walk the input. Every time 4 chars are read, convert them to the 3 corresponding output bytes.
- /// This method is a bit lengthy on purpose. We are trying to avoid jumps to helpers in the loop
- /// to aid performance.
- /// </summary>
- /// <param name="inputPtr">Pointer to first input char</param>
- /// <param name="inputLength">Number of input chars</param>
- /// <param name="destPtr">Pointer to location for the first result byte</param>
- /// <param name="destLength">Max length of the preallocated result buffer</param>
- /// <returns>If the result buffer was not large enough to write all result bytes, return -1;
- /// Otherwise return the number of result bytes actually produced.</returns>
- private static unsafe Int32 FromBase64_Decode(Char* startInputPtr, Int32 inputLength, Byte* startDestPtr, Int32 destLength)
- {
- // You may find this method weird to look at. It's written for performance, not aesthetics.
- // You will find unrolled loops label jumps and bit manipulations.
-
- const UInt32 intA = (UInt32)'A';
- const UInt32 inta = (UInt32)'a';
- const UInt32 int0 = (UInt32)'0';
- const UInt32 intEq = (UInt32)'=';
- const UInt32 intPlus = (UInt32)'+';
- const UInt32 intSlash = (UInt32)'/';
- const UInt32 intSpace = (UInt32)' ';
- const UInt32 intTab = (UInt32)'\t';
- const UInt32 intNLn = (UInt32)'\n';
- const UInt32 intCRt = (UInt32)'\r';
- const UInt32 intAtoZ = (UInt32)('Z' - 'A'); // = ('z' - 'a')
- const UInt32 int0to9 = (UInt32)('9' - '0');
-
- Char* inputPtr = startInputPtr;
- Byte* destPtr = startDestPtr;
-
- // Pointers to the end of input and output:
- Char* endInputPtr = inputPtr + inputLength;
- Byte* endDestPtr = destPtr + destLength;
-
- // Current char code/value:
- UInt32 currCode;
-
- // This 4-byte integer will contain the 4 codes of the current 4-char group.
- // Eeach char codes for 6 bits = 24 bits.
- // The remaining byte will be FF, we use it as a marker when 4 chars have been processed.
- UInt32 currBlockCodes = 0x000000FFu;
-
- unchecked
- {
- while (true)
- {
- // break when done:
- if (inputPtr >= endInputPtr)
- goto _AllInputConsumed;
-
- // Get current char:
- currCode = (UInt32)(*inputPtr);
- inputPtr++;
-
- // Determine current char code:
-
- if (currCode - intA <= intAtoZ)
- currCode -= intA;
-
- else if (currCode - inta <= intAtoZ)
- currCode -= (inta - 26u);
-
- else if (currCode - int0 <= int0to9)
- currCode -= (int0 - 52u);
-
- else
- {
- // Use the slower switch for less common cases:
- switch (currCode)
- {
- // Significant chars:
- case intPlus:
- currCode = 62u;
- break;
-
- case intSlash:
- currCode = 63u;
- break;
-
- // Legal no-value chars (we ignore these):
- case intCRt:
- case intNLn:
- case intSpace:
- case intTab:
- continue;
-
- // The equality char is only legal at the end of the input.
- // Jump after the loop to make it easier for the JIT register predictor to do a good job for the loop itself:
- case intEq:
- goto _EqualityCharEncountered;
-
- // Other chars are illegal:
- default:
- throw new FormatException(SR.Format_BadBase64Char);
- }
- }
-
- // Ok, we got the code. Save it:
- currBlockCodes = (currBlockCodes << 6) | currCode;
-
- // Last bit in currBlockCodes will be on after in shifted right 4 times:
- if ((currBlockCodes & 0x80000000u) != 0u)
- {
- if ((Int32)(endDestPtr - destPtr) < 3)
- return -1;
-
- *(destPtr) = (Byte)(currBlockCodes >> 16);
- *(destPtr + 1) = (Byte)(currBlockCodes >> 8);
- *(destPtr + 2) = (Byte)(currBlockCodes);
- destPtr += 3;
-
- currBlockCodes = 0x000000FFu;
- }
- }
- } // unchecked while
-
- // 'd be nice to have an assert that we never get here, but CS0162: Unreachable code detected.
- // Debug.Fail("We only leave the above loop by jumping; should never get here.");
-
- // We jump here out of the loop if we hit an '=':
- _EqualityCharEncountered:
-
- Debug.Assert(currCode == intEq);
-
- // Recall that inputPtr is now one position past where '=' was read.
- // '=' can only be at the last input pos:
- if (inputPtr == endInputPtr)
- {
- // Code is zero for trailing '=':
- currBlockCodes <<= 6;
-
- // The '=' did not complete a 4-group. The input must be bad:
- if ((currBlockCodes & 0x80000000u) == 0u)
- throw new FormatException(SR.Format_BadBase64CharArrayLength);
-
- if ((int)(endDestPtr - destPtr) < 2) // Autch! We underestimated the output length!
- return -1;
-
- // We are good, store bytes form this past group. We had a single "=", so we take two bytes:
- *(destPtr++) = (Byte)(currBlockCodes >> 16);
- *(destPtr++) = (Byte)(currBlockCodes >> 8);
-
- currBlockCodes = 0x000000FFu;
- }
- else
- { // '=' can also be at the pre-last position iff the last is also a '=' excluding the white spaces:
- // We need to get rid of any intermediate white spaces.
- // Otherwise we would be rejecting input such as "abc= =":
- while (inputPtr < (endInputPtr - 1))
- {
- Int32 lastChar = *(inputPtr);
- if (lastChar != (Int32)' ' && lastChar != (Int32)'\n' && lastChar != (Int32)'\r' && lastChar != (Int32)'\t')
- break;
- inputPtr++;
- }
-
- if (inputPtr == (endInputPtr - 1) && *(inputPtr) == '=')
- {
- // Code is zero for each of the two '=':
- currBlockCodes <<= 12;
-
- // The '=' did not complete a 4-group. The input must be bad:
- if ((currBlockCodes & 0x80000000u) == 0u)
- throw new FormatException(SR.Format_BadBase64CharArrayLength);
-
- if ((Int32)(endDestPtr - destPtr) < 1) // Autch! We underestimated the output length!
- return -1;
-
- // We are good, store bytes form this past group. We had a "==", so we take only one byte:
- *(destPtr++) = (Byte)(currBlockCodes >> 16);
-
- currBlockCodes = 0x000000FFu;
- }
- else // '=' is not ok at places other than the end:
- throw new FormatException(SR.Format_BadBase64Char);
- }
-
- // We get here either from above or by jumping out of the loop:
- _AllInputConsumed:
-
- // The last block of chars has less than 4 items
- if (currBlockCodes != 0x000000FFu)
- throw new FormatException(SR.Format_BadBase64CharArrayLength);
-
- // Return how many bytes were actually recovered:
- return (Int32)(destPtr - startDestPtr);
- } // Int32 FromBase64_Decode(...)
-
-
/// <summary>
/// Compute the number of bytes encoded in the specified Base 64 char array:
/// Walk the entire input counting white spaces and padding chars, then compute result length
/// based on 3 bytes per 4 chars.
/// </summary>
- private static unsafe Int32 FromBase64_ComputeResultLength(Char* inputPtr, Int32 inputLength)
+ private static unsafe int FromBase64_ComputeResultLength(char* inputPtr, int inputLength)
{
- const UInt32 intEq = (UInt32)'=';
- const UInt32 intSpace = (UInt32)' ';
+ const uint intEq = (uint)'=';
+ const uint intSpace = (uint)' ';
Debug.Assert(0 <= inputLength);
- Char* inputEndPtr = inputPtr + inputLength;
- Int32 usefulInputLength = inputLength;
- Int32 padding = 0;
+ char* inputEndPtr = inputPtr + inputLength;
+ int usefulInputLength = inputLength;
+ int padding = 0;
while (inputPtr < inputEndPtr)
{
- UInt32 c = (UInt32)(*inputPtr);
+ uint c = (uint)(*inputPtr);
inputPtr++;
// We want to be as fast as possible and filter out spaces with as few comparisons as possible.
diff --git a/src/System.Private.CoreLib/shared/System/CurrentSystemTimeZone.cs b/src/System.Private.CoreLib/shared/System/CurrentSystemTimeZone.cs
index bab6a92bf..0112c81ab 100644
--- a/src/System.Private.CoreLib/shared/System/CurrentSystemTimeZone.cs
+++ b/src/System.Private.CoreLib/shared/System/CurrentSystemTimeZone.cs
@@ -17,25 +17,21 @@
**
============================================================*/
-using System;
-using System.Text;
using System.Collections;
using System.Globalization;
-using System.Runtime.CompilerServices;
-using System.Runtime.Versioning;
namespace System
{
[Obsolete("System.CurrentSystemTimeZone has been deprecated. Please investigate the use of System.TimeZoneInfo.Local instead.")]
- internal partial class CurrentSystemTimeZone : TimeZone
+ internal class CurrentSystemTimeZone : TimeZone
{
// Standard offset in ticks to the Universal time if
// no daylight saving is in used.
// E.g. the offset for PST (Pacific Standard time) should be -8 * 60 * 60 * 1000 * 10000.
// (1 millisecond = 10000 ticks)
private long m_ticksOffset;
- private String m_standardName;
- private String m_daylightName;
+ private string m_standardName;
+ private string m_daylightName;
internal CurrentSystemTimeZone()
{
@@ -46,7 +42,7 @@ namespace System
m_daylightName = local.DaylightName;
}
- public override String StandardName
+ public override string StandardName
{
get
{
@@ -54,7 +50,7 @@ namespace System
}
}
- public override String DaylightName
+ public override string DaylightName
{
get
{
@@ -62,7 +58,7 @@ namespace System
}
}
- internal long GetUtcOffsetFromUniversalTime(DateTime time, ref Boolean isAmbiguousLocalDst)
+ internal long GetUtcOffsetFromUniversalTime(DateTime time, ref bool isAmbiguousLocalDst)
{
// Get the daylight changes for the year of the specified time.
TimeSpan offset = new TimeSpan(m_ticksOffset);
@@ -93,7 +89,7 @@ namespace System
ambiguousEnd = startTime - daylightTime.Delta;
}
- Boolean isDst = false;
+ bool isDst = false;
if (startTime > endTime)
{
// In southern hemisphere, the daylight saving time starts later in the year, and ends in the beginning of next year.
@@ -126,8 +122,8 @@ namespace System
{
return time;
}
- Boolean isAmbiguousLocalDst = false;
- Int64 offset = GetUtcOffsetFromUniversalTime(time, ref isAmbiguousLocalDst);
+ bool isAmbiguousLocalDst = false;
+ long offset = GetUtcOffsetFromUniversalTime(time, ref isAmbiguousLocalDst);
long tick = time.Ticks + offset;
if (tick > DateTime.MaxTicks)
{
@@ -193,5 +189,29 @@ namespace System
return new TimeSpan(TimeZone.CalculateUtcOffset(time, GetDaylightChanges(time.Year)).Ticks + m_ticksOffset);
}
}
+
+ private DaylightTime GetCachedDaylightChanges(int year)
+ {
+ object objYear = (object)year;
+
+ if (!m_CachedDaylightChanges.Contains(objYear))
+ {
+ DaylightTime currentDaylightChanges = CreateDaylightChanges(year);
+ lock (m_CachedDaylightChanges)
+ {
+ if (!m_CachedDaylightChanges.Contains(objYear))
+ {
+ m_CachedDaylightChanges.Add(objYear, currentDaylightChanges);
+ }
+ }
+ }
+
+ return (DaylightTime)m_CachedDaylightChanges[objYear];
+ }
+
+ // The per-year information is cached in in this instance value. As a result it can
+ // be cleaned up by CultureInfo.ClearCachedData, which will clear the instance of this object
+ private readonly Hashtable m_CachedDaylightChanges = new Hashtable();
+
} // class CurrentSystemTimeZone
}
diff --git a/src/System.Private.CoreLib/shared/System/DataMisalignedException.cs b/src/System.Private.CoreLib/shared/System/DataMisalignedException.cs
index 2a245b6ef..940407fc5 100644
--- a/src/System.Private.CoreLib/shared/System/DataMisalignedException.cs
+++ b/src/System.Private.CoreLib/shared/System/DataMisalignedException.cs
@@ -23,13 +23,13 @@ namespace System
HResult = HResults.COR_E_DATAMISALIGNED;
}
- public DataMisalignedException(String message)
+ public DataMisalignedException(string message)
: base(message)
{
HResult = HResults.COR_E_DATAMISALIGNED;
}
- public DataMisalignedException(String message, Exception innerException)
+ public DataMisalignedException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_DATAMISALIGNED;
diff --git a/src/System.Private.CoreLib/shared/System/DateTime.cs b/src/System.Private.CoreLib/shared/System/DateTime.cs
index b5deefa94..5b76f6092 100644
--- a/src/System.Private.CoreLib/shared/System/DateTime.cs
+++ b/src/System.Private.CoreLib/shared/System/DateTime.cs
@@ -115,18 +115,18 @@ namespace System
public static readonly DateTime MaxValue = new DateTime(MaxTicks, DateTimeKind.Unspecified);
public static readonly DateTime UnixEpoch = new DateTime(UnixEpochTicks, DateTimeKind.Utc);
- private const UInt64 TicksMask = 0x3FFFFFFFFFFFFFFF;
- private const UInt64 FlagsMask = 0xC000000000000000;
- private const UInt64 LocalMask = 0x8000000000000000;
- private const Int64 TicksCeiling = 0x4000000000000000;
- private const UInt64 KindUnspecified = 0x0000000000000000;
- private const UInt64 KindUtc = 0x4000000000000000;
- private const UInt64 KindLocal = 0x8000000000000000;
- private const UInt64 KindLocalAmbiguousDst = 0xC000000000000000;
- private const Int32 KindShift = 62;
-
- private const String TicksField = "ticks"; // Do not rename (binary serialization)
- private const String DateDataField = "dateData"; // Do not rename (binary serialization)
+ private const ulong TicksMask = 0x3FFFFFFFFFFFFFFF;
+ private const ulong FlagsMask = 0xC000000000000000;
+ private const ulong LocalMask = 0x8000000000000000;
+ private const long TicksCeiling = 0x4000000000000000;
+ private const ulong KindUnspecified = 0x0000000000000000;
+ private const ulong KindUtc = 0x4000000000000000;
+ private const ulong KindLocal = 0x8000000000000000;
+ private const ulong KindLocalAmbiguousDst = 0xC000000000000000;
+ private const int KindShift = 62;
+
+ private const string TicksField = "ticks"; // Do not rename (binary serialization)
+ private const string DateDataField = "dateData"; // Do not rename (binary serialization)
// The data is stored as an unsigned 64-bit integer
// Bits 01-62: The value of 100-nanosecond ticks where 0 represents 1/1/0001 12:00am, up until the value
@@ -136,7 +136,7 @@ namespace System
// savings time hour and it is in daylight savings time. This allows distinction of these
// otherwise ambiguous local times and prevents data loss when round tripping from Local to
// UTC time.
- private readonly UInt64 _dateData;
+ private readonly ulong _dateData;
// Constructs a DateTime from a tick count. The ticks
// argument specifies the date as the number of 100-nanosecond intervals
@@ -146,10 +146,10 @@ namespace System
{
if (ticks < MinTicks || ticks > MaxTicks)
throw new ArgumentOutOfRangeException(nameof(ticks), SR.ArgumentOutOfRange_DateTimeBadTicks);
- _dateData = (UInt64)ticks;
+ _dateData = (ulong)ticks;
}
- private DateTime(UInt64 dateData)
+ private DateTime(ulong dateData)
{
this._dateData = dateData;
}
@@ -164,17 +164,17 @@ namespace System
{
throw new ArgumentException(SR.Argument_InvalidDateTimeKind, nameof(kind));
}
- _dateData = ((UInt64)ticks | ((UInt64)kind << KindShift));
+ _dateData = ((ulong)ticks | ((ulong)kind << KindShift));
}
- internal DateTime(long ticks, DateTimeKind kind, Boolean isAmbiguousDst)
+ internal DateTime(long ticks, DateTimeKind kind, bool isAmbiguousDst)
{
if (ticks < MinTicks || ticks > MaxTicks)
{
throw new ArgumentOutOfRangeException(nameof(ticks), SR.ArgumentOutOfRange_DateTimeBadTicks);
}
Debug.Assert(kind == DateTimeKind.Local, "Internal Constructor is for local times only");
- _dateData = ((UInt64)ticks | (isAmbiguousDst ? KindLocalAmbiguousDst : KindLocal));
+ _dateData = ((ulong)ticks | (isAmbiguousDst ? KindLocalAmbiguousDst : KindLocal));
}
// Constructs a DateTime from a given year, month, and day. The
@@ -182,7 +182,7 @@ namespace System
//
public DateTime(int year, int month, int day)
{
- _dateData = (UInt64)DateToTicks(year, month, day);
+ _dateData = (ulong)DateToTicks(year, month, day);
}
// Constructs a DateTime from a given year, month, and day for
@@ -199,7 +199,7 @@ namespace System
//
public DateTime(int year, int month, int day, int hour, int minute, int second)
{
- _dateData = (UInt64)(DateToTicks(year, month, day) + TimeToTicks(hour, minute, second));
+ _dateData = (ulong)(DateToTicks(year, month, day) + TimeToTicks(hour, minute, second));
}
public DateTime(int year, int month, int day, int hour, int minute, int second, DateTimeKind kind)
@@ -208,8 +208,8 @@ namespace System
{
throw new ArgumentException(SR.Argument_InvalidDateTimeKind, nameof(kind));
}
- Int64 ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second);
- _dateData = ((UInt64)ticks | ((UInt64)kind << KindShift));
+ long ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second);
+ _dateData = ((ulong)ticks | ((ulong)kind << KindShift));
}
// Constructs a DateTime from a given year, month, day, hour,
@@ -219,7 +219,7 @@ namespace System
{
if (calendar == null)
throw new ArgumentNullException(nameof(calendar));
- _dateData = (UInt64)calendar.ToDateTime(year, month, day, hour, minute, second, 0).Ticks;
+ _dateData = (ulong)calendar.ToDateTime(year, month, day, hour, minute, second, 0).Ticks;
}
// Constructs a DateTime from a given year, month, day, hour,
@@ -231,11 +231,11 @@ namespace System
{
throw new ArgumentOutOfRangeException(nameof(millisecond), SR.Format(SR.ArgumentOutOfRange_Range, 0, MillisPerSecond - 1));
}
- Int64 ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second);
+ long ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second);
ticks += millisecond * TicksPerMillisecond;
if (ticks < MinTicks || ticks > MaxTicks)
throw new ArgumentException(SR.Arg_DateTimeRange);
- _dateData = (UInt64)ticks;
+ _dateData = (ulong)ticks;
}
public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, DateTimeKind kind)
@@ -248,11 +248,11 @@ namespace System
{
throw new ArgumentException(SR.Argument_InvalidDateTimeKind, nameof(kind));
}
- Int64 ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second);
+ long ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second);
ticks += millisecond * TicksPerMillisecond;
if (ticks < MinTicks || ticks > MaxTicks)
throw new ArgumentException(SR.Arg_DateTimeRange);
- _dateData = ((UInt64)ticks | ((UInt64)kind << KindShift));
+ _dateData = ((ulong)ticks | ((ulong)kind << KindShift));
}
// Constructs a DateTime from a given year, month, day, hour,
@@ -266,11 +266,11 @@ namespace System
{
throw new ArgumentOutOfRangeException(nameof(millisecond), SR.Format(SR.ArgumentOutOfRange_Range, 0, MillisPerSecond - 1));
}
- Int64 ticks = calendar.ToDateTime(year, month, day, hour, minute, second, 0).Ticks;
+ long ticks = calendar.ToDateTime(year, month, day, hour, minute, second, 0).Ticks;
ticks += millisecond * TicksPerMillisecond;
if (ticks < MinTicks || ticks > MaxTicks)
throw new ArgumentException(SR.Arg_DateTimeRange);
- _dateData = (UInt64)ticks;
+ _dateData = (ulong)ticks;
}
public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar, DateTimeKind kind)
@@ -285,11 +285,11 @@ namespace System
{
throw new ArgumentException(SR.Argument_InvalidDateTimeKind, nameof(kind));
}
- Int64 ticks = calendar.ToDateTime(year, month, day, hour, minute, second, 0).Ticks;
+ long ticks = calendar.ToDateTime(year, month, day, hour, minute, second, 0).Ticks;
ticks += millisecond * TicksPerMillisecond;
if (ticks < MinTicks || ticks > MaxTicks)
throw new ArgumentException(SR.Arg_DateTimeRange);
- _dateData = ((UInt64)ticks | ((UInt64)kind << KindShift));
+ _dateData = ((ulong)ticks | ((ulong)kind << KindShift));
}
private DateTime(SerializationInfo info, StreamingContext context)
@@ -297,10 +297,10 @@ namespace System
if (info == null)
throw new ArgumentNullException(nameof(info));
- Boolean foundTicks = false;
- Boolean foundDateData = false;
- Int64 serializedTicks = 0;
- UInt64 serializedDateData = 0;
+ bool foundTicks = false;
+ bool foundDateData = false;
+ long serializedTicks = 0;
+ ulong serializedDateData = 0;
// Get the data
@@ -328,13 +328,13 @@ namespace System
}
else if (foundTicks)
{
- _dateData = (UInt64)serializedTicks;
+ _dateData = (ulong)serializedTicks;
}
else
{
throw new SerializationException(SR.Serialization_MissingDateTimeData);
}
- Int64 ticks = InternalTicks;
+ long ticks = InternalTicks;
if (ticks < MinTicks || ticks > MaxTicks)
{
throw new SerializationException(SR.Serialization_DateTimeTicksOutOfRange);
@@ -343,15 +343,15 @@ namespace System
- internal Int64 InternalTicks
+ internal long InternalTicks
{
get
{
- return (Int64)(_dateData & TicksMask);
+ return (long)(_dateData & TicksMask);
}
}
- private UInt64 InternalKind
+ private ulong InternalKind
{
get
{
@@ -459,7 +459,7 @@ namespace System
}
int days = DaysInMonth(y, m);
if (d > days) d = days;
- return new DateTime((UInt64)(DateToTicks(y, m, d) + InternalTicks % TicksPerDay) | InternalKind);
+ return new DateTime((ulong)(DateToTicks(y, m, d) + InternalTicks % TicksPerDay) | InternalKind);
}
// Returns the DateTime resulting from adding a fractional number of
@@ -484,7 +484,7 @@ namespace System
{
throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_DateArithmetic);
}
- return new DateTime((UInt64)(ticks + value) | InternalKind);
+ return new DateTime((ulong)(ticks + value) | InternalKind);
}
// Returns the DateTime resulting from adding the given number of
@@ -511,8 +511,8 @@ namespace System
//
public static int Compare(DateTime t1, DateTime t2)
{
- Int64 ticks1 = t1.InternalTicks;
- Int64 ticks2 = t2.InternalTicks;
+ long ticks1 = t1.InternalTicks;
+ long ticks2 = t2.InternalTicks;
if (ticks1 > ticks2) return 1;
if (ticks1 < ticks2) return -1;
return 0;
@@ -524,7 +524,7 @@ namespace System
// occurs. Null is considered less than any instance.
//
// Returns a value less than zero if this object
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null) return 1;
if (!(value is DateTime))
@@ -610,7 +610,7 @@ namespace System
// is equal to the value of this DateTime. Returns false
// otherwise.
//
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
if (value is DateTime)
{
@@ -633,15 +633,15 @@ namespace System
return t1.InternalTicks == t2.InternalTicks;
}
- public static DateTime FromBinary(Int64 dateData)
+ public static DateTime FromBinary(long dateData)
{
- if ((dateData & (unchecked((Int64)LocalMask))) != 0)
+ if ((dateData & (unchecked((long)LocalMask))) != 0)
{
// Local times need to be adjusted as you move from one time zone to another,
// just as they are when serializing in text. As such the format for local times
// changes to store the ticks of the UTC time, but with flags that look like a
// local date.
- Int64 ticks = dateData & (unchecked((Int64)TicksMask));
+ long ticks = dateData & (unchecked((long)TicksMask));
// Negative ticks are stored in the top part of the range and should be converted back into a negative number
if (ticks > TicksCeiling - TicksPerDay)
{
@@ -649,8 +649,8 @@ namespace System
}
// Convert the ticks back to local. If the UTC ticks are out of range, we need to default to
// the UTC offset from MinValue and MaxValue to be consistent with Parse.
- Boolean isAmbiguousLocalDst = false;
- Int64 offsetTicks;
+ bool isAmbiguousLocalDst = false;
+ long offsetTicks;
if (ticks < MinTicks)
{
offsetTicks = TimeZoneInfo.GetLocalUtcOffset(DateTime.MinValue, TimeZoneInfoOptions.NoThrowOnInvalidTime).Ticks;
@@ -664,7 +664,7 @@ namespace System
// Because the ticks conversion between UTC and local is lossy, we need to capture whether the
// time is in a repeated hour so that it can be passed to the DateTime constructor.
DateTime utcDt = new DateTime(ticks, DateTimeKind.Utc);
- Boolean isDaylightSavings = false;
+ bool isDaylightSavings = false;
offsetTicks = TimeZoneInfo.GetUtcOffsetFromUtc(utcDt, TimeZoneInfo.Local, out isDaylightSavings, out isAmbiguousLocalDst).Ticks;
}
ticks += offsetTicks;
@@ -688,12 +688,12 @@ namespace System
// A version of ToBinary that uses the real representation and does not adjust local times. This is needed for
// scenarios where the serialized data must maintain compatibility
- internal static DateTime FromBinaryRaw(Int64 dateData)
+ internal static DateTime FromBinaryRaw(long dateData)
{
- Int64 ticks = dateData & (Int64)TicksMask;
+ long ticks = dateData & (long)TicksMask;
if (ticks < MinTicks || ticks > MaxTicks)
throw new ArgumentException(SR.Argument_DateTimeBadBinaryData, nameof(dateData));
- return new DateTime((UInt64)dateData);
+ return new DateTime((ulong)dateData);
}
// Creates a DateTime from a Windows filetime. A Windows filetime is
@@ -736,7 +736,7 @@ namespace System
info.AddValue(DateDataField, _dateData);
}
- public Boolean IsDaylightSavingTime()
+ public bool IsDaylightSavingTime()
{
if (Kind == DateTimeKind.Utc)
{
@@ -750,7 +750,7 @@ namespace System
return new DateTime(value.InternalTicks, kind);
}
- public Int64 ToBinary()
+ public long ToBinary()
{
if (Kind == DateTimeKind.Local)
{
@@ -765,17 +765,17 @@ namespace System
// end of the maximum range, and values just below minimum value are stored
// at the end of the ticks area, just below 2^62.
TimeSpan offset = TimeZoneInfo.GetLocalUtcOffset(this, TimeZoneInfoOptions.NoThrowOnInvalidTime);
- Int64 ticks = Ticks;
- Int64 storedTicks = ticks - offset.Ticks;
+ long ticks = Ticks;
+ long storedTicks = ticks - offset.Ticks;
if (storedTicks < 0)
{
storedTicks = TicksCeiling + storedTicks;
}
- return storedTicks | (unchecked((Int64)LocalMask));
+ return storedTicks | (unchecked((long)LocalMask));
}
else
{
- return (Int64)_dateData;
+ return (long)_dateData;
}
}
@@ -787,8 +787,8 @@ namespace System
{
get
{
- Int64 ticks = InternalTicks;
- return new DateTime((UInt64)(ticks - ticks % TicksPerDay) | InternalKind);
+ long ticks = InternalTicks;
+ return new DateTime((ulong)(ticks - ticks % TicksPerDay) | InternalKind);
}
}
@@ -796,7 +796,7 @@ namespace System
// to compute the year, day-of-year, month, or day part.
private int GetDatePart(int part)
{
- Int64 ticks = InternalTicks;
+ long ticks = InternalTicks;
// n = number of days since 1/1/0001
int n = (int)(ticks / TicksPerDay);
// y400 = number of whole 400-year periods since 1/1/0001
@@ -846,7 +846,7 @@ namespace System
// are needed rather than redoing the computations for each.
internal void GetDatePart(out int year, out int month, out int day)
{
- Int64 ticks = InternalTicks;
+ long ticks = InternalTicks;
// n = number of days since 1/1/0001
int n = (int)(ticks / TicksPerDay);
// y400 = number of whole 400-year periods since 1/1/0001
@@ -925,7 +925,7 @@ namespace System
//
public override int GetHashCode()
{
- Int64 ticks = InternalTicks;
+ long ticks = InternalTicks;
return unchecked((int)ticks) ^ (int)(ticks >> 32);
}
@@ -940,7 +940,7 @@ namespace System
}
}
- internal Boolean IsAmbiguousDaylightSavingTime()
+ internal bool IsAmbiguousDaylightSavingTime()
{
return (InternalKind == KindLocalAmbiguousDst);
}
@@ -1001,8 +1001,8 @@ namespace System
get
{
DateTime utc = UtcNow;
- Boolean isAmbiguousLocalDst = false;
- Int64 offset = TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc(utc, out isAmbiguousLocalDst).Ticks;
+ bool isAmbiguousLocalDst = false;
+ long offset = TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc(utc, out isAmbiguousLocalDst).Ticks;
long tick = utc.Ticks + offset;
if (tick > DateTime.MaxTicks)
{
@@ -1089,7 +1089,7 @@ namespace System
// date and optionally a time in a culture-specific or universal format.
// Leading and trailing whitespace characters are allowed.
//
- public static DateTime Parse(String s)
+ public static DateTime Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return (DateTimeParse.Parse(s, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.None));
@@ -1099,13 +1099,13 @@ namespace System
// date and optionally a time in a culture-specific or universal format.
// Leading and trailing whitespace characters are allowed.
//
- public static DateTime Parse(String s, IFormatProvider provider)
+ public static DateTime Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return (DateTimeParse.Parse(s, DateTimeFormatInfo.GetInstance(provider), DateTimeStyles.None));
}
- public static DateTime Parse(String s, IFormatProvider provider, DateTimeStyles styles)
+ public static DateTime Parse(string s, IFormatProvider provider, DateTimeStyles styles)
{
DateTimeFormatInfo.ValidateStyles(styles, nameof(styles));
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -1122,7 +1122,7 @@ namespace System
// date and optionally a time in a culture-specific or universal format.
// Leading and trailing whitespace characters are allowed.
//
- public static DateTime ParseExact(String s, String format, IFormatProvider provider)
+ public static DateTime ParseExact(string s, string format, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
if (format == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.format);
@@ -1133,7 +1133,7 @@ namespace System
// date and optionally a time in a culture-specific or universal format.
// Leading and trailing whitespace characters are allowed.
//
- public static DateTime ParseExact(String s, String format, IFormatProvider provider, DateTimeStyles style)
+ public static DateTime ParseExact(string s, string format, IFormatProvider provider, DateTimeStyles style)
{
DateTimeFormatInfo.ValidateStyles(style, nameof(style));
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -1141,20 +1141,13 @@ namespace System
return (DateTimeParse.ParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), style));
}
- // TODO https://github.com/dotnet/corefx/issues/25337: Remove this overload once corefx is updated to target the new signatures
- public static DateTime ParseExact(ReadOnlySpan<char> s, string format, IFormatProvider provider, DateTimeStyles style)
- {
- if (format == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.format);
- return ParseExact(s, (ReadOnlySpan<char>)format, provider, style);
- }
-
public static DateTime ParseExact(ReadOnlySpan<char> s, ReadOnlySpan<char> format, IFormatProvider provider, DateTimeStyles style = DateTimeStyles.None)
{
DateTimeFormatInfo.ValidateStyles(style, nameof(style));
return DateTimeParse.ParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), style);
}
- public static DateTime ParseExact(String s, String[] formats, IFormatProvider provider, DateTimeStyles style)
+ public static DateTime ParseExact(string s, string[] formats, IFormatProvider provider, DateTimeStyles style)
{
DateTimeFormatInfo.ValidateStyles(style, nameof(style));
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -1180,7 +1173,7 @@ namespace System
{
throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_DateArithmetic);
}
- return new DateTime((UInt64)(ticks - valueTicks) | InternalKind);
+ return new DateTime((ulong)(ticks - valueTicks) | InternalKind);
}
// This function is duplicated in COMDateTime.cpp
@@ -1239,9 +1232,9 @@ namespace System
{
return this;
}
- Boolean isDaylightSavings = false;
- Boolean isAmbiguousLocalDst = false;
- Int64 offset = TimeZoneInfo.GetUtcOffsetFromUtc(this, TimeZoneInfo.Local, out isDaylightSavings, out isAmbiguousLocalDst).Ticks;
+ bool isDaylightSavings = false;
+ bool isAmbiguousLocalDst = false;
+ long offset = TimeZoneInfo.GetUtcOffsetFromUtc(this, TimeZoneInfo.Local, out isDaylightSavings, out isAmbiguousLocalDst).Ticks;
long tick = Ticks + offset;
if (tick > DateTime.MaxTicks)
{
@@ -1260,59 +1253,55 @@ namespace System
return new DateTime(tick, DateTimeKind.Local, isAmbiguousLocalDst);
}
- public String ToLongDateString()
+ public string ToLongDateString()
{
- return DateTimeFormat.Format(this, "D", DateTimeFormatInfo.CurrentInfo);
+ return DateTimeFormat.Format(this, "D", null);
}
- public String ToLongTimeString()
+ public string ToLongTimeString()
{
- return DateTimeFormat.Format(this, "T", DateTimeFormatInfo.CurrentInfo);
+ return DateTimeFormat.Format(this, "T", null);
}
- public String ToShortDateString()
+ public string ToShortDateString()
{
- return DateTimeFormat.Format(this, "d", DateTimeFormatInfo.CurrentInfo);
+ return DateTimeFormat.Format(this, "d", null);
}
- public String ToShortTimeString()
+ public string ToShortTimeString()
{
- return DateTimeFormat.Format(this, "t", DateTimeFormatInfo.CurrentInfo);
+ return DateTimeFormat.Format(this, "t", null);
}
- public override String ToString()
+ public override string ToString()
{
- return DateTimeFormat.Format(this, null, DateTimeFormatInfo.CurrentInfo);
+ return DateTimeFormat.Format(this, null, null);
}
- public String ToString(String format)
+ public string ToString(string format)
{
- return DateTimeFormat.Format(this, format, DateTimeFormatInfo.CurrentInfo);
+ return DateTimeFormat.Format(this, format, null);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
- return DateTimeFormat.Format(this, null, DateTimeFormatInfo.GetInstance(provider));
+ return DateTimeFormat.Format(this, null, provider);
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
- return DateTimeFormat.Format(this, format, DateTimeFormatInfo.GetInstance(provider));
+ return DateTimeFormat.Format(this, format, provider);
}
- // TODO https://github.com/dotnet/corefx/issues/25337: Remove this overload once corefx is updated to target the new signatures
- public bool TryFormat(Span<char> destination, out int charsWritten, string format, IFormatProvider provider) =>
- TryFormat(destination, out charsWritten, (ReadOnlySpan<char>)format, provider);
-
public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format = default, IFormatProvider provider = null) =>
- DateTimeFormat.TryFormat(this, destination, out charsWritten, format, DateTimeFormatInfo.GetInstance(provider));
+ DateTimeFormat.TryFormat(this, destination, out charsWritten, format, provider);
public DateTime ToUniversalTime()
{
return TimeZoneInfo.ConvertTimeToUtc(this, TimeZoneInfoOptions.NoThrowOnInvalidTime);
}
- public static Boolean TryParse(String s, out DateTime result)
+ public static bool TryParse(string s, out DateTime result)
{
if (s == null)
{
@@ -1327,7 +1316,7 @@ namespace System
return DateTimeParse.TryParse(s, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.None, out result);
}
- public static Boolean TryParse(String s, IFormatProvider provider, DateTimeStyles styles, out DateTime result)
+ public static bool TryParse(string s, IFormatProvider provider, DateTimeStyles styles, out DateTime result)
{
DateTimeFormatInfo.ValidateStyles(styles, nameof(styles));
@@ -1346,7 +1335,7 @@ namespace System
return DateTimeParse.TryParse(s, DateTimeFormatInfo.GetInstance(provider), styles, out result);
}
- public static Boolean TryParseExact(String s, String format, IFormatProvider provider, DateTimeStyles style, out DateTime result)
+ public static bool TryParseExact(string s, string format, IFormatProvider provider, DateTimeStyles style, out DateTime result)
{
DateTimeFormatInfo.ValidateStyles(style, nameof(style));
@@ -1359,25 +1348,13 @@ namespace System
return DateTimeParse.TryParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), style, out result);
}
- // TODO https://github.com/dotnet/corefx/issues/25337: Remove this overload once corefx is updated to target the new signatures
- public static bool TryParseExact(ReadOnlySpan<char> s, string format, IFormatProvider provider, DateTimeStyles style, out DateTime result)
- {
- if (format == null)
- {
- result = default;
- return false;
- }
-
- return TryParseExact(s, (ReadOnlySpan<char>)format, provider, style, out result);
- }
-
public static bool TryParseExact(ReadOnlySpan<char> s, ReadOnlySpan<char> format, IFormatProvider provider, DateTimeStyles style, out DateTime result)
{
DateTimeFormatInfo.ValidateStyles(style, nameof(style));
return DateTimeParse.TryParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), style, out result);
}
- public static Boolean TryParseExact(String s, String[] formats, IFormatProvider provider, DateTimeStyles style, out DateTime result)
+ public static bool TryParseExact(string s, string[] formats, IFormatProvider provider, DateTimeStyles style, out DateTime result)
{
DateTimeFormatInfo.ValidateStyles(style, nameof(style));
@@ -1404,7 +1381,7 @@ namespace System
{
throw new ArgumentOutOfRangeException(nameof(t), SR.ArgumentOutOfRange_DateArithmetic);
}
- return new DateTime((UInt64)(ticks + valueTicks) | d.InternalKind);
+ return new DateTime((ulong)(ticks + valueTicks) | d.InternalKind);
}
public static DateTime operator -(DateTime d, TimeSpan t)
@@ -1415,7 +1392,7 @@ namespace System
{
throw new ArgumentOutOfRangeException(nameof(t), SR.ArgumentOutOfRange_DateArithmetic);
}
- return new DateTime((UInt64)(ticks - valueTicks) | d.InternalKind);
+ return new DateTime((ulong)(ticks - valueTicks) | d.InternalKind);
}
public static TimeSpan operator -(DateTime d1, DateTime d2)
@@ -1457,7 +1434,7 @@ namespace System
// Returns a string array containing all of the known date and time options for the
// current culture. The strings returned are properly formatted date and
// time strings for the current instance of DateTime.
- public String[] GetDateTimeFormats()
+ public string[] GetDateTimeFormats()
{
return (GetDateTimeFormats(CultureInfo.CurrentCulture));
}
@@ -1465,7 +1442,7 @@ namespace System
// Returns a string array containing all of the known date and time options for the
// using the information provided by IFormatProvider. The strings returned are properly formatted date and
// time strings for the current instance of DateTime.
- public String[] GetDateTimeFormats(IFormatProvider provider)
+ public string[] GetDateTimeFormats(IFormatProvider provider)
{
return (DateTimeFormat.GetAllDateTimes(this, DateTimeFormatInfo.GetInstance(provider)));
}
@@ -1474,7 +1451,7 @@ namespace System
// Returns a string array containing all of the date and time options for the
// given format format and current culture. The strings returned are properly formatted date and
// time strings for the current instance of DateTime.
- public String[] GetDateTimeFormats(char format)
+ public string[] GetDateTimeFormats(char format)
{
return (GetDateTimeFormats(format, CultureInfo.CurrentCulture));
}
@@ -1482,7 +1459,7 @@ namespace System
// Returns a string array containing all of the date and time options for the
// given format format and given culture. The strings returned are properly formatted date and
// time strings for the current instance of DateTime.
- public String[] GetDateTimeFormats(char format, IFormatProvider provider)
+ public string[] GetDateTimeFormats(char format, IFormatProvider provider)
{
return (DateTimeFormat.GetAllDateTimes(this, format, DateTimeFormatInfo.GetInstance(provider)));
}
@@ -1557,7 +1534,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "DateTime", "Double"));
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "DateTime", "Decimal"));
}
@@ -1567,7 +1544,7 @@ namespace System
return this;
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
@@ -1575,7 +1552,7 @@ namespace System
// Tries to construct a DateTime from a given year, month, day, hour,
// minute, second and millisecond.
//
- internal static Boolean TryCreate(int year, int month, int day, int hour, int minute, int second, int millisecond, out DateTime result)
+ internal static bool TryCreate(int year, int month, int day, int hour, int minute, int second, int millisecond, out DateTime result)
{
result = DateTime.MinValue;
if (year < 1 || year > 9999 || month < 1 || month > 12)
diff --git a/src/System.Private.CoreLib/shared/System/DateTimeOffset.cs b/src/System.Private.CoreLib/shared/System/DateTimeOffset.cs
index bb2196348..e89cbc6ca 100644
--- a/src/System.Private.CoreLib/shared/System/DateTimeOffset.cs
+++ b/src/System.Private.CoreLib/shared/System/DateTimeOffset.cs
@@ -31,11 +31,11 @@ namespace System
[StructLayout(LayoutKind.Auto)]
[Serializable]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct DateTimeOffset : IComparable, IFormattable, IComparable<DateTimeOffset>, IEquatable<DateTimeOffset>, ISerializable, IDeserializationCallback, ISpanFormattable
+ public readonly struct DateTimeOffset : IComparable, IFormattable, IComparable<DateTimeOffset>, IEquatable<DateTimeOffset>, ISerializable, IDeserializationCallback, ISpanFormattable
{
// Constants
- internal const Int64 MaxOffset = TimeSpan.TicksPerHour * 14;
- internal const Int64 MinOffset = -MaxOffset;
+ internal const long MaxOffset = TimeSpan.TicksPerHour * 14;
+ internal const long MinOffset = -MaxOffset;
private const long UnixEpochSeconds = DateTime.UnixEpochTicks / TimeSpan.TicksPerSecond; // 62,135,596,800
private const long UnixEpochMilliseconds = DateTime.UnixEpochTicks / TimeSpan.TicksPerMillisecond; // 62,135,596,800,000
@@ -49,8 +49,8 @@ namespace System
public static readonly DateTimeOffset UnixEpoch = new DateTimeOffset(DateTime.UnixEpochTicks, TimeSpan.Zero);
// Instance Fields
- private DateTime _dateTime;
- private Int16 _offsetMinutes;
+ private readonly DateTime _dateTime;
+ private readonly short _offsetMinutes;
// Constructors
@@ -447,7 +447,7 @@ namespace System
// argument must be another DateTimeOffset, or otherwise an exception
// occurs. Null is considered less than any instance.
//
- int IComparable.CompareTo(Object obj)
+ int IComparable.CompareTo(object obj)
{
if (obj == null) return 1;
if (!(obj is DateTimeOffset))
@@ -477,7 +477,7 @@ namespace System
// is equal to the value of this DateTimeOffset. Returns false
// otherwise.
//
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
if (obj is DateTimeOffset)
{
@@ -549,12 +549,12 @@ namespace System
// ----- SECTION: private serialization instance methods ----------------*
- void IDeserializationCallback.OnDeserialization(Object sender)
+ void IDeserializationCallback.OnDeserialization(object sender)
{
try
{
- _offsetMinutes = ValidateOffset(Offset);
- _dateTime = ValidateDate(ClockDateTime, Offset);
+ ValidateOffset(Offset);
+ ValidateDate(ClockDateTime, Offset);
}
catch (ArgumentException e)
{
@@ -583,7 +583,7 @@ namespace System
}
_dateTime = (DateTime)info.GetValue("DateTime", typeof(DateTime)); // Do not rename (binary serialization)
- _offsetMinutes = (Int16)info.GetValue("OffsetMinutes", typeof(Int16)); // Do not rename (binary serialization)
+ _offsetMinutes = (short)info.GetValue("OffsetMinutes", typeof(short)); // Do not rename (binary serialization)
}
// Returns the hash code for this DateTimeOffset.
@@ -597,7 +597,7 @@ namespace System
// date and optionally a time in a culture-specific or universal format.
// Leading and trailing whitespace characters are allowed.
//
- public static DateTimeOffset Parse(String input)
+ public static DateTimeOffset Parse(string input)
{
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
@@ -613,13 +613,13 @@ namespace System
// date and optionally a time in a culture-specific or universal format.
// Leading and trailing whitespace characters are allowed.
//
- public static DateTimeOffset Parse(String input, IFormatProvider formatProvider)
+ public static DateTimeOffset Parse(string input, IFormatProvider formatProvider)
{
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
return Parse(input, formatProvider, DateTimeStyles.None);
}
- public static DateTimeOffset Parse(String input, IFormatProvider formatProvider, DateTimeStyles styles)
+ public static DateTimeOffset Parse(string input, IFormatProvider formatProvider, DateTimeStyles styles)
{
styles = ValidateStyles(styles, nameof(styles));
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
@@ -643,7 +643,7 @@ namespace System
// date and optionally a time in a culture-specific or universal format.
// Leading and trailing whitespace characters are allowed.
//
- public static DateTimeOffset ParseExact(String input, String format, IFormatProvider formatProvider)
+ public static DateTimeOffset ParseExact(string input, string format, IFormatProvider formatProvider)
{
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
if (format == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.format);
@@ -654,7 +654,7 @@ namespace System
// date and optionally a time in a culture-specific or universal format.
// Leading and trailing whitespace characters are allowed.
//
- public static DateTimeOffset ParseExact(String input, String format, IFormatProvider formatProvider, DateTimeStyles styles)
+ public static DateTimeOffset ParseExact(string input, string format, IFormatProvider formatProvider, DateTimeStyles styles)
{
styles = ValidateStyles(styles, nameof(styles));
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
@@ -669,13 +669,6 @@ namespace System
return new DateTimeOffset(dateResult.Ticks, offset);
}
- // TODO https://github.com/dotnet/corefx/issues/25337: Remove this overload once corefx is updated to target the new signatures
- public static DateTimeOffset ParseExact(ReadOnlySpan<char> input, string format, IFormatProvider formatProvider, DateTimeStyles styles)
- {
- if (format == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.format);
- return ParseExact(input, (ReadOnlySpan<char>)format, formatProvider, styles);
- }
-
public static DateTimeOffset ParseExact(ReadOnlySpan<char> input, ReadOnlySpan<char> format, IFormatProvider formatProvider, DateTimeStyles styles = DateTimeStyles.None)
{
styles = ValidateStyles(styles, nameof(styles));
@@ -683,7 +676,7 @@ namespace System
return new DateTimeOffset(dateResult.Ticks, offset);
}
- public static DateTimeOffset ParseExact(String input, String[] formats, IFormatProvider formatProvider, DateTimeStyles styles)
+ public static DateTimeOffset ParseExact(string input, string[] formats, IFormatProvider formatProvider, DateTimeStyles styles)
{
styles = ValidateStyles(styles, nameof(styles));
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
@@ -760,43 +753,39 @@ namespace System
return new DateTimeOffset(UtcDateTime.ToLocalTime(throwOnOverflow));
}
- public override String ToString()
+ public override string ToString()
{
- return DateTimeFormat.Format(ClockDateTime, null, DateTimeFormatInfo.CurrentInfo, Offset);
+ return DateTimeFormat.Format(ClockDateTime, null, null, Offset);
}
- public String ToString(String format)
+ public string ToString(string format)
{
- return DateTimeFormat.Format(ClockDateTime, format, DateTimeFormatInfo.CurrentInfo, Offset);
+ return DateTimeFormat.Format(ClockDateTime, format, null, Offset);
}
- public String ToString(IFormatProvider formatProvider)
+ public string ToString(IFormatProvider formatProvider)
{
- return DateTimeFormat.Format(ClockDateTime, null, DateTimeFormatInfo.GetInstance(formatProvider), Offset);
+ return DateTimeFormat.Format(ClockDateTime, null, formatProvider, Offset);
}
- public String ToString(String format, IFormatProvider formatProvider)
+ public string ToString(string format, IFormatProvider formatProvider)
{
- return DateTimeFormat.Format(ClockDateTime, format, DateTimeFormatInfo.GetInstance(formatProvider), Offset);
+ return DateTimeFormat.Format(ClockDateTime, format, formatProvider, Offset);
}
- // TODO https://github.com/dotnet/corefx/issues/25337: Remove this overload once corefx is updated to target the new signatures
- public bool TryFormat(Span<char> destination, out int charsWritten, string format, IFormatProvider provider) =>
- TryFormat(destination, out charsWritten, (ReadOnlySpan<char>)format, provider);
-
public bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format = default, IFormatProvider formatProvider = null) =>
- DateTimeFormat.TryFormat(ClockDateTime, destination, out charsWritten, format, DateTimeFormatInfo.GetInstance(formatProvider), Offset);
+ DateTimeFormat.TryFormat(ClockDateTime, destination, out charsWritten, format, formatProvider, Offset);
public DateTimeOffset ToUniversalTime()
{
return new DateTimeOffset(UtcDateTime);
}
- public static Boolean TryParse(String input, out DateTimeOffset result)
+ public static bool TryParse(string input, out DateTimeOffset result)
{
TimeSpan offset;
DateTime dateResult;
- Boolean parsed = DateTimeParse.TryParse(input,
+ bool parsed = DateTimeParse.TryParse(input,
DateTimeFormatInfo.CurrentInfo,
DateTimeStyles.None,
out dateResult,
@@ -812,18 +801,18 @@ namespace System
return parsed;
}
- public static Boolean TryParse(String input, IFormatProvider formatProvider, DateTimeStyles styles, out DateTimeOffset result)
+ public static bool TryParse(string input, IFormatProvider formatProvider, DateTimeStyles styles, out DateTimeOffset result)
{
styles = ValidateStyles(styles, nameof(styles));
if (input == null)
{
- result = default(DateTimeOffset);
+ result = default;
return false;
}
TimeSpan offset;
DateTime dateResult;
- Boolean parsed = DateTimeParse.TryParse(input,
+ bool parsed = DateTimeParse.TryParse(input,
DateTimeFormatInfo.GetInstance(formatProvider),
styles,
out dateResult,
@@ -840,19 +829,19 @@ namespace System
return parsed;
}
- public static Boolean TryParseExact(String input, String format, IFormatProvider formatProvider, DateTimeStyles styles,
+ public static bool TryParseExact(string input, string format, IFormatProvider formatProvider, DateTimeStyles styles,
out DateTimeOffset result)
{
styles = ValidateStyles(styles, nameof(styles));
if (input == null || format == null)
{
- result = default(DateTimeOffset);
+ result = default;
return false;
}
TimeSpan offset;
DateTime dateResult;
- Boolean parsed = DateTimeParse.TryParseExact(input,
+ bool parsed = DateTimeParse.TryParseExact(input,
format,
DateTimeFormatInfo.GetInstance(formatProvider),
styles,
@@ -862,18 +851,6 @@ namespace System
return parsed;
}
- // TODO https://github.com/dotnet/corefx/issues/25337: Remove this overload once corefx is updated to target the new signatures
- public static bool TryParseExact(ReadOnlySpan<char> input, string format, IFormatProvider formatProvider, DateTimeStyles styles, out DateTimeOffset result)
- {
- if (format == null)
- {
- result = default;
- return false;
- }
-
- return TryParseExact(input, (ReadOnlySpan<char>)format, formatProvider, styles, out result);
- }
-
public static bool TryParseExact(
ReadOnlySpan<char> input, ReadOnlySpan<char> format, IFormatProvider formatProvider, DateTimeStyles styles, out DateTimeOffset result)
{
@@ -883,19 +860,19 @@ namespace System
return parsed;
}
- public static Boolean TryParseExact(String input, String[] formats, IFormatProvider formatProvider, DateTimeStyles styles,
+ public static bool TryParseExact(string input, string[] formats, IFormatProvider formatProvider, DateTimeStyles styles,
out DateTimeOffset result)
{
styles = ValidateStyles(styles, nameof(styles));
if (input == null)
{
- result = default(DateTimeOffset);
+ result = default;
return false;
}
TimeSpan offset;
DateTime dateResult;
- Boolean parsed = DateTimeParse.TryParseExactMultiple(input,
+ bool parsed = DateTimeParse.TryParseExactMultiple(input,
formats,
DateTimeFormatInfo.GetInstance(formatProvider),
styles,
@@ -915,9 +892,9 @@ namespace System
}
// Ensures the TimeSpan is valid to go in a DateTimeOffset.
- private static Int16 ValidateOffset(TimeSpan offset)
+ private static short ValidateOffset(TimeSpan offset)
{
- Int64 ticks = offset.Ticks;
+ long ticks = offset.Ticks;
if (ticks % TimeSpan.TicksPerMinute != 0)
{
throw new ArgumentException(SR.Argument_OffsetPrecision, nameof(offset));
@@ -926,7 +903,7 @@ namespace System
{
throw new ArgumentOutOfRangeException(nameof(offset), SR.Argument_OffsetOutOfRange);
}
- return (Int16)(offset.Ticks / TimeSpan.TicksPerMinute);
+ return (short)(offset.Ticks / TimeSpan.TicksPerMinute);
}
// Ensures that the time and offset are in range.
@@ -937,8 +914,8 @@ namespace System
Debug.Assert(offset.Ticks >= MinOffset && offset.Ticks <= MaxOffset, "Offset not validated.");
// This operation cannot overflow because offset should have already been validated to be within
- // 14 hours and the DateTime instance is more than that distance from the boundaries of Int64.
- Int64 utcTicks = dateTime.Ticks - offset.Ticks;
+ // 14 hours and the DateTime instance is more than that distance from the boundaries of long.
+ long utcTicks = dateTime.Ticks - offset.Ticks;
if (utcTicks < DateTime.MinTicks || utcTicks > DateTime.MaxTicks)
{
throw new ArgumentOutOfRangeException(nameof(offset), SR.Argument_UTCOutOfRange);
@@ -948,7 +925,7 @@ namespace System
return new DateTime(utcTicks, DateTimeKind.Unspecified);
}
- private static DateTimeStyles ValidateStyles(DateTimeStyles style, String parameterName)
+ private static DateTimeStyles ValidateStyles(DateTimeStyles style, string parameterName)
{
if ((style & DateTimeFormatInfo.InvalidDateTimeStyles) != 0)
{
diff --git a/src/System.Private.CoreLib/src/System/Decimal.DecCalc.cs b/src/System.Private.CoreLib/shared/System/Decimal.DecCalc.cs
index 05afe6b7e..22574c106 100644
--- a/src/System.Private.CoreLib/src/System/Decimal.DecCalc.cs
+++ b/src/System.Private.CoreLib/shared/System/Decimal.DecCalc.cs
@@ -5,68 +5,35 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using Internal.Runtime.CompilerServices;
+using X86 = System.Runtime.Intrinsics.X86;
namespace System
{
public partial struct Decimal
{
- // Low level accessors used by a DecCalc and formatting
- internal uint High
- {
- get { return uhi; }
- set { uhi = value; }
- }
+ // Low level accessors used by a DecCalc and formatting
+ internal uint High => (uint)hi;
+ internal uint Low => (uint)lo;
+ internal uint Mid => (uint)mid;
- internal uint Low
- {
- get { return ulo; }
- set { ulo = value; }
- }
+ internal bool IsNegative => flags < 0;
- internal uint Mid
- {
- get { return umid; }
- set { umid = value; }
- }
-
- internal bool IsNegative
- {
- get { return flags < 0; }
- set { uflags = (uflags & ~SignMask) | (value ? SignMask : 0); }
- }
-
- internal int Scale
- {
- get { return (byte)(uflags >> ScaleShift); }
- set { uflags = (uflags & ~ScaleMask) | ((uint)value << ScaleShift); }
- }
+ internal int Scale => (byte)(flags >> ScaleShift);
- private ulong Low64
- {
#if BIGENDIAN
- get { return ((ulong)umid << 32) | ulo; }
- set { umid = (uint)(value >> 32); ulo = (uint)value; }
+ private ulong Low64 => ((ulong)Mid << 32) | Low;
#else
- get => ulomidLE;
- set => ulomidLE = value;
+ private ulong Low64 => Unsafe.As<int, ulong>(ref Unsafe.AsRef(in lo));
#endif
- }
- #region APIs need by number formatting.
+ private static ref DecCalc AsMutable(ref decimal d) => ref Unsafe.As<decimal, DecCalc>(ref d);
- internal static uint DecDivMod1E9(ref Decimal value)
- {
- return DecCalc.DecDivMod1E9(ref value);
- }
-
- internal static void DecAddInt32(ref Decimal value, uint i)
- {
- DecCalc.DecAddInt32(ref value, i);
- }
+ #region APIs need by number formatting.
- internal static void DecMul10(ref Decimal value)
+ internal static uint DecDivMod1E9(ref decimal value)
{
- DecCalc.DecMul10(ref value);
+ return DecCalc.DecDivMod1E9(ref AsMutable(ref value));
}
#endregion
@@ -74,15 +41,60 @@ namespace System
/// <summary>
/// Class that contains all the mathematical calculations for decimal. Most of which have been ported from oleaut32.
/// </summary>
- private static class DecCalc
+ [StructLayout(LayoutKind.Explicit)]
+ private struct DecCalc
{
- // Constant representing the negative number that is the closest possible
- // Decimal value to -0m.
- private const Decimal NearNegativeZero = -0.000000000000000000000000001m;
+ // NOTE: Do not change the offsets of these fields. This structure must have the same layout as Decimal.
+ [FieldOffset(0)]
+ private uint uflags;
+ [FieldOffset(4)]
+ private uint uhi;
+ [FieldOffset(8)]
+ private uint ulo;
+ [FieldOffset(12)]
+ private uint umid;
+
+ /// <summary>
+ /// The low and mid fields combined in little-endian order
+ /// </summary>
+ [FieldOffset(8)]
+ private ulong ulomidLE;
+
+ private uint High
+ {
+ get => uhi;
+ set => uhi = value;
+ }
+
+ private uint Low
+ {
+ get => ulo;
+ set => ulo = value;
+ }
- // Constant representing the positive number that is the closest possible
- // Decimal value to +0m.
- private const Decimal NearPositiveZero = +0.000000000000000000000000001m;
+ private uint Mid
+ {
+ get => umid;
+ set => umid = value;
+ }
+
+ private bool IsNegative => (int)uflags < 0;
+
+ private int Scale => (byte)(uflags >> ScaleShift);
+
+ private ulong Low64
+ {
+#if BIGENDIAN
+ get { return ((ulong)umid << 32) | ulo; }
+ set { umid = (uint)(value >> 32); ulo = (uint)value; }
+#else
+ get => ulomidLE;
+ set => ulomidLE = value;
+#endif
+ }
+
+ private const uint SignMask = 0x80000000;
+ private const uint ScaleMask = 0x00FF0000;
private const int DEC_SCALE_MAX = 28;
@@ -90,12 +102,12 @@ namespace System
private const ulong TenToPowerEighteen = 1000000000000000000;
// The maximum power of 10 that a 32 bit integer can store
- private const Int32 MaxInt32Scale = 9;
+ private const int MaxInt32Scale = 9;
// The maximum power of 10 that a 64 bit integer can store
- private const Int32 MaxInt64Scale = 19;
+ private const int MaxInt64Scale = 19;
- // Fast access for 10^n where n is 0-9
- private static readonly UInt32[] s_powers10 = new UInt32[] {
+ // Fast access for 10^n where n is 0-9
+ private static readonly uint[] s_powers10 = new uint[] {
1,
10,
100,
@@ -173,24 +185,26 @@ namespace System
return (ulong)a * (ulong)b;
}
- private static ulong UInt64x64To128(ulong a, ulong b, out ulong dlHi)
+ private static void UInt64x64To128(ulong a, ulong b, ref DecCalc pdecOut)
{
- ulong low = (uint)a * (ulong)(uint)b; // lo partial prod
- ulong mid = (uint)a * (b >> 32); // mid 1 partial prod
- ulong high = (a >> 32) * (b >> 32);
+ ulong low = UInt32x32To64((uint)a, (uint)b); // lo partial prod
+ ulong mid = UInt32x32To64((uint)a, (uint)(b >> 32)); // mid 1 partial prod
+ ulong high = UInt32x32To64((uint)(a >> 32), (uint)(b >> 32));
high += mid >> 32;
low += mid <<= 32;
if (low < mid) // test for carry
high++;
- mid = (a >> 32) * (uint)b;
+ mid = UInt32x32To64((uint)(a >> 32), (uint)b);
high += mid >> 32;
low += mid <<= 32;
if (low < mid) // test for carry
high++;
- dlHi = high;
- return low;
+ if (high > uint.MaxValue)
+ throw new OverflowException(SR.Overflow_Decimal);
+ pdecOut.Low64 = low;
+ pdecOut.High = (uint)high;
}
/***
@@ -220,7 +234,7 @@ namespace System
tmp = bufNum.High64;
div = tmp / ulDen;
bufNum.High64 = div;
- tmp = ((tmp - div * ulDen) << 32) | bufNum.U0;
+ tmp = ((tmp - (uint)div * ulDen) << 32) | bufNum.U0;
if (tmp == 0)
return 0;
uint div32 = (uint)(tmp / ulDen);
@@ -236,52 +250,98 @@ namespace System
return (uint)(tmp - div * ulDen);
}
- private static uint Div96ByConst100000000(ref Buf12 bufNum)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static bool Div96ByConst(ref ulong high64, ref uint low, uint pow)
{
- const uint ulDen = 100000000;
- ulong tmp = bufNum.High64;
- ulong div = tmp / ulDen;
- bufNum.High64 = div;
- tmp = ((tmp - div * ulDen) << 32) | bufNum.U0;
- uint div32 = (uint)(tmp / ulDen);
- bufNum.U0 = div32;
- return (uint)tmp - div32 * ulDen;
- }
+#if BIT64
+ ulong div64 = high64 / pow;
+ uint div = (uint)((((high64 - div64 * pow) << 32) + low) / pow);
+ if (low == div * pow)
+ {
+ high64 = div64;
+ low = div;
+ return true;
+ }
+#else
+ // 32-bit RyuJIT doesn't convert 64-bit division by constant into multiplication by reciprocal. Do half-width divisions instead.
+ Debug.Assert(pow <= ushort.MaxValue);
+ uint num, mid32, low16, div;
+ if (high64 <= uint.MaxValue)
+ {
+ num = (uint)high64;
+ mid32 = num / pow;
+ num = (num - mid32 * pow) << 16;
+
+ num += low >> 16;
+ low16 = num / pow;
+ num = (num - low16 * pow) << 16;
+
+ num += (ushort)low;
+ div = num / pow;
+ if (num == div * pow)
+ {
+ high64 = mid32;
+ low = (low16 << 16) + div;
+ return true;
+ }
+ }
+ else
+ {
+ num = (uint)(high64 >> 32);
+ uint high32 = num / pow;
+ num = (num - high32 * pow) << 16;
- private static uint Div96ByConst10000(ref Buf12 bufNum)
- {
- const uint ulDen = 10000;
- ulong tmp = bufNum.High64;
- ulong div = tmp / ulDen;
- bufNum.High64 = div;
- tmp = ((tmp - div * ulDen) << 32) | bufNum.U0;
- uint div32 = (uint)(tmp / ulDen);
- bufNum.U0 = div32;
- return (uint)tmp - div32 * ulDen;
- }
+ num += (uint)high64 >> 16;
+ mid32 = num / pow;
+ num = (num - mid32 * pow) << 16;
- private static uint Div96ByConst100(ref Buf12 bufNum)
- {
- const uint ulDen = 100;
- ulong tmp = bufNum.High64;
- ulong div = tmp / ulDen;
- bufNum.High64 = div;
- tmp = ((tmp - div * ulDen) << 32) | bufNum.U0;
- uint div32 = (uint)(tmp / ulDen);
- bufNum.U0 = div32;
- return (uint)tmp - div32 * ulDen;
+ num += (ushort)high64;
+ div = num / pow;
+ num = (num - div * pow) << 16;
+ mid32 = div + (mid32 << 16);
+
+ num += low >> 16;
+ low16 = num / pow;
+ num = (num - low16 * pow) << 16;
+
+ num += (ushort)low;
+ div = num / pow;
+ if (num == div * pow)
+ {
+ high64 = ((ulong)high32 << 32) | mid32;
+ low = (low16 << 16) + div;
+ return true;
+ }
+ }
+#endif
+ return false;
}
- private static uint Div96ByConst10(ref Buf12 bufNum)
+ // Normalize (unscale) the number by trying to divide out 10^8, 10^4, 10^2, and 10^1.
+ // If a division by one of these powers returns a zero remainder, then we keep the quotient.
+ //
+ // Since 10 = 2 * 5, there must be a factor of 2 for every power of 10 we can extract.
+ // We use this as a quick test on whether to try a given power.
+ //
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void Unscale(ref uint low, ref ulong high64, ref int scale)
{
- const uint ulDen = 10;
- ulong tmp = bufNum.High64;
- ulong div = tmp / ulDen;
- bufNum.High64 = div;
- tmp = ((tmp - div * ulDen) << 32) | bufNum.U0;
- uint div32 = (uint)(tmp / ulDen);
- bufNum.U0 = div32;
- return (uint)tmp - div32 * ulDen;
+#if BIT64
+ while ((byte)low == 0 && scale >= 8 && Div96ByConst(ref high64, ref low, 100000000))
+ scale -= 8;
+
+ if ((low & 0xF) == 0 && scale >= 4 && Div96ByConst(ref high64, ref low, 10000))
+ scale -= 4;
+#else
+ while ((low & 0xF) == 0 && scale >= 4 && Div96ByConst(ref high64, ref low, 10000))
+ scale -= 4;
+#endif
+
+ if ((low & 3) == 0 && scale >= 2 && Div96ByConst(ref high64, ref low, 100))
+ scale -= 2;
+
+ if ((low & 1) == 0 && scale >= 1 && Div96ByConst(ref high64, ref low, 10))
+ scale--;
}
/***
@@ -531,33 +591,33 @@ PosRem:
// See if we need to scale the result. The combined scale must
// be <= DEC_SCALE_MAX and the upper 96 bits must be zero.
- //
+ //
// Start by figuring a lower bound on the scaling needed to make
// the upper 96 bits zero. iHiRes is the index into rgulRes[]
// of the highest non-zero ULONG.
- //
+ //
int iNewScale = 0;
if (iHiRes > 2)
{
iNewScale = (int)iHiRes * 32 - 64 - 1;
- iNewScale -= LeadingZeroCount(rgulRes[iHiRes]);
+ iNewScale -= X86.Lzcnt.IsSupported ? (int)X86.Lzcnt.LeadingZeroCount(rgulRes[iHiRes]) : LeadingZeroCount(rgulRes[iHiRes]);
// Multiply bit position by log10(2) to figure it's power of 10.
- // We scale the log by 256. log(2) = .30103, * 256 = 77. Doing this
+ // We scale the log by 256. log(2) = .30103, * 256 = 77. Doing this
// with a multiply saves a 96-byte lookup table. The power returned
// is <= the power of the number, so we must add one power of 10
// to make it's integer part zero after dividing by 256.
- //
+ //
// Note: the result of this multiplication by an approximation of
- // log10(2) have been exhaustively checked to verify it gives the
+ // log10(2) have been exhaustively checked to verify it gives the
// correct result. (There were only 95 to check...)
- //
+ //
iNewScale = ((iNewScale * 77) >> 8) + 1;
// iNewScale = min scale factor to make high 96 bits zero, 0 - 29.
// This reduces the scale factor of the result. If it exceeds the
// current scale of the result, we'll overflow.
- //
+ //
if (iNewScale > iScale)
goto ThrowOverflow;
}
@@ -570,8 +630,8 @@ PosRem:
if (iNewScale != 0)
{
- // Scale by the power of 10 given by iNewScale. Note that this is
- // NOT guaranteed to bring the number within 96 bits -- it could
+ // Scale by the power of 10 given by iNewScale. Note that this is
+ // NOT guaranteed to bring the number within 96 bits -- it could
// be 1 power of 10 short.
//
iScale -= iNewScale;
@@ -583,118 +643,41 @@ PosRem:
ulSticky |= remainder; // record remainder as sticky bit
uint ulPwr;
- uint high = rgulRes[iHiRes];
// Scaling loop specialized for each power of 10 because division by constant is an order of magnitude faster (especially for 64-bit division that's actually done by 128bit DIV on x64)
switch (iNewScale)
{
case 1:
- {
- const uint power = 10;
- remainder = high - (quotient = high / power) * power;
- for (uint i = iHiRes - 1; (int)i >= 0; i--)
- {
- ulong num = rgulRes[i] + ((ulong)remainder << 32);
- remainder = (uint)num - (rgulRes[i] = (uint)(num / power)) * power;
- }
- ulPwr = power;
- break;
- }
+ ulPwr = DivByConst(rgulRes, iHiRes, out quotient, out remainder, 10);
+ break;
case 2:
- {
- const uint power = 100;
- remainder = high - (quotient = high / power) * power;
- for (uint i = iHiRes - 1; (int)i >= 0; i--)
- {
- ulong num = rgulRes[i] + ((ulong)remainder << 32);
- remainder = (uint)num - (rgulRes[i] = (uint)(num / power)) * power;
- }
- ulPwr = power;
- break;
- }
+ ulPwr = DivByConst(rgulRes, iHiRes, out quotient, out remainder, 100);
+ break;
case 3:
- {
- const uint power = 1000;
- remainder = high - (quotient = high / power) * power;
- for (uint i = iHiRes - 1; (int)i >= 0; i--)
- {
- ulong num = rgulRes[i] + ((ulong)remainder << 32);
- remainder = (uint)num - (rgulRes[i] = (uint)(num / power)) * power;
- }
- ulPwr = power;
- break;
- }
+ ulPwr = DivByConst(rgulRes, iHiRes, out quotient, out remainder, 1000);
+ break;
case 4:
- {
- const uint power = 10000;
- remainder = high - (quotient = high / power) * power;
- for (uint i = iHiRes - 1; (int)i >= 0; i--)
- {
- ulong num = rgulRes[i] + ((ulong)remainder << 32);
- remainder = (uint)num - (rgulRes[i] = (uint)(num / power)) * power;
- }
- ulPwr = power;
- break;
- }
+ ulPwr = DivByConst(rgulRes, iHiRes, out quotient, out remainder, 10000);
+ break;
+#if BIT64
case 5:
- {
- const uint power = 100000;
- remainder = high - (quotient = high / power) * power;
- for (uint i = iHiRes - 1; (int)i >= 0; i--)
- {
- ulong num = rgulRes[i] + ((ulong)remainder << 32);
- remainder = (uint)num - (rgulRes[i] = (uint)(num / power)) * power;
- }
- ulPwr = power;
- break;
- }
+ ulPwr = DivByConst(rgulRes, iHiRes, out quotient, out remainder, 100000);
+ break;
case 6:
- {
- const uint power = 1000000;
- remainder = high - (quotient = high / power) * power;
- for (uint i = iHiRes - 1; (int)i >= 0; i--)
- {
- ulong num = rgulRes[i] + ((ulong)remainder << 32);
- remainder = (uint)num - (rgulRes[i] = (uint)(num / power)) * power;
- }
- ulPwr = power;
- break;
- }
+ ulPwr = DivByConst(rgulRes, iHiRes, out quotient, out remainder, 1000000);
+ break;
case 7:
- {
- const uint power = 10000000;
- remainder = high - (quotient = high / power) * power;
- for (uint i = iHiRes - 1; (int)i >= 0; i--)
- {
- ulong num = rgulRes[i] + ((ulong)remainder << 32);
- remainder = (uint)num - (rgulRes[i] = (uint)(num / power)) * power;
- }
- ulPwr = power;
- break;
- }
+ ulPwr = DivByConst(rgulRes, iHiRes, out quotient, out remainder, 10000000);
+ break;
case 8:
- {
- const uint power = 100000000;
- remainder = high - (quotient = high / power) * power;
- for (uint i = iHiRes - 1; (int)i >= 0; i--)
- {
- ulong num = rgulRes[i] + ((ulong)remainder << 32);
- remainder = (uint)num - (rgulRes[i] = (uint)(num / power)) * power;
- }
- ulPwr = power;
- break;
- }
+ ulPwr = DivByConst(rgulRes, iHiRes, out quotient, out remainder, 100000000);
+ break;
default:
- {
- const uint power = TenToPowerNine;
- remainder = high - (quotient = high / power) * power;
- for (uint i = iHiRes - 1; (int)i >= 0; i--)
- {
- ulong num = rgulRes[i] + ((ulong)remainder << 32);
- remainder = (uint)num - (rgulRes[i] = (uint)(num / power)) * power;
- }
- ulPwr = power;
- break;
- }
+ ulPwr = DivByConst(rgulRes, iHiRes, out quotient, out remainder, TenToPowerNine);
+ break;
+#else
+ default:
+ goto case 4;
+#endif
}
rgulRes[iHiRes] = quotient;
// If first quotient was 0, update iHiRes.
@@ -702,7 +685,11 @@ PosRem:
if (quotient == 0 && iHiRes != 0)
iHiRes--;
+#if BIT64
iNewScale -= MaxInt32Scale;
+#else
+ iNewScale -= 4;
+#endif
if (iNewScale > 0)
continue; // scale some more
@@ -733,7 +720,7 @@ PosRem:
if (iCur > 2)
{
- // The rounding caused us to carry beyond 96 bits.
+ // The rounding caused us to carry beyond 96 bits.
// Scale by 10 more.
//
if (iScale == 0)
@@ -757,13 +744,42 @@ ThrowOverflow:
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static int LeadingZeroCount(uint value)
+ private static unsafe uint DivByConst(uint* rgulRes, uint iHiRes, out uint quotient, out uint remainder, uint power)
{
-#if CORECLR
- if (System.Runtime.Intrinsics.X86.Lzcnt.IsSupported)
- return (int)System.Runtime.Intrinsics.X86.Lzcnt.LeadingZeroCount(value);
+ uint high = rgulRes[iHiRes];
+ remainder = high - (quotient = high / power) * power;
+ for (uint i = iHiRes - 1; (int)i >= 0; i--)
+ {
+#if BIT64
+ ulong num = rgulRes[i] + ((ulong)remainder << 32);
+ remainder = (uint)num - (rgulRes[i] = (uint)(num / power)) * power;
+#else
+ // 32-bit RyuJIT doesn't convert 64-bit division by constant into multiplication by reciprocal. Do half-width divisions instead.
+ Debug.Assert(power <= ushort.MaxValue);
+#if BIGENDIAN
+ const int low16 = 2, high16 = 0;
+#else
+ const int low16 = 0, high16 = 2;
+#endif
+ // byte* is used here because Roslyn doesn't do constant propagation for pointer arithmetic
+ uint num = *(ushort*)((byte*)rgulRes + i * 4 + high16) + (remainder << 16);
+ uint div = num / power;
+ remainder = num - div * power;
+ *(ushort*)((byte*)rgulRes + i * 4 + high16) = (ushort)div;
+
+ num = *(ushort*)((byte*)rgulRes + i * 4 + low16) + (remainder << 16);
+ div = num / power;
+ remainder = num - div * power;
+ *(ushort*)((byte*)rgulRes + i * 4 + low16) = (ushort)div;
#endif
+ }
+ return power;
+ }
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static int LeadingZeroCount(uint value)
+ {
+ Debug.Assert(value > 0);
int c = 1;
if ((value & 0xFFFF0000) == 0)
{
@@ -788,8 +804,8 @@ ThrowOverflow:
return c + ((int)value >> 31);
}
- // Adjust the quotient to deal with an overflow. We need to divide by 10,
- // feed in the high bit to undo the overflow and then round as required,
+ // Adjust the quotient to deal with an overflow. We need to divide by 10,
+ // feed in the high bit to undo the overflow and then round as required,
private static int OverflowUnscale(ref Buf12 bufQuo, int iScale, bool fRemainder)
{
if (--iScale < 0)
@@ -901,17 +917,17 @@ ThrowOverflow:
// In all cases, we already found we could not use the power one larger.
// So if we can use this power, it is the biggest, and we're done. If
- // we can't use this power, the one below it is correct for all cases
+ // we can't use this power, the one below it is correct for all cases
// unless it's 10^1 -- we might have to go to 10^0 (no scaling).
- //
+ //
if (ulResHi == powerOvfl[iCurScale - 1].Hi && ulResMidLo > powerOvfl[iCurScale - 1].MidLo)
iCurScale--;
HaveScale:
- // iCurScale = largest power of 10 we can scale by without overflow,
- // iCurScale < 9. See if this is enough to make scale factor
+ // iCurScale = largest power of 10 we can scale by without overflow,
+ // iCurScale < 9. See if this is enough to make scale factor
// positive if it isn't already.
- //
+ //
if (iCurScale + iScale < 0)
throw new OverflowException(SR.Overflow_Decimal);
@@ -930,9 +946,10 @@ ThrowOverflow:
return true;
}
- // DecAddSub adds or subtracts two decimal values. On return, d1 contains the result
- // of the operation. Passing in true for bSign means subtract and false means add.
- private static unsafe void DecAddSub(ref Decimal d1, ref Decimal d2, bool bSign)
+ // DecAddSub adds or subtracts two decimal values.
+ // On return, d1 contains the result of the operation and d2 is trashed.
+ // Passing in true for bSign means subtract and false means add.
+ internal static unsafe void DecAddSub(ref DecCalc d1, ref DecCalc d2, bool bSign)
{
ulong low64 = d1.Low64;
uint high = d1.High, flags = d1.uflags, d2flags = d2.uflags;
@@ -971,97 +988,113 @@ ThrowOverflow:
d2 = d1;
}
- Buf24 bufNum;
- _ = &bufNum; // workaround for CS0165
- uint ulPwr, iHiProd;
- ulong tmp64;
+ uint ulPwr;
+ ulong tmp64, tmpLow;
// d1 will need to be multiplied by 10^iScale so
// it will have the same scale as d2. We could be
// extending it to up to 192 bits of precision.
+
+ // Scan for zeros in the upper words.
//
- if (iScale <= MaxInt32Scale)
+ if (high == 0)
+ {
+ if (low64 <= uint.MaxValue)
+ {
+ if ((uint)low64 == 0)
+ {
+ // Left arg is zero, return right.
+ //
+ uint signFlags = flags & SignMask;
+ if (bSign)
+ signFlags ^= SignMask;
+ d1 = d2;
+ d1.uflags = d2.uflags & ScaleMask | signFlags;
+ return;
+ }
+
+ do
+ {
+ if (iScale <= MaxInt32Scale)
+ {
+ low64 = UInt32x32To64((uint)low64, s_powers10[iScale]);
+ goto AlignedAdd;
+ }
+ iScale -= MaxInt32Scale;
+ low64 = UInt32x32To64((uint)low64, TenToPowerNine);
+ } while (low64 <= uint.MaxValue);
+ }
+
+ do
+ {
+ ulPwr = TenToPowerNine;
+ if (iScale < MaxInt32Scale)
+ ulPwr = s_powers10[iScale];
+ tmpLow = UInt32x32To64((uint)low64, ulPwr);
+ tmp64 = UInt32x32To64((uint)(low64 >> 32), ulPwr) + (tmpLow >> 32);
+ low64 = (uint)tmpLow + (tmp64 << 32);
+ high = (uint)(tmp64 >> 32);
+ if ((iScale -= MaxInt32Scale) <= 0)
+ goto AlignedAdd;
+ } while (high == 0);
+ }
+
+ while (true)
{
// Scaling won't make it larger than 4 ULONGs
//
- ulPwr = s_powers10[iScale];
- ulong tmpLow = UInt32x32To64((uint)low64, ulPwr);
- tmp64 = (low64 >> 32) * ulPwr + (tmpLow >> 32);
+ ulPwr = TenToPowerNine;
+ if (iScale < MaxInt32Scale)
+ ulPwr = s_powers10[iScale];
+ tmpLow = UInt32x32To64((uint)low64, ulPwr);
+ tmp64 = UInt32x32To64((uint)(low64 >> 32), ulPwr) + (tmpLow >> 32);
low64 = (uint)tmpLow + (tmp64 << 32);
tmp64 >>= 32;
tmp64 += UInt32x32To64(high, ulPwr);
- if (tmp64 <= uint.MaxValue)
- {
- // Result fits in 96 bits. Use standard aligned add.
- //
- high = (uint)tmp64;
+
+ iScale -= MaxInt32Scale;
+ if (tmp64 > uint.MaxValue)
+ break;
+
+ high = (uint)tmp64;
+ // Result fits in 96 bits. Use standard aligned add.
+ if (iScale <= 0)
goto AlignedAdd;
- }
- bufNum.Low64 = low64;
- bufNum.Mid64 = tmp64;
- iHiProd = 3;
}
- else
- {
- iHiProd = 2;
- // Scan for zeros in the upper words.
- //
- if (high == 0)
+ // Have to scale by a bunch. Move the number to a buffer where it has room to grow as it's scaled.
+ //
+ Buf24 bufNum;
+ _ = &bufNum; // workaround for CS0165
+ bufNum.Low64 = low64;
+ bufNum.Mid64 = tmp64;
+ uint iHiProd = 3;
+
+ // Scaling loop, up to 10^9 at a time. iHiProd stays updated with index of highest non-zero ULONG.
+ //
+ for (; iScale > 0; iScale -= MaxInt32Scale)
+ {
+ ulPwr = TenToPowerNine;
+ if (iScale < MaxInt32Scale)
+ ulPwr = s_powers10[iScale];
+ tmp64 = 0;
+ uint* rgulNum = (uint*)&bufNum;
+ for (uint iCur = 0; ;)
{
- iHiProd = 1;
- if (low64 >> 32 == 0)
- {
- iHiProd = 0;
- if ((uint)low64 == 0)
- {
- // Left arg is zero, return right.
- //
- uint signFlags = flags & SignMask;
- if (bSign)
- signFlags ^= SignMask;
- d1 = d2;
- d1.uflags = d2.uflags & ScaleMask | signFlags;
- return;
- }
- }
+ Debug.Assert(iCur < bufNum.Length);
+ tmp64 += UInt32x32To64(rgulNum[iCur], ulPwr);
+ rgulNum[iCur] = (uint)tmp64;
+ iCur++;
+ tmp64 >>= 32;
+ if (iCur > iHiProd)
+ break;
}
- // Have to scale by a bunch. Move the number to a buffer
- // where it has room to grow as it's scaled.
- //
- bufNum.Low64 = low64;
- bufNum.U2 = high;
-
- // Scaling loop, up to 10^9 at a time. iHiProd stays updated
- // with index of highest non-zero ULONG.
- //
- for (; iScale > 0; iScale -= MaxInt32Scale)
+ if ((uint)tmp64 != 0)
{
- if (iScale >= MaxInt32Scale)
- ulPwr = TenToPowerNine;
- else
- ulPwr = s_powers10[iScale];
-
- tmp64 = 0;
- uint* rgulNum = (uint*)&bufNum;
- for (uint iCur = 0; ;)
- {
- Debug.Assert(iCur < bufNum.Length);
- tmp64 += UInt32x32To64(rgulNum[iCur], ulPwr);
- rgulNum[iCur] = (uint)tmp64;
- iCur++;
- tmp64 >>= 32;
- if (iCur > iHiProd)
- break;
- }
-
- if ((uint)tmp64 != 0)
- {
- // We're extending the result by another ULONG.
- Debug.Assert(iHiProd + 1 < bufNum.Length);
- rgulNum[++iHiProd] = (uint)tmp64;
- }
+ // We're extending the result by another ULONG.
+ Debug.Assert(iHiProd + 1 < bufNum.Length);
+ rgulNum[++iHiProd] = (uint)tmp64;
}
}
@@ -1090,16 +1123,8 @@ ThrowOverflow:
else if (high <= tmpHigh)
goto NoCarry;
- // If rgulNum has more than 96 bits of precision, then we need to
- // carry the subtraction into the higher bits. If it doesn't,
- // then we subtracted in the wrong order and have to flip the
- // sign of the result.
+ // Carry the subtraction into the higher bits.
//
- if (iHiProd <= 2)
- {
- goto SignFlip;
- }
-
uint* rgulNum = (uint*)&bufNum;
uint iCur = 3;
do
@@ -1107,8 +1132,8 @@ ThrowOverflow:
Debug.Assert(iCur < bufNum.Length);
} while (rgulNum[iCur++]-- == 0);
Debug.Assert(iHiProd < bufNum.Length);
- if (rgulNum[iHiProd] == 0)
- iHiProd--;
+ if (rgulNum[iHiProd] == 0 && --iHiProd <= 2)
+ goto ReturnResult;
}
else
{
@@ -1129,8 +1154,7 @@ ThrowOverflow:
goto NoCarry;
uint* rgulNum = (uint*)&bufNum;
- uint iCur = 3;
- do
+ for (uint iCur = 3; ++rgulNum[iCur++] == 0;)
{
Debug.Assert(iCur < bufNum.Length);
if (iHiProd < iCur)
@@ -1139,21 +1163,16 @@ ThrowOverflow:
iHiProd = iCur;
break;
}
- } while (++rgulNum[iCur++] == 0);
+ }
}
NoCarry:
- if (iHiProd > 2)
- {
- bufNum.Low64 = low64;
- bufNum.U2 = high;
- int scale = ScaleResult(&bufNum, iHiProd, (byte)(flags >> ScaleShift));
- flags = (flags & ~ScaleMask) | ((uint)scale << ScaleShift);
-
- low64 = bufNum.Low64;
- high = bufNum.U2;
- }
-
+ bufNum.Low64 = low64;
+ bufNum.U2 = high;
+ int scale = ScaleResult(&bufNum, iHiProd, (byte)(flags >> ScaleShift));
+ flags = (flags & ~ScaleMask) | ((uint)scale << ScaleShift);
+ low64 = bufNum.Low64;
+ high = bufNum.U2;
goto ReturnResult;
}
@@ -1172,7 +1191,7 @@ AlignedScale:
{
// The addition carried above 96 bits.
// Divide the value by 10, dropping the scale factor.
- //
+ //
if ((flags & ScaleMask) == 0)
throw new OverflowException(SR.Overflow_Decimal);
flags -= 1 << ScaleShift;
@@ -1254,7 +1273,7 @@ ReturnResult:
//**********************************************************************
// VarCyFromDec - Convert Currency to Decimal (similar to OleAut32 api.)
//**********************************************************************
- internal static long VarCyFromDec(ref Decimal pdecIn)
+ internal static long VarCyFromDec(ref DecCalc pdecIn)
{
long value;
@@ -1299,7 +1318,7 @@ ThrowOverflow:
//**********************************************************************
// VarDecCmp - Decimal Compare updated to return values similar to ICompareTo
//**********************************************************************
- internal static int VarDecCmp(ref Decimal pdecL, ref Decimal pdecR)
+ internal static int VarDecCmp(in decimal pdecL, in decimal pdecR)
{
if ((pdecR.Low | pdecR.Mid | pdecR.High) == 0)
{
@@ -1313,10 +1332,10 @@ ThrowOverflow:
int sign = (pdecL.flags >> 31) - (pdecR.flags >> 31);
if (sign != 0)
return sign;
- return VarDecCmpSub(ref pdecL, ref pdecR);
+ return VarDecCmpSub(in pdecL, in pdecR);
}
- private static int VarDecCmpSub(ref Decimal d1, ref Decimal d2)
+ private static int VarDecCmpSub(in decimal d1, in decimal d2)
{
int flags = d2.flags;
int sign = (flags >> 31) | 1;
@@ -1355,7 +1374,7 @@ ThrowOverflow:
{
uint ulPwr = iScale >= MaxInt32Scale ? TenToPowerNine : s_powers10[iScale];
ulong tmpLow = UInt32x32To64((uint)low64, ulPwr);
- ulong tmp = (low64 >> 32) * ulPwr + (tmpLow >> 32);
+ ulong tmp = UInt32x32To64((uint)(low64 >> 32), ulPwr) + (tmpLow >> 32);
low64 = (uint)tmpLow + (tmp << 32);
tmp >>= 32;
tmp += UInt32x32To64(high, ulPwr);
@@ -1387,48 +1406,114 @@ ThrowOverflow:
//**********************************************************************
// VarDecMul - Decimal Multiply
//**********************************************************************
- internal static unsafe void VarDecMul(ref Decimal pdecL, ref Decimal pdecR)
+ internal static unsafe void VarDecMul(ref DecCalc pdecL, ref DecCalc pdecR)
{
int iScale = (byte)(pdecL.uflags + pdecR.uflags >> ScaleShift);
- if ((pdecL.High | pdecL.Mid | pdecR.High | pdecR.Mid) == 0)
+ ulong tmp;
+ uint iHiProd;
+ Buf24 bufProd;
+ _ = &bufProd; // workaround for CS0165
+
+ if ((pdecL.High | pdecL.Mid) == 0)
{
- // Upper 64 bits are zero.
- //
- ulong low64 = UInt32x32To64(pdecL.Low, pdecR.Low);
- if (iScale > DEC_SCALE_MAX)
+ if ((pdecR.High | pdecR.Mid) == 0)
{
- // Result iScale is too big. Divide result by power of 10 to reduce it.
- // If the amount to divide by is > 19 the result is guaranteed
- // less than 1/2. [max value in 64 bits = 1.84E19]
+ // Upper 64 bits are zero.
//
- iScale -= DEC_SCALE_MAX + 1;
- if (iScale >= MaxInt64Scale)
- goto ReturnZero;
+ ulong low64 = UInt32x32To64(pdecL.Low, pdecR.Low);
+ if (iScale > DEC_SCALE_MAX)
+ {
+ // Result iScale is too big. Divide result by power of 10 to reduce it.
+ // If the amount to divide by is > 19 the result is guaranteed
+ // less than 1/2. [max value in 64 bits = 1.84E19]
+ //
+ if (iScale > DEC_SCALE_MAX + MaxInt64Scale)
+ goto ReturnZero;
- ulong ulPwr = s_ulongPowers10[iScale];
+ iScale -= DEC_SCALE_MAX + 1;
+ ulong ulPwr = s_ulongPowers10[iScale];
- // TODO: https://github.com/dotnet/coreclr/issues/3439
- ulong div = low64 / ulPwr;
- ulong remainder = low64 - div * ulPwr;
- low64 = div;
+ // TODO: https://github.com/dotnet/coreclr/issues/3439
+ tmp = low64 / ulPwr;
+ ulong remainder = low64 - tmp * ulPwr;
+ low64 = tmp;
- // Round result. See if remainder >= 1/2 of divisor.
- // Divisor is a power of 10, so it is always even.
- //
- ulPwr >>= 1;
- if (remainder >= ulPwr && (remainder > ulPwr || (low64 & 1) > 0))
- low64++;
+ // Round result. See if remainder >= 1/2 of divisor.
+ // Divisor is a power of 10, so it is always even.
+ //
+ ulPwr >>= 1;
+ if (remainder >= ulPwr && (remainder > ulPwr || ((uint)low64 & 1) > 0))
+ low64++;
- iScale = DEC_SCALE_MAX;
+ iScale = DEC_SCALE_MAX;
+ }
+ pdecL.Low64 = low64;
+ pdecL.uflags = ((pdecR.uflags ^ pdecL.uflags) & SignMask) | ((uint)iScale << ScaleShift);
+ return;
+ }
+ else
+ {
+ // Left value is 32-bit, result fits in 4 uints
+ tmp = UInt32x32To64(pdecL.Low, pdecR.Low);
+ bufProd.U0 = (uint)tmp;
+
+ tmp = UInt32x32To64(pdecL.Low, pdecR.Mid) + (tmp >> 32);
+ bufProd.U1 = (uint)tmp;
+ tmp >>= 32;
+
+ if (pdecR.High != 0)
+ {
+ tmp += UInt32x32To64(pdecL.Low, pdecR.High);
+ if (tmp > uint.MaxValue)
+ {
+ bufProd.Mid64 = tmp;
+ iHiProd = 3;
+ goto SkipScan;
+ }
+ }
+ if ((uint)tmp != 0)
+ {
+ bufProd.U2 = (uint)tmp;
+ iHiProd = 2;
+ goto SkipScan;
+ }
+ iHiProd = 1;
}
- pdecL.Low64 = low64;
+ }
+ else if ((pdecR.High | pdecR.Mid) == 0)
+ {
+ // Right value is 32-bit, result fits in 4 uints
+ tmp = UInt32x32To64(pdecR.Low, pdecL.Low);
+ bufProd.U0 = (uint)tmp;
+
+ tmp = UInt32x32To64(pdecR.Low, pdecL.Mid) + (tmp >> 32);
+ bufProd.U1 = (uint)tmp;
+ tmp >>= 32;
+
+ if (pdecL.High != 0)
+ {
+ tmp += UInt32x32To64(pdecR.Low, pdecL.High);
+ if (tmp > uint.MaxValue)
+ {
+ bufProd.Mid64 = tmp;
+ iHiProd = 3;
+ goto SkipScan;
+ }
+ }
+ if ((uint)tmp != 0)
+ {
+ bufProd.U2 = (uint)tmp;
+ iHiProd = 2;
+ goto SkipScan;
+ }
+ iHiProd = 1;
}
else
{
- // At least one operand has bits set in the upper 64 bits.
+ // Both operands have bits set in the upper 64 bits.
//
- // Compute and accumulate the 9 partial products into a
+ // Compute and accumulate the 9 partial products into a
// 192-bit (24-byte) result.
//
// [l-h][l-m][l-l] left high, middle, low
@@ -1447,11 +1532,8 @@ ThrowOverflow:
// ------------------------------
// [p-5][p-4][p-3][p-2][p-1][p-0] prod[] array
//
- uint iHiProd;
- Buf24 bufProd;
- _ = &bufProd; // workaround for CS0165
- ulong tmp = UInt32x32To64(pdecL.Low, pdecR.Low);
+ tmp = UInt32x32To64(pdecL.Low, pdecR.Low);
bufProd.U0 = (uint)tmp;
ulong tmp2 = UInt32x32To64(pdecL.Low, pdecR.Mid) + (tmp >> 32);
@@ -1460,10 +1542,9 @@ ThrowOverflow:
tmp += tmp2; // this could generate carry
bufProd.U1 = (uint)tmp;
if (tmp < tmp2) // detect carry
- tmp2 = 1UL << 32;
+ tmp2 = (tmp >> 32) | (1UL << 32);
else
- tmp2 = 0;
- tmp2 += tmp >> 32;
+ tmp2 = tmp >> 32;
tmp = UInt32x32To64(pdecL.Mid, pdecR.Mid) + tmp2;
@@ -1473,32 +1554,31 @@ ThrowOverflow:
//
tmp2 = UInt32x32To64(pdecL.Low, pdecR.High);
tmp += tmp2; // this could generate carry
- ulong tmp3 = 0;
+ uint tmp3 = 0;
if (tmp < tmp2) // detect carry
- tmp3 = 1UL << 32;
+ tmp3 = 1;
tmp2 = UInt32x32To64(pdecL.High, pdecR.Low);
tmp += tmp2; // this could generate carry
bufProd.U2 = (uint)tmp;
if (tmp < tmp2) // detect carry
- tmp3 += 1UL << 32;
- tmp2 = tmp3 + (tmp >> 32);
+ tmp3++;
+ tmp2 = ((ulong)tmp3 << 32) | (tmp >> 32);
tmp = UInt32x32To64(pdecL.Mid, pdecR.High);
tmp += tmp2; // this could generate carry
tmp3 = 0;
if (tmp < tmp2) // detect carry
- tmp3 = 1UL << 32;
+ tmp3 = 1;
tmp2 = UInt32x32To64(pdecL.High, pdecR.Mid);
tmp += tmp2; // this could generate carry
bufProd.U3 = (uint)tmp;
if (tmp < tmp2) // detect carry
- tmp3 += 1UL << 32;
- tmp3 += tmp >> 32;
+ tmp3++;
+ tmp = ((ulong)tmp3 << 32) | (tmp >> 32);
- tmp = UInt32x32To64(pdecL.High, pdecR.High) + tmp3;
- bufProd.High64 = tmp;
+ bufProd.High64 = UInt32x32To64(pdecL.High, pdecR.High) + tmp;
iHiProd = 5;
}
@@ -1509,42 +1589,39 @@ ThrowOverflow:
}
else
iHiProd = 1;
+ }
- // Check for leading zero ULONGs on the product
- //
- uint* rgulProd = (uint*)&bufProd;
- while (rgulProd[iHiProd] == 0)
- {
- if (iHiProd == 0)
- goto ReturnZero;
- iHiProd--;
- }
-
- if (iHiProd > 2 || iScale > DEC_SCALE_MAX)
- {
- iScale = ScaleResult(&bufProd, iHiProd, iScale);
- }
+ // Check for leading zero ULONGs on the product
+ //
+ uint* rgulProd = (uint*)&bufProd;
+ while (rgulProd[(int)iHiProd] == 0)
+ {
+ if (iHiProd == 0)
+ goto ReturnZero;
+ iHiProd--;
+ }
- pdecL.Low64 = bufProd.Low64;
- pdecL.High = bufProd.U2;
+SkipScan:
+ if (iHiProd > 2 || iScale > DEC_SCALE_MAX)
+ {
+ iScale = ScaleResult(&bufProd, iHiProd, iScale);
}
+ pdecL.Low64 = bufProd.Low64;
+ pdecL.High = bufProd.U2;
pdecL.uflags = ((pdecR.uflags ^ pdecL.uflags) & SignMask) | ((uint)iScale << ScaleShift);
return;
ReturnZero:
- pdecL = default(Decimal);
+ pdecL = default;
}
//**********************************************************************
// VarDecFromR4 - Convert float to Decimal
//**********************************************************************
-#if PROJECTN // Workaround ProjectN bug #555233
- [MethodImplAttribute(MethodImplOptions.NoOptimization)]
-#endif
- internal static void VarDecFromR4(float input, out Decimal pdecOut)
+ internal static void VarDecFromR4(float input, out DecCalc pdecOut)
{
- pdecOut = new Decimal();
+ pdecOut = default;
// The most we can scale by is 10^28, which is just slightly more
// than 2^93. So a float with an exponent of -94 could just
@@ -1556,7 +1633,7 @@ ReturnZero:
return; // result should be zeroed out
if (iExp > 96)
- goto ThrowOverflow;
+ throw new OverflowException(SR.Overflow_Decimal);
uint flags = 0;
if (input < 0)
@@ -1569,8 +1646,8 @@ ReturnZero:
// only 7 digits of precision, and we want to keep garbage digits
// out of the Decimal were making.
//
- // Calculate max power of 10 input value could have by multiplying
- // the exponent by log10(2). Using scaled integer multiplcation,
+ // Calculate max power of 10 input value could have by multiplying
+ // the exponent by log10(2). Using scaled integer multiplcation,
// log10(2) * 2 ^ 16 = .30103 * 65536 = 19728.3.
//
double dbl = input;
@@ -1604,10 +1681,17 @@ ReturnZero:
// Round to integer
//
- uint ulMant = (uint)dbl;
- dbl -= (double)ulMant; // difference between input & integer
- if (dbl > 0.5 || dbl == 0.5 && (ulMant & 1) != 0)
- ulMant++;
+ uint ulMant;
+ // with SSE4.1 support ROUNDSD can be used
+ if (X86.Sse41.IsSupported)
+ ulMant = (uint)(int)Math.Round(dbl);
+ else
+ {
+ ulMant = (uint)(int)dbl;
+ dbl -= (int)ulMant; // difference between input & integer
+ if (dbl > 0.5 || dbl == 0.5 && (ulMant & 1) != 0)
+ ulMant++;
+ }
if (ulMant == 0)
return; // result should be zeroed out
@@ -1628,12 +1712,7 @@ ReturnZero:
if (iPower > 18)
{
ulong low64 = UInt32x32To64(ulMant, s_powers10[iPower - 18]);
- low64 = UInt64x64To128(low64, TenToPowerEighteen, out ulong tmplong);
- ulong hi64 = tmplong;
- if (hi64 > uint.MaxValue)
- goto ThrowOverflow;
- pdecOut.Low64 = low64;
- pdecOut.High = (uint)hi64;
+ UInt64x64To128(low64, TenToPowerEighteen, ref pdecOut);
}
else
{
@@ -1652,8 +1731,8 @@ ReturnZero:
{
// Factor out powers of 10 to reduce the scale, if possible.
// The maximum number we could factor out would be 6. This
- // comes from the fact we have a 7-digit number, and the
- // MSD must be non-zero -- but the lower 6 digits could be
+ // comes from the fact we have a 7-digit number, and the
+ // MSD must be non-zero -- but the lower 6 digits could be
// zero. Note also the scale factor is never negative, so
// we can't scale by any more than the power we used to
// get the integer.
@@ -1702,21 +1781,14 @@ ReturnZero:
}
pdecOut.uflags = flags;
- return;
-
-ThrowOverflow:
- throw new OverflowException(SR.Overflow_Decimal);
}
//**********************************************************************
// VarDecFromR8 - Convert double to Decimal
//**********************************************************************
-#if PROJECTN // Workaround ProjectN bug #555233
- [MethodImplAttribute(MethodImplOptions.NoOptimization)]
-#endif
- internal static void VarDecFromR8(double input, out Decimal pdecOut)
+ internal static void VarDecFromR8(double input, out DecCalc pdecOut)
{
- pdecOut = new Decimal();
+ pdecOut = default;
// The most we can scale by is 10^28, which is just slightly more
// than 2^93. So a float with an exponent of -94 could just
@@ -1728,7 +1800,7 @@ ThrowOverflow:
return; // result should be zeroed out
if (iExp > 96)
- goto ThrowOverflow;
+ throw new OverflowException(SR.Overflow_Decimal);
uint flags = 0;
if (input < 0)
@@ -1741,8 +1813,8 @@ ThrowOverflow:
// only 15 digits of precision, and we want to keep garbage digits
// out of the Decimal were making.
//
- // Calculate max power of 10 input value could have by multiplying
- // the exponent by log10(2). Using scaled integer multiplcation,
+ // Calculate max power of 10 input value could have by multiplying
+ // the exponent by log10(2). Using scaled integer multiplcation,
// log10(2) * 2 ^ 16 = .30103 * 65536 = 19728.3.
//
double dbl = input;
@@ -1776,10 +1848,17 @@ ThrowOverflow:
// Round to int64
//
- ulong ulMant = (ulong)dbl;
- dbl -= (double)ulMant; // difference between input & integer
- if (dbl > 0.5 || dbl == 0.5 && (ulMant & 1) != 0)
- ulMant++;
+ ulong ulMant;
+ // with SSE4.1 support ROUNDSD can be used
+ if (X86.Sse41.IsSupported)
+ ulMant = (ulong)(long)Math.Round(dbl);
+ else
+ {
+ ulMant = (ulong)(long)dbl;
+ dbl -= (long)ulMant; // difference between input & integer
+ if (dbl > 0.5 || dbl == 0.5 && (ulMant & 1) != 0)
+ ulMant++;
+ }
if (ulMant == 0)
return; // result should be zeroed out
@@ -1805,20 +1884,15 @@ ThrowOverflow:
// Have a big power of 10.
//
Debug.Assert(iPower <= 14);
- ulong low64 = UInt64x64To128(ulMant, s_ulongPowers10[iPower - 1], out ulong tmplong);
- ulong hi64 = tmplong;
- if (hi64 > uint.MaxValue)
- goto ThrowOverflow;
- pdecOut.Low64 = low64;
- pdecOut.High = (uint)hi64;
+ UInt64x64To128(ulMant, s_ulongPowers10[iPower - 1], ref pdecOut);
}
}
else
{
// Factor out powers of 10 to reduce the scale, if possible.
// The maximum number we could factor out would be 14. This
- // comes from the fact we have a 15-digit number, and the
- // MSD must be non-zero -- but the lower 14 digits could be
+ // comes from the fact we have a 15-digit number, and the
+ // MSD must be non-zero -- but the lower 14 digits could be
// zero. Note also the scale factor is never negative, so
// we can't scale by any more than the power we used to
// get the integer.
@@ -1831,7 +1905,7 @@ ThrowOverflow:
{
const uint den = 100000000;
ulong div = ulMant / den;
- if (ulMant == div * den)
+ if ((uint)ulMant == (uint)(div * den))
{
ulMant = div;
iPower -= 8;
@@ -1843,7 +1917,7 @@ ThrowOverflow:
{
const uint den = 10000;
ulong div = ulMant / den;
- if (ulMant == div * den)
+ if ((uint)ulMant == (uint)(div * den))
{
ulMant = div;
iPower -= 4;
@@ -1855,7 +1929,7 @@ ThrowOverflow:
{
const uint den = 100;
ulong div = ulMant / den;
- if (ulMant == div * den)
+ if ((uint)ulMant == (uint)(div * den))
{
ulMant = div;
iPower -= 2;
@@ -1867,7 +1941,7 @@ ThrowOverflow:
{
const uint den = 10;
ulong div = ulMant / den;
- if (ulMant == div * den)
+ if ((uint)ulMant == (uint)(div * den))
{
ulMant = div;
iPower--;
@@ -1879,16 +1953,12 @@ ThrowOverflow:
}
pdecOut.uflags = flags;
- return;
-
-ThrowOverflow:
- throw new OverflowException(SR.Overflow_Decimal);
}
//**********************************************************************
// VarR4ToDec - Convert Decimal to float
//**********************************************************************
- internal static float VarR4FromDec(ref Decimal pdecIn)
+ internal static float VarR4FromDec(ref decimal pdecIn)
{
return (float)VarR8FromDec(ref pdecIn);
}
@@ -1896,9 +1966,9 @@ ThrowOverflow:
//**********************************************************************
// VarR8ToDec - Convert Decimal to double
//**********************************************************************
- internal static double VarR8FromDec(ref Decimal pdecIn)
+ internal static double VarR8FromDec(ref decimal pdecIn)
{
- // Value taken via reverse engineering the double that corrisponds to 2^65. (oleaut32 has ds2to64 = DEFDS(0, 0, DBLBIAS + 65, 0))
+ // Value taken via reverse engineering the double that corresponds to 2^64. (oleaut32 has ds2to64 = DEFDS(0, 0, DBLBIAS + 65, 0))
const double ds2to64 = 1.8446744073709552e+019;
double dbl = ((double)pdecIn.Low64 +
@@ -1910,23 +1980,28 @@ ThrowOverflow:
return dbl;
}
- // VarDecAdd divides two decimal values. On return, d1 contains the result
- // of the operation
- internal static void VarDecAdd(ref Decimal d1, ref Decimal d2)
+ internal static int GetHashCode(in decimal d)
{
- DecAddSub(ref d1, ref d2, false);
- }
+ if ((d.Low | d.Mid | d.High) == 0)
+ return 0;
- // VarDecSub divides two decimal values. On return, d1 contains the result
- // of the operation.
- internal static void VarDecSub(ref Decimal d1, ref Decimal d2)
- {
- DecAddSub(ref d1, ref d2, true);
+ uint flags = (uint)d.flags;
+ if ((flags & ScaleMask) == 0 || (d.Low & 1) != 0)
+ return (int)(flags ^ d.High ^ d.Mid ^ d.Low);
+
+ int scale = (byte)(flags >> ScaleShift);
+ uint low = d.Low;
+ ulong high64 = ((ulong)d.High << 32) | d.Mid;
+
+ Unscale(ref low, ref high64, ref scale);
+
+ flags = ((flags) & ~ScaleMask) | (uint)scale << ScaleShift;
+ return (int)(flags ^ (uint)(high64 >> 32) ^ (uint)high64 ^ low);
}
// VarDecDiv divides two decimal values. On return, d1 contains the result
// of the operation.
- internal static unsafe void VarDecDiv(ref Decimal d1, ref Decimal d2)
+ internal static unsafe void VarDecDiv(ref DecCalc d1, ref DecCalc d2)
{
Buf12 bufQuo, bufDivisor;
_ = &bufQuo; // workaround for CS0165
@@ -1944,7 +2019,7 @@ ThrowOverflow:
//
uint den = d2.Low;
if (den == 0)
- throw new DivideByZeroException(SR.Overflow_Decimal);
+ throw new DivideByZeroException();
bufQuo.Low64 = d1.Low64;
bufQuo.U2 = d1.High;
@@ -1965,23 +2040,23 @@ ThrowOverflow:
// We need to unscale if and only if we have a non-zero remainder
fUnscale = true;
- // We have computed a quotient based on the natural scale
- // ( <dividend scale> - <divisor scale> ). We have a non-zero
- // remainder, so now we should increase the scale if possible to
+ // We have computed a quotient based on the natural scale
+ // ( <dividend scale> - <divisor scale> ). We have a non-zero
+ // remainder, so now we should increase the scale if possible to
// include more quotient bits.
- //
- // If it doesn't cause overflow, we'll loop scaling by 10^9 and
- // computing more quotient bits as long as the remainder stays
- // non-zero. If scaling by that much would cause overflow, we'll
+ //
+ // If it doesn't cause overflow, we'll loop scaling by 10^9 and
+ // computing more quotient bits as long as the remainder stays
+ // non-zero. If scaling by that much would cause overflow, we'll
// drop out of the loop and scale by as much as we can.
- //
- // Scaling by 10^9 will overflow if rgulQuo[2].rgulQuo[1] >= 2^32 / 10^9
- // = 4.294 967 296. So the upper limit is rgulQuo[2] == 4 and
- // rgulQuo[1] == 0.294 967 296 * 2^32 = 1,266,874,889.7+. Since
- // quotient bits in rgulQuo[0] could be all 1's, then 1,266,874,888
- // is the largest value in rgulQuo[1] (when rgulQuo[2] == 4) that is
+ //
+ // Scaling by 10^9 will overflow if rgulQuo[2].rgulQuo[1] >= 2^32 / 10^9
+ // = 4.294 967 296. So the upper limit is rgulQuo[2] == 4 and
+ // rgulQuo[1] == 0.294 967 296 * 2^32 = 1,266,874,889.7+. Since
+ // quotient bits in rgulQuo[0] could be all 1's, then 1,266,874,888
+ // is the largest value in rgulQuo[1] (when rgulQuo[2] == 4) that is
// assured not to overflow.
- //
+ //
if (iScale == DEC_SCALE_MAX || (iCurScale = SearchScale(ref bufQuo, iScale)) == 0)
{
// No more scaling to be done, but remainder is non-zero.
@@ -2016,9 +2091,9 @@ ThrowOverflow:
{
// Divisor has bits set in the upper 64 bits.
//
- // Divisor must be fully normalized (shifted so bit 31 of the most
- // significant ULONG is 1). Locate the MSB so we know how much to
- // normalize by. The dividend will be shifted by the same amount so
+ // Divisor must be fully normalized (shifted so bit 31 of the most
+ // significant ULONG is 1). Locate the MSB so we know how much to
+ // normalize by. The dividend will be shifted by the same amount so
// the quotient is not changed.
//
bufDivisor.Low64 = d2.Low64;
@@ -2027,10 +2102,10 @@ ThrowOverflow:
if (ulTmp == 0)
ulTmp = d2.Mid;
- iCurScale = LeadingZeroCount(ulTmp);
+ iCurScale = X86.Lzcnt.IsSupported ? (int)X86.Lzcnt.LeadingZeroCount(ulTmp) : LeadingZeroCount(ulTmp);
// Shift both dividend and divisor left by iCurScale.
- //
+ //
Buf16 bufRem;
_ = &bufRem; // workaround for CS0165
bufRem.Low64 = d1.Low64 << iCurScale;
@@ -2040,9 +2115,9 @@ ThrowOverflow:
if (bufDivisor.U2 == 0)
{
- // Have a 64-bit divisor in sdlDivisor. The remainder
+ // Have a 64-bit divisor in sdlDivisor. The remainder
// (currently 96 bits spread over 4 ULONGs) will be < divisor.
- //
+ //
bufQuo.U1 = Div96By64(ref *(Buf12*)&bufRem.U1, divisor);
bufQuo.U0 = Div96By64(ref *(Buf12*)&bufRem, divisor);
@@ -2062,9 +2137,9 @@ ThrowOverflow:
// We need to unscale if and only if we have a non-zero remainder
fUnscale = true;
- // Remainder is non-zero. Scale up quotient and remainder by
+ // Remainder is non-zero. Scale up quotient and remainder by
// powers of 10 so we can compute more significant bits.
- //
+ //
if (iScale == DEC_SCALE_MAX || (iCurScale = SearchScale(ref bufQuo, iScale)) == 0)
{
// No more scaling to be done, but remainder is non-zero.
@@ -2103,7 +2178,7 @@ ThrowOverflow:
bufDivisor.Low64 = divisor;
bufDivisor.U2 = tmp;
- // The remainder (currently 96 bits spread over 4 ULONGs)
+ // The remainder (currently 96 bits spread over 4 ULONGs)
// will be < divisor.
//
bufQuo.Low64 = Div128By96(ref bufRem, ref bufDivisor);
@@ -2123,7 +2198,7 @@ ThrowOverflow:
// We need to unscale if and only if we have a non-zero remainder
fUnscale = true;
- // Remainder is non-zero. Scale up quotient and remainder by
+ // Remainder is non-zero. Scale up quotient and remainder by
// powers of 10 so we can compute more significant bits.
//
if (iScale == DEC_SCALE_MAX || (iCurScale = SearchScale(ref bufQuo, iScale)) == 0)
@@ -2166,78 +2241,22 @@ ThrowOverflow:
}
Unscale:
- ulong low64 = bufQuo.Low64;
- uint high = bufQuo.U2;
- // We need to unscale if and only if we have a non-zero remainder
if (fUnscale)
{
- // Try extracting any extra powers of 10 we may have
- // added. We do this by trying to divide out 10^8, 10^4, 10^2, and 10^1.
- // If a division by one of these powers returns a zero remainder, then
- // we keep the quotient. If the remainder is not zero, then we restore
- // the previous value.
- //
- // Since 10 = 2 * 5, there must be a factor of 2 for every power of 10
- // we can extract. We use this as a quick test on whether to try a
- // given power.
- //
- while ((byte)low64 == 0 && iScale >= 8)
- {
- if (Div96ByConst100000000(ref bufQuo) == 0)
- {
- low64 = bufQuo.Low64;
- high = bufQuo.U2;
- iScale -= 8;
- }
- else
- {
- bufQuo.Low64 = low64;
- bufQuo.U2 = high;
- break;
- }
- }
-
- if (((uint)low64 & 0xF) == 0 && iScale >= 4)
- {
- if (Div96ByConst10000(ref bufQuo) == 0)
- {
- low64 = bufQuo.Low64;
- high = bufQuo.U2;
- iScale -= 4;
- }
- else
- {
- bufQuo.Low64 = low64;
- bufQuo.U2 = high;
- }
- }
-
- if (((uint)low64 & 3) == 0 && iScale >= 2)
- {
- if (Div96ByConst100(ref bufQuo) == 0)
- {
- low64 = bufQuo.Low64;
- high = bufQuo.U2;
- iScale -= 2;
- }
- else
- {
- bufQuo.Low64 = low64;
- bufQuo.U2 = high;
- }
- }
-
- if (((uint)low64 & 1) == 0 && iScale >= 1 && Div96ByConst10(ref bufQuo) == 0)
- {
- low64 = bufQuo.Low64;
- high = bufQuo.U2;
- iScale -= 1;
- }
+ uint low = bufQuo.U0;
+ ulong high64 = bufQuo.High64;
+ Unscale(ref low, ref high64, ref iScale);
+ d1.Low = low;
+ d1.Mid = (uint)high64;
+ d1.High = (uint)(high64 >> 32);
+ }
+ else
+ {
+ d1.Low64 = bufQuo.Low64;
+ d1.High = bufQuo.U2;
}
d1.uflags = ((d1.uflags ^ d2.uflags) & SignMask) | ((uint)iScale << ScaleShift);
- d1.High = high;
- d1.Low64 = low64;
return;
RoundUp:
@@ -2256,52 +2275,60 @@ ThrowOverflow:
//**********************************************************************
// VarDecMod - Computes the remainder between two decimals
//**********************************************************************
- internal static Decimal VarDecMod(ref Decimal d1, ref Decimal d2)
+ internal static void VarDecMod(ref DecCalc d1, ref DecCalc d2)
{
- // OleAut doesn't provide a VarDecMod.
+ if ((d2.ulo | d2.umid | d2.uhi) == 0)
+ throw new DivideByZeroException();
+
+ if ((d1.ulo | d1.umid | d1.uhi) == 0)
+ return;
// In the operation x % y the sign of y does not matter. Result will have the sign of x.
d2.uflags = (d2.uflags & ~SignMask) | (d1.uflags & SignMask);
+ int cmp = VarDecCmpSub(in Unsafe.As<DecCalc, decimal>(ref d1), in Unsafe.As<DecCalc, decimal>(ref d2));
+ if (cmp == 0)
+ {
+ d1.ulo = 0;
+ d1.umid = 0;
+ d1.uhi = 0;
+ if (d2.uflags > d1.uflags)
+ d1.uflags = d2.uflags;
+ return;
+ }
+ if ((cmp ^ (int)(d1.uflags & SignMask)) < 0)
+ return;
// This piece of code is to work around the fact that Dividing a decimal with 28 digits number by decimal which causes
// causes the result to be 28 digits, can cause to be incorrectly rounded up.
// eg. Decimal.MaxValue / 2 * Decimal.MaxValue will overflow since the division by 2 was rounded instead of being truncked.
- if (Math.Abs(d1) < Math.Abs(d2))
- {
- return d1;
- }
- d1 -= d2;
-
- if (d1 == 0)
- {
- // The sign of D1 will be wrong here. Fall through so that we still get a DivideByZeroException
- d1.uflags = (d1.uflags & ~SignMask) | (d2.uflags & SignMask);
- }
-
- // Formula: d1 - (RoundTowardsZero(d1 / d2) * d2)
- Decimal dividedResult = Truncate(d1 / d2);
- Decimal multipliedResult = dividedResult * d2;
- Decimal result = d1 - multipliedResult;
+ DecCalc tmp = d2;
+ DecAddSub(ref d1, ref tmp, true);
+
+ // Formula: d1 - (RoundTowardsZero(d1 / d2) * d2)
+ tmp = d1;
+ VarDecDiv(ref tmp, ref d2);
+ Truncate(ref Unsafe.As<DecCalc, decimal>(ref tmp));
+ VarDecMul(ref tmp, ref d2);
+ uint flags = d1.uflags;
+ DecAddSub(ref d1, ref tmp, true);
// See if the result has crossed 0
- if ((d1.uflags & SignMask) != (result.uflags & SignMask))
+ if (((flags ^ d1.uflags) & SignMask) != 0)
{
- if (NearNegativeZero <= result && result <= NearPositiveZero)
+ if ((d1.Low | d1.Mid | d1.High) == 0 || d1.Scale == DEC_SCALE_MAX && d1.Low64 == 1 && d1.High == 0)
{
// Certain Remainder operations on decimals with 28 significant digits round
- // to [+-]0.000000000000000000000000001m instead of [+-]0m during the intermediate calculations.
+ // to [+-]0.0000000000000000000000000001m instead of [+-]0m during the intermediate calculations.
// 'zero' results just need their sign corrected.
- result.uflags = (result.uflags & ~SignMask) | (d1.uflags & SignMask);
+ d1.uflags ^= SignMask;
}
else
{
// If the division rounds up because it runs out of digits, the multiplied result can end up with a larger
// absolute value and the result of the formula crosses 0. To correct it can add the divisor back.
- result += d2;
+ DecAddSub(ref d1, ref d2, false);
}
}
-
- return result;
}
internal enum RoundingMode
@@ -2314,7 +2341,7 @@ ThrowOverflow:
}
// Does an in-place round by the specified scale
- internal static void InternalRound(ref Decimal d, uint scale, RoundingMode mode)
+ internal static void InternalRound(ref DecCalc d, uint scale, RoundingMode mode)
{
// the scale becomes the desired decimal count
d.uflags -= scale << ScaleShift;
@@ -2434,74 +2461,19 @@ done:
return;
}
-#region Number Formatting helpers
-
- private static uint D32DivMod1E9(uint hi32, ref uint lo32)
- {
- ulong n = (ulong)hi32 << 32 | lo32;
- lo32 = (uint)(n / 1000000000);
- return (uint)(n % 1000000000);
- }
-
- internal static uint DecDivMod1E9(ref Decimal value)
- {
- return D32DivMod1E9(D32DivMod1E9(D32DivMod1E9(0,
- ref value.uhi),
- ref value.umid),
- ref value.ulo);
- }
-
- internal static void DecAddInt32(ref Decimal value, uint i)
- {
- if (D32AddCarry(ref value.ulo, i))
- {
- if (D32AddCarry(ref value.umid, 1))
- D32AddCarry(ref value.uhi, 1);
- }
- }
-
- private static bool D32AddCarry(ref uint value, uint i)
+ internal static uint DecDivMod1E9(ref DecCalc value)
{
- uint v = value;
- uint sum = v + i;
- value = sum;
- return (sum < v) || (sum < i);
+ ulong high64 = ((ulong)value.uhi << 32) + value.umid;
+ ulong div64 = high64 / TenToPowerNine;
+ value.uhi = (uint)(div64 >> 32);
+ value.umid = (uint)div64;
+
+ ulong num = ((high64 - (uint)div64 * TenToPowerNine) << 32) + value.ulo;
+ uint div = (uint)(num / TenToPowerNine);
+ value.ulo = div;
+ return (uint)num - div * TenToPowerNine;
}
- internal static void DecMul10(ref Decimal value)
- {
- Decimal d = value;
- DecShiftLeft(ref value);
- DecShiftLeft(ref value);
- DecAdd(ref value, d);
- DecShiftLeft(ref value);
- }
-
- private static void DecShiftLeft(ref Decimal value)
- {
- uint c0 = (value.Low & 0x80000000) != 0 ? 1u : 0u;
- uint c1 = (value.Mid & 0x80000000) != 0 ? 1u : 0u;
- value.Low = value.Low << 1;
- value.Mid = (value.Mid << 1) | c0;
- value.High = (value.High << 1) | c1;
- }
-
- private static void DecAdd(ref Decimal value, Decimal d)
- {
- if (D32AddCarry(ref value.ulo, d.Low))
- {
- if (D32AddCarry(ref value.umid, 1))
- D32AddCarry(ref value.uhi, 1);
- }
-
- if (D32AddCarry(ref value.umid, d.Mid))
- D32AddCarry(ref value.uhi, 1);
-
- D32AddCarry(ref value.uhi, d.High);
- }
-
-#endregion
-
struct PowerOvfl
{
public readonly uint Hi;
@@ -2518,7 +2490,7 @@ done:
{
// This is a table of the largest values that can be in the upper two
// ULONGs of a 96-bit number that will not overflow when multiplied
- // by a given power. For the upper word, this is a table of
+ // by a given power. For the upper word, this is a table of
// 2^32 / 10^n for 1 <= n <= 8. For the lower word, this is the
// remaining fraction part * 2^32. 2^32 = 4294967296.
//
diff --git a/src/System.Private.CoreLib/src/System/Decimal.cs b/src/System.Private.CoreLib/shared/System/Decimal.cs
index a6bd05552..7e472b70c 100644
--- a/src/System.Private.CoreLib/src/System/Decimal.cs
+++ b/src/System.Private.CoreLib/shared/System/Decimal.cs
@@ -52,12 +52,13 @@ namespace System
// throw an exception. A conversion from float or double to
// Decimal throws an OverflowException if the value is not within
// the range of the Decimal type.
+ [StructLayout(LayoutKind.Sequential)]
[Serializable]
- [StructLayout(LayoutKind.Explicit)]
+ [System.Runtime.Versioning.NonVersionable] // This only applies to field layout
#if !MONO
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
#endif
- public partial struct Decimal : IFormattable, IComparable, IConvertible, IComparable<Decimal>, IEquatable<Decimal>, IDeserializationCallback, ISpanFormattable
+ public readonly partial struct Decimal : IFormattable, IComparable, IConvertible, IComparable<decimal>, IEquatable<decimal>, IDeserializationCallback, ISpanFormattable
{
// Sign mask for the flags field. A value of zero in this bit indicates a
// positive Decimal value, and a value of one in this bit indicates a
@@ -65,34 +66,32 @@ namespace System
//
// Look at OleAut's DECIMAL_NEG constant to check for negative values
// in native code.
- private const uint SignMask = 0x80000000;
+ private const int SignMask = unchecked((int)0x80000000);
// Scale mask for the flags field. This byte in the flags field contains
// the power of 10 to divide the Decimal value by. The scale byte must
// contain a value between 0 and 28 inclusive.
- private const uint ScaleMask = 0x00FF0000;
+ private const int ScaleMask = 0x00FF0000;
// Number of bits scale is shifted by.
private const int ScaleShift = 16;
// Constant representing the Decimal value 0.
- public const Decimal Zero = 0m;
+ public const decimal Zero = 0m;
// Constant representing the Decimal value 1.
- public const Decimal One = 1m;
+ public const decimal One = 1m;
// Constant representing the Decimal value -1.
- public const Decimal MinusOne = -1m;
+ public const decimal MinusOne = -1m;
// Constant representing the largest possible Decimal value. The value of
// this constant is 79,228,162,514,264,337,593,543,950,335.
- public const Decimal MaxValue = 79228162514264337593543950335m;
+ public const decimal MaxValue = 79228162514264337593543950335m;
// Constant representing the smallest possible Decimal value. The value of
// this constant is -79,228,162,514,264,337,593,543,950,335.
- public const Decimal MinValue = -79228162514264337593543950335m;
-
- private const int CurrencyScale = 4; // Divide the "Int64" representation by 1E4 to get the "true" value of the Currency.
+ public const decimal MinValue = -79228162514264337593543950335m;
// The lo, mid, hi, and flags fields contain the representation of the
// Decimal value. The lo, mid, and hi fields contain the 96-bit integer
@@ -103,51 +102,28 @@ namespace System
// and finally bit 31 indicates the sign of the Decimal value, 0 meaning
// positive and 1 meaning negative.
//
- // NOTE: Do not change the offsets of these fields. This structure maps to the OleAut DECIMAL structure
- // and can be passed as such in P/Invokes.
- [FieldOffset(0)]
- private int flags; // Do not rename (binary serialization)
- [FieldOffset(4)]
- private int hi; // Do not rename (binary serialization)
- [FieldOffset(8)]
- private int lo; // Do not rename (binary serialization)
- [FieldOffset(12)]
- private int mid; // Do not rename (binary serialization)
-
- // NOTE: This set of fields overlay the ones exposed to serialization (which have to be signed ints for serialization compat.)
- // The code inside Decimal was ported from C++ and expect unsigned values.
- [FieldOffset(0), NonSerialized]
- private uint uflags;
- [FieldOffset(4), NonSerialized]
- private uint uhi;
- [FieldOffset(8), NonSerialized]
- private uint ulo;
- [FieldOffset(12), NonSerialized]
- private uint umid;
-
- /// <summary>
- /// The low and mid fields combined in little-endian order
- /// </summary>
- [FieldOffset(8), NonSerialized]
- private ulong ulomidLE;
+ // NOTE: Do not change the order in which these fields are declared. The
+ // native methods in this class rely on this particular order.
+ // Do not rename (binary serialization).
+ private readonly int flags;
+ private readonly int hi;
+ private readonly int lo;
+ private readonly int mid;
// Constructs a Decimal from an integer value.
//
public Decimal(int value)
{
- // JIT today can't inline methods that contains "starg" opcode.
- // For more details, see DevDiv Bugs 81184: x86 JIT CQ: Removing the inline striction of "starg".
- int value_copy = value;
- if (value_copy >= 0)
+ if (value >= 0)
{
- uflags = 0;
+ flags = 0;
}
else
{
- uflags = SignMask;
- value_copy = -value_copy;
+ flags = SignMask;
+ value = -value;
}
- lo = value_copy;
+ lo = value;
mid = 0;
hi = 0;
}
@@ -157,30 +133,28 @@ namespace System
[CLSCompliant(false)]
public Decimal(uint value)
{
- uflags = 0;
- ulo = value;
- umid = 0;
- uhi = 0;
+ flags = 0;
+ lo = (int)value;
+ mid = 0;
+ hi = 0;
}
// Constructs a Decimal from a long value.
//
public Decimal(long value)
{
- // JIT today can't inline methods that contains "starg" opcode.
- // For more details, see DevDiv Bugs 81184: x86 JIT CQ: Removing the inline striction of "starg".
- long value_copy = value;
- if (value_copy >= 0)
+ if (value >= 0)
{
- uflags = 0;
+ flags = 0;
}
else
{
- uflags = SignMask;
- value_copy = -value_copy;
+ flags = SignMask;
+ value = -value;
}
- Low64 = (ulong)value_copy;
- uhi = 0;
+ lo = (int)value;
+ mid = (int)(value >> 32);
+ hi = 0;
}
// Constructs a Decimal from an unsigned long value.
@@ -188,23 +162,24 @@ namespace System
[CLSCompliant(false)]
public Decimal(ulong value)
{
- uflags = 0;
- Low64 = value;
- uhi = 0;
+ flags = 0;
+ lo = (int)value;
+ mid = (int)(value >> 32);
+ hi = 0;
}
// Constructs a Decimal from a float value.
//
public Decimal(float value)
{
- DecCalc.VarDecFromR4(value, out this);
+ DecCalc.VarDecFromR4(value, out AsMutable(ref this));
}
// Constructs a Decimal from a double value.
//
public Decimal(double value)
{
- DecCalc.VarDecFromR8(value, out this);
+ DecCalc.VarDecFromR8(value, out AsMutable(ref this));
}
//
@@ -213,15 +188,13 @@ namespace System
// A Currency represents a positive or negative decimal value with 4 digits past the decimal point. The actual Int64 representation used by these methods
// is the currency value multiplied by 10,000. For example, a currency value of $12.99 would be represented by the Int64 value 129,900.
//
-
- public static Decimal FromOACurrency(long cy)
+ public static decimal FromOACurrency(long cy)
{
- Decimal d = default(Decimal);
-
ulong absoluteCy; // has to be ulong to accommodate the case where cy == long.MinValue.
+ bool isNegative = false;
if (cy < 0)
{
- d.IsNegative = true;
+ isNegative = true;
absoluteCy = (ulong)(-cy);
}
else
@@ -232,7 +205,7 @@ namespace System
// In most cases, FromOACurrency() produces a Decimal with Scale set to 4. Unless, that is, some of the trailing digits past the decimal point are zero,
// in which case, for compatibility with .Net, we reduce the Scale by the number of zeros. While the result is still numerically equivalent, the scale does
// affect the ToString() value. In particular, it prevents a converted currency value of $12.95 from printing uglily as "12.9500".
- int scale = CurrencyScale;
+ int scale = 4;
if (absoluteCy != 0) // For compatibility, a currency of 0 emits the Decimal "0.0000" (scale set to 4).
{
while (scale != 0 && ((absoluteCy % 10) == 0))
@@ -242,18 +215,15 @@ namespace System
}
}
- // No need to set d.Hi32 - a currency will never go high enough for it to be anything other than zero.
- d.Low64 = absoluteCy;
- d.Scale = scale;
- return d;
+ return new decimal((int)absoluteCy, (int)(absoluteCy >> 32), 0, isNegative, (byte)scale);
}
- public static long ToOACurrency(Decimal value)
+ public static long ToOACurrency(decimal value)
{
- return DecCalc.VarCyFromDec(ref value);
+ return DecCalc.VarCyFromDec(ref AsMutable(ref value));
}
- private static bool IsValid(uint flags) => (flags & ~(SignMask | ScaleMask)) == 0 && ((flags & ScaleMask) <= (28 << 16));
+ private static bool IsValid(int flags) => (flags & ~(SignMask | ScaleMask)) == 0 && ((uint)(flags & ScaleMask) <= (28 << ScaleShift));
// Constructs a Decimal from an integer array containing a binary
// representation. The bits argument must be a non-null integer
@@ -280,13 +250,13 @@ namespace System
throw new ArgumentNullException(nameof(bits));
if (bits.Length == 4)
{
- uint f = (uint)bits[3];
+ int f = bits[3];
if (IsValid(f))
{
lo = bits[0];
mid = bits[1];
hi = bits[2];
- uflags = f;
+ flags = f;
return;
}
}
@@ -302,62 +272,73 @@ namespace System
this.lo = lo;
this.mid = mid;
this.hi = hi;
- uflags = ((uint)scale) << 16;
+ flags = ((int)scale) << 16;
if (isNegative)
- uflags |= SignMask;
+ flags |= SignMask;
}
- void IDeserializationCallback.OnDeserialization(Object sender)
+ void IDeserializationCallback.OnDeserialization(object sender)
{
// OnDeserialization is called after each instance of this class is deserialized.
// This callback method performs decimal validation after being deserialized.
- if (!IsValid(uflags))
+ if (!IsValid(flags))
throw new SerializationException(SR.Overflow_Decimal);
}
// Constructs a Decimal from its constituent parts.
- private Decimal(ulong ulomidLE, uint hi, uint flags)
+ private Decimal(int lo, int mid, int hi, int flags)
{
- this.ulomidLE = ulomidLE;
- this.uhi = hi;
- this.uflags = flags;
+ if (IsValid(flags))
+ {
+ this.lo = lo;
+ this.mid = mid;
+ this.hi = hi;
+ this.flags = flags;
+ return;
+ }
+ throw new ArgumentException(SR.Arg_DecBitCtor);
+ }
+
+ private Decimal(in decimal d, int flags)
+ {
+ this = d;
+ this.flags = flags;
}
// Returns the absolute value of the given Decimal. If d is
// positive, the result is d. If d is negative, the result
// is -d.
//
- internal static Decimal Abs(ref Decimal d)
+ internal static decimal Abs(ref decimal d)
{
- return new Decimal(d.ulomidLE, d.uhi, d.uflags & ~SignMask);
+ return new decimal(in d, d.flags & ~SignMask);
}
-
// Adds two Decimal values.
//
- public static Decimal Add(Decimal d1, Decimal d2)
+ public static decimal Add(decimal d1, decimal d2)
{
- DecCalc.VarDecAdd(ref d1, ref d2);
+ DecCalc.DecAddSub(ref AsMutable(ref d1), ref AsMutable(ref d2), false);
return d1;
}
// Rounds a Decimal to an integer value. The Decimal argument is rounded
// towards positive infinity.
- public static Decimal Ceiling(Decimal d)
+ public static decimal Ceiling(decimal d)
{
- uint flags = d.uflags;
+ int flags = d.flags;
if ((flags & ScaleMask) != 0)
- DecCalc.InternalRound(ref d, (byte)(flags >> ScaleShift), DecCalc.RoundingMode.Ceiling);
+ DecCalc.InternalRound(ref AsMutable(ref d), (byte)(flags >> ScaleShift), DecCalc.RoundingMode.Ceiling);
return d;
}
// Compares two Decimal values, returning an integer that indicates their
// relationship.
//
- public static int Compare(Decimal d1, Decimal d2)
+ public static int Compare(decimal d1, decimal d2)
{
- return DecCalc.VarDecCmp(ref d1, ref d2);
+ return DecCalc.VarDecCmp(in d1, in d2);
}
// Compares this object to another object, returning an integer that
@@ -366,27 +347,27 @@ namespace System
// null is considered to be less than any instance.
// If object is not of type Decimal, this method throws an ArgumentException.
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
return 1;
- if (!(value is Decimal))
+ if (!(value is decimal))
throw new ArgumentException(SR.Arg_MustBeDecimal);
- Decimal other = (Decimal)value;
- return DecCalc.VarDecCmp(ref this, ref other);
+ decimal other = (decimal)value;
+ return DecCalc.VarDecCmp(in this, in other);
}
- public int CompareTo(Decimal value)
+ public int CompareTo(decimal value)
{
- return DecCalc.VarDecCmp(ref this, ref value);
+ return DecCalc.VarDecCmp(in this, in value);
}
// Divides two Decimal values.
//
- public static Decimal Divide(Decimal d1, Decimal d2)
+ public static decimal Divide(decimal d1, decimal d2)
{
- DecCalc.VarDecDiv(ref d1, ref d2);
+ DecCalc.VarDecDiv(ref AsMutable(ref d1), ref AsMutable(ref d2));
return d1;
}
@@ -394,59 +375,41 @@ namespace System
// if the given object is a boxed Decimal and its value is equal to the
// value of this Decimal. Returns false otherwise.
//
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
- if (value is Decimal)
+ if (value is decimal)
{
- Decimal other = (Decimal)value;
- return DecCalc.VarDecCmp(ref this, ref other) == 0;
+ decimal other = (decimal)value;
+ return DecCalc.VarDecCmp(in this, in other) == 0;
}
return false;
}
- public bool Equals(Decimal value)
+ public bool Equals(decimal value)
{
- return DecCalc.VarDecCmp(ref this, ref value) == 0;
+ return DecCalc.VarDecCmp(in this, in value) == 0;
}
// Returns the hash code for this Decimal.
//
- public unsafe override int GetHashCode()
- {
- double dbl = DecCalc.VarR8FromDec(ref this);
- if (dbl == 0.0)
- // Ensure 0 and -0 have the same hash code
- return 0;
-
- // conversion to double is lossy and produces rounding errors so we mask off the lowest 4 bits
- //
- // For example these two numerically equal decimals with different internal representations produce
- // slightly different results when converted to double:
- //
- // decimal a = new decimal(new int[] { 0x76969696, 0x2fdd49fa, 0x409783ff, 0x00160000 });
- // => (decimal)1999021.176470588235294117647000000000 => (double)1999021.176470588
- // decimal b = new decimal(new int[] { 0x3f0f0f0f, 0x1e62edcc, 0x06758d33, 0x00150000 });
- // => (decimal)1999021.176470588235294117647000000000 => (double)1999021.1764705882
- //
- return (int)(((((uint*)&dbl)[0]) & 0xFFFFFFF0) ^ ((uint*)&dbl)[1]);
- }
+ public override int GetHashCode() => DecCalc.GetHashCode(in this);
// Compares two Decimal values for equality. Returns true if the two
// Decimal values are equal, or false if they are not equal.
//
- public static bool Equals(Decimal d1, Decimal d2)
+ public static bool Equals(decimal d1, decimal d2)
{
- return DecCalc.VarDecCmp(ref d1, ref d2) == 0;
+ return DecCalc.VarDecCmp(in d1, in d2) == 0;
}
// Rounds a Decimal to an integer value. The Decimal argument is rounded
// towards negative infinity.
//
- public static Decimal Floor(Decimal d)
+ public static decimal Floor(decimal d)
{
- uint flags = d.uflags;
+ int flags = d.flags;
if ((flags & ScaleMask) != 0)
- DecCalc.InternalRound(ref d, (byte)(flags >> ScaleShift), DecCalc.RoundingMode.Floor);
+ DecCalc.InternalRound(ref AsMutable(ref d), (byte)(flags >> ScaleShift), DecCalc.RoundingMode.Floor);
return d;
}
@@ -455,22 +418,22 @@ namespace System
// optionally followed by a decimal point (".") and another sequence of
// digits.
//
- public override String ToString()
+ public override string ToString()
{
return Number.FormatDecimal(this, null, NumberFormatInfo.CurrentInfo);
}
- public String ToString(String format)
+ public string ToString(string format)
{
return Number.FormatDecimal(this, format, NumberFormatInfo.CurrentInfo);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return Number.FormatDecimal(this, null, NumberFormatInfo.GetInstance(provider));
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
return Number.FormatDecimal(this, format, NumberFormatInfo.GetInstance(provider));
}
@@ -480,7 +443,6 @@ namespace System
return Number.TryFormatDecimal(this, format, NumberFormatInfo.GetInstance(provider), destination, out charsWritten);
}
-
// Converts a string to a Decimal. The string must consist of an optional
// minus sign ("-") followed by a sequence of digits ("0" - "9"). The
// sequence of digits may optionally contain a single decimal point (".")
@@ -488,58 +450,39 @@ namespace System
// Parse also allows a currency symbol, a trailing negative sign, and
// parentheses in the number.
//
- public static Decimal Parse(String s)
+ public static decimal Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseDecimal(s, NumberStyles.Number, NumberFormatInfo.CurrentInfo);
}
- internal const NumberStyles InvalidNumberStyles = ~(NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite
- | NumberStyles.AllowLeadingSign | NumberStyles.AllowTrailingSign
- | NumberStyles.AllowParentheses | NumberStyles.AllowDecimalPoint
- | NumberStyles.AllowThousands | NumberStyles.AllowExponent
- | NumberStyles.AllowCurrencySymbol | NumberStyles.AllowHexSpecifier);
-
- internal static void ValidateParseStyleFloatingPoint(NumberStyles style)
- {
- // Check for undefined flags
- if ((style & InvalidNumberStyles) != 0)
- {
- throw new ArgumentException(SR.Argument_InvalidNumberStyles, nameof(style));
- }
- if ((style & NumberStyles.AllowHexSpecifier) != 0)
- { // Check for hex number
- throw new ArgumentException(SR.Arg_HexStyleNotSupported);
- }
- }
-
- public static Decimal Parse(String s, NumberStyles style)
+ public static decimal Parse(string s, NumberStyles style)
{
- ValidateParseStyleFloatingPoint(style);
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseDecimal(s, style, NumberFormatInfo.CurrentInfo);
}
- public static Decimal Parse(String s, IFormatProvider provider)
+ public static decimal Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseDecimal(s, NumberStyles.Number, NumberFormatInfo.GetInstance(provider));
}
- public static Decimal Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static decimal Parse(string s, NumberStyles style, IFormatProvider provider)
{
- ValidateParseStyleFloatingPoint(style);
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseDecimal(s, style, NumberFormatInfo.GetInstance(provider));
}
- public static Decimal Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ public static decimal Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Number, IFormatProvider provider = null)
{
- ValidateParseStyleFloatingPoint(style);
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
return Number.ParseDecimal(s, style, NumberFormatInfo.GetInstance(provider));
}
- public static Boolean TryParse(String s, out Decimal result)
+ public static bool TryParse(string s, out decimal result)
{
if (s == null)
{
@@ -555,20 +498,22 @@ namespace System
return Number.TryParseDecimal(s, NumberStyles.Number, NumberFormatInfo.CurrentInfo, out result);
}
- public static Boolean TryParse(String s, NumberStyles style, IFormatProvider provider, out Decimal result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out decimal result)
{
- ValidateParseStyleFloatingPoint(style);
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+
if (s == null)
{
result = 0;
return false;
}
+
return Number.TryParseDecimal(s, style, NumberFormatInfo.GetInstance(provider), out result);
}
public static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, IFormatProvider provider, out decimal result)
{
- ValidateParseStyleFloatingPoint(style);
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
return Number.TryParseDecimal(s, style, NumberFormatInfo.GetInstance(provider), out result);
}
@@ -582,12 +527,12 @@ namespace System
// indicates the sign of the Decimal value, 0 meaning positive and 1
// meaning negative.
//
- public static int[] GetBits(Decimal d)
+ public static int[] GetBits(decimal d)
{
return new int[] { d.lo, d.mid, d.hi, d.flags };
}
- internal static void GetBytes(Decimal d, byte[] buffer)
+ internal static void GetBytes(decimal d, byte[] buffer)
{
Debug.Assert((buffer != null && buffer.Length >= 16), "[GetBytes]buffer != null && buffer.Length >= 16");
buffer[0] = (byte)d.lo;
@@ -611,40 +556,50 @@ namespace System
buffer[15] = (byte)(d.flags >> 24);
}
+ internal static decimal ToDecimal(byte[] buffer)
+ {
+ Debug.Assert((buffer != null && buffer.Length >= 16), "[ToDecimal]buffer != null && buffer.Length >= 16");
+ int lo = ((int)buffer[0]) | ((int)buffer[1] << 8) | ((int)buffer[2] << 16) | ((int)buffer[3] << 24);
+ int mid = ((int)buffer[4]) | ((int)buffer[5] << 8) | ((int)buffer[6] << 16) | ((int)buffer[7] << 24);
+ int hi = ((int)buffer[8]) | ((int)buffer[9] << 8) | ((int)buffer[10] << 16) | ((int)buffer[11] << 24);
+ int flags = ((int)buffer[12]) | ((int)buffer[13] << 8) | ((int)buffer[14] << 16) | ((int)buffer[15] << 24);
+ return new decimal(lo, mid, hi, flags);
+ }
+
// Returns the larger of two Decimal values.
//
- internal static ref Decimal Max(ref Decimal d1, ref Decimal d2)
+ internal static ref decimal Max(ref decimal d1, ref decimal d2)
{
- return ref DecCalc.VarDecCmp(ref d1, ref d2) >= 0 ? ref d1 : ref d2;
+ return ref DecCalc.VarDecCmp(in d1, in d2) >= 0 ? ref d1 : ref d2;
}
// Returns the smaller of two Decimal values.
//
- internal static ref Decimal Min(ref Decimal d1, ref Decimal d2)
+ internal static ref decimal Min(ref decimal d1, ref decimal d2)
{
- return ref DecCalc.VarDecCmp(ref d1, ref d2) < 0 ? ref d1 : ref d2;
+ return ref DecCalc.VarDecCmp(in d1, in d2) < 0 ? ref d1 : ref d2;
}
-
- public static Decimal Remainder(Decimal d1, Decimal d2)
+ public static decimal Remainder(decimal d1, decimal d2)
{
- return DecCalc.VarDecMod(ref d1, ref d2);
+ DecCalc.VarDecMod(ref AsMutable(ref d1), ref AsMutable(ref d2));
+ return d1;
}
// Multiplies two Decimal values.
//
- public static Decimal Multiply(Decimal d1, Decimal d2)
+ public static decimal Multiply(decimal d1, decimal d2)
{
- DecCalc.VarDecMul(ref d1, ref d2);
+ DecCalc.VarDecMul(ref AsMutable(ref d1), ref AsMutable(ref d2));
return d1;
}
// Returns the negated value of the given Decimal. If d is non-zero,
// the result is -d. If d is zero, the result is zero.
//
- public static Decimal Negate(Decimal d)
+ public static decimal Negate(decimal d)
{
- return new Decimal(d.ulomidLE, d.uhi, d.uflags ^ SignMask);
+ return new decimal(in d, d.flags ^ SignMask);
}
// Rounds a Decimal value to a given number of decimal places. The value
@@ -655,12 +610,12 @@ namespace System
// By default a mid-point value is rounded to the nearest even number. If the mode is
// passed in, it can also round away from zero.
- public static Decimal Round(Decimal d) => Round(ref d, 0, MidpointRounding.ToEven);
- public static Decimal Round(Decimal d, int decimals) => Round(ref d, decimals, MidpointRounding.ToEven);
- public static Decimal Round(Decimal d, MidpointRounding mode) => Round(ref d, 0, mode);
- public static Decimal Round(Decimal d, int decimals, MidpointRounding mode) => Round(ref d, decimals, mode);
+ public static decimal Round(decimal d) => Round(ref d, 0, MidpointRounding.ToEven);
+ public static decimal Round(decimal d, int decimals) => Round(ref d, decimals, MidpointRounding.ToEven);
+ public static decimal Round(decimal d, MidpointRounding mode) => Round(ref d, 0, mode);
+ public static decimal Round(decimal d, int decimals, MidpointRounding mode) => Round(ref d, decimals, mode);
- private static Decimal Round(ref Decimal d, int decimals, MidpointRounding mode)
+ private static decimal Round(ref decimal d, int decimals, MidpointRounding mode)
{
if ((uint)decimals > 28)
throw new ArgumentOutOfRangeException(nameof(decimals), SR.ArgumentOutOfRange_DecimalRound);
@@ -669,7 +624,7 @@ namespace System
int scale = d.Scale - decimals;
if (scale > 0)
- DecCalc.InternalRound(ref d, (uint)scale, (DecCalc.RoundingMode)mode);
+ DecCalc.InternalRound(ref AsMutable(ref d), (uint)scale, (DecCalc.RoundingMode)mode);
return d;
}
@@ -677,9 +632,9 @@ namespace System
// Subtracts two Decimal values.
//
- public static Decimal Subtract(Decimal d1, Decimal d2)
+ public static decimal Subtract(decimal d1, decimal d2)
{
- DecCalc.VarDecSub(ref d1, ref d2);
+ DecCalc.DecAddSub(ref AsMutable(ref d1), ref AsMutable(ref d2), true);
return d1;
}
@@ -687,7 +642,7 @@ namespace System
// towards zero to the nearest integer value, and the result of this
// operation is returned as a byte.
//
- public static byte ToByte(Decimal value)
+ public static byte ToByte(decimal value)
{
uint temp;
try
@@ -707,7 +662,7 @@ namespace System
// operation is returned as a byte.
//
[CLSCompliant(false)]
- public static sbyte ToSByte(Decimal value)
+ public static sbyte ToSByte(decimal value)
{
int temp;
try
@@ -726,7 +681,7 @@ namespace System
// rounded towards zero to the nearest integer value, and the result of
// this operation is returned as a short.
//
- public static short ToInt16(Decimal value)
+ public static short ToInt16(decimal value)
{
int temp;
try
@@ -744,7 +699,7 @@ namespace System
// Converts a Decimal to a double. Since a double has fewer significant
// digits than a Decimal, this operation may produce round-off errors.
//
- public static double ToDouble(Decimal d)
+ public static double ToDouble(decimal d)
{
return DecCalc.VarR8FromDec(ref d);
}
@@ -753,7 +708,7 @@ namespace System
// zero to the nearest integer value, and the result of this operation is
// returned as an integer.
//
- public static int ToInt32(Decimal d)
+ public static int ToInt32(decimal d)
{
Truncate(ref d);
if ((d.hi | d.mid) == 0)
@@ -776,10 +731,10 @@ namespace System
// to the nearest integer value, and the result of this operation is
// returned as a long.
//
- public static long ToInt64(Decimal d)
+ public static long ToInt64(decimal d)
{
Truncate(ref d);
- if (d.uhi == 0)
+ if (d.hi == 0)
{
long l = (long)d.Low64;
if (!d.IsNegative)
@@ -800,7 +755,7 @@ namespace System
// result of this operation is returned as an ushort.
//
[CLSCompliant(false)]
- public static ushort ToUInt16(Decimal value)
+ public static ushort ToUInt16(decimal value)
{
uint temp;
try
@@ -820,12 +775,12 @@ namespace System
// result of this operation is returned as an unsigned integer.
//
[CLSCompliant(false)]
- public static uint ToUInt32(Decimal d)
+ public static uint ToUInt32(decimal d)
{
Truncate(ref d);
- if ((d.uhi | d.umid) == 0)
+ if ((d.hi | d.mid) == 0)
{
- uint i = d.ulo;
+ uint i = d.Low;
if (!d.IsNegative || i == 0)
return i;
}
@@ -837,10 +792,10 @@ namespace System
// result of this operation is returned as a long.
//
[CLSCompliant(false)]
- public static ulong ToUInt64(Decimal d)
+ public static ulong ToUInt64(decimal d)
{
Truncate(ref d);
- if (d.uhi == 0)
+ if (d.hi == 0)
{
ulong l = d.Low64;
if (!d.IsNegative || l == 0)
@@ -852,7 +807,7 @@ namespace System
// Converts a Decimal to a float. Since a float has fewer significant
// digits than a Decimal, this operation may produce round-off errors.
//
- public static float ToSingle(Decimal d)
+ public static float ToSingle(decimal d)
{
return DecCalc.VarR4FromDec(ref d);
}
@@ -861,94 +816,94 @@ namespace System
// towards zero to the nearest integer value, corresponding to removing all
// digits after the decimal point.
//
- public static Decimal Truncate(Decimal d)
+ public static decimal Truncate(decimal d)
{
Truncate(ref d);
return d;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static void Truncate(ref Decimal d)
+ private static void Truncate(ref decimal d)
{
- uint flags = d.uflags;
+ int flags = d.flags;
if ((flags & ScaleMask) != 0)
- DecCalc.InternalRound(ref d, (byte)(flags >> ScaleShift), DecCalc.RoundingMode.Truncate);
+ DecCalc.InternalRound(ref AsMutable(ref d), (byte)(flags >> ScaleShift), DecCalc.RoundingMode.Truncate);
}
- public static implicit operator Decimal(byte value)
+ public static implicit operator decimal(byte value)
{
- return new Decimal(value);
+ return new decimal(value);
}
[CLSCompliant(false)]
- public static implicit operator Decimal(sbyte value)
+ public static implicit operator decimal(sbyte value)
{
- return new Decimal(value);
+ return new decimal(value);
}
- public static implicit operator Decimal(short value)
+ public static implicit operator decimal(short value)
{
- return new Decimal(value);
+ return new decimal(value);
}
[CLSCompliant(false)]
- public static implicit operator Decimal(ushort value)
+ public static implicit operator decimal(ushort value)
{
- return new Decimal(value);
+ return new decimal(value);
}
- public static implicit operator Decimal(char value)
+ public static implicit operator decimal(char value)
{
- return new Decimal(value);
+ return new decimal(value);
}
- public static implicit operator Decimal(int value)
+ public static implicit operator decimal(int value)
{
- return new Decimal(value);
+ return new decimal(value);
}
[CLSCompliant(false)]
- public static implicit operator Decimal(uint value)
+ public static implicit operator decimal(uint value)
{
- return new Decimal(value);
+ return new decimal(value);
}
- public static implicit operator Decimal(long value)
+ public static implicit operator decimal(long value)
{
- return new Decimal(value);
+ return new decimal(value);
}
[CLSCompliant(false)]
- public static implicit operator Decimal(ulong value)
+ public static implicit operator decimal(ulong value)
{
- return new Decimal(value);
+ return new decimal(value);
}
- public static explicit operator Decimal(float value)
+ public static explicit operator decimal(float value)
{
- return new Decimal(value);
+ return new decimal(value);
}
- public static explicit operator Decimal(double value)
+ public static explicit operator decimal(double value)
{
- return new Decimal(value);
+ return new decimal(value);
}
- public static explicit operator byte(Decimal value)
+ public static explicit operator byte(decimal value)
{
return ToByte(value);
}
[CLSCompliant(false)]
- public static explicit operator sbyte(Decimal value)
+ public static explicit operator sbyte(decimal value)
{
return ToSByte(value);
}
- public static explicit operator char(Decimal value)
+ public static explicit operator char(decimal value)
{
- UInt16 temp;
+ ushort temp;
try
{
temp = ToUInt16(value);
@@ -960,122 +915,122 @@ namespace System
return (char)temp;
}
- public static explicit operator short(Decimal value)
+ public static explicit operator short(decimal value)
{
return ToInt16(value);
}
[CLSCompliant(false)]
- public static explicit operator ushort(Decimal value)
+ public static explicit operator ushort(decimal value)
{
return ToUInt16(value);
}
- public static explicit operator int(Decimal value)
+ public static explicit operator int(decimal value)
{
return ToInt32(value);
}
[CLSCompliant(false)]
- public static explicit operator uint(Decimal value)
+ public static explicit operator uint(decimal value)
{
return ToUInt32(value);
}
- public static explicit operator long(Decimal value)
+ public static explicit operator long(decimal value)
{
return ToInt64(value);
}
[CLSCompliant(false)]
- public static explicit operator ulong(Decimal value)
+ public static explicit operator ulong(decimal value)
{
return ToUInt64(value);
}
- public static explicit operator float(Decimal value)
+ public static explicit operator float(decimal value)
{
return ToSingle(value);
}
- public static explicit operator double(Decimal value)
+ public static explicit operator double(decimal value)
{
return ToDouble(value);
}
- public static Decimal operator +(Decimal d)
+ public static decimal operator +(decimal d)
{
return d;
}
- public static Decimal operator -(Decimal d)
+ public static decimal operator -(decimal d)
{
return Negate(d);
}
- public static Decimal operator ++(Decimal d)
+ public static decimal operator ++(decimal d)
{
return Add(d, One);
}
- public static Decimal operator --(Decimal d)
+ public static decimal operator --(decimal d)
{
return Subtract(d, One);
}
- public static Decimal operator +(Decimal d1, Decimal d2)
+ public static decimal operator +(decimal d1, decimal d2)
{
return Add(d1, d2);
}
- public static Decimal operator -(Decimal d1, Decimal d2)
+ public static decimal operator -(decimal d1, decimal d2)
{
return Subtract(d1, d2);
}
- public static Decimal operator *(Decimal d1, Decimal d2)
+ public static decimal operator *(decimal d1, decimal d2)
{
return Multiply(d1, d2);
}
- public static Decimal operator /(Decimal d1, Decimal d2)
+ public static decimal operator /(decimal d1, decimal d2)
{
return Divide(d1, d2);
}
- public static Decimal operator %(Decimal d1, Decimal d2)
+ public static decimal operator %(decimal d1, decimal d2)
{
return Remainder(d1, d2);
}
- public static bool operator ==(Decimal d1, Decimal d2)
+ public static bool operator ==(decimal d1, decimal d2)
{
- return DecCalc.VarDecCmp(ref d1, ref d2) == 0;
+ return DecCalc.VarDecCmp(in d1, in d2) == 0;
}
- public static bool operator !=(Decimal d1, Decimal d2)
+ public static bool operator !=(decimal d1, decimal d2)
{
- return DecCalc.VarDecCmp(ref d1, ref d2) != 0;
+ return DecCalc.VarDecCmp(in d1, in d2) != 0;
}
- public static bool operator <(Decimal d1, Decimal d2)
+ public static bool operator <(decimal d1, decimal d2)
{
- return DecCalc.VarDecCmp(ref d1, ref d2) < 0;
+ return DecCalc.VarDecCmp(in d1, in d2) < 0;
}
- public static bool operator <=(Decimal d1, Decimal d2)
+ public static bool operator <=(decimal d1, decimal d2)
{
- return DecCalc.VarDecCmp(ref d1, ref d2) <= 0;
+ return DecCalc.VarDecCmp(in d1, in d2) <= 0;
}
- public static bool operator >(Decimal d1, Decimal d2)
+ public static bool operator >(decimal d1, decimal d2)
{
- return DecCalc.VarDecCmp(ref d1, ref d2) > 0;
+ return DecCalc.VarDecCmp(in d1, in d2) > 0;
}
- public static bool operator >=(Decimal d1, Decimal d2)
+ public static bool operator >=(decimal d1, decimal d2)
{
- return DecCalc.VarDecCmp(ref d1, ref d2) >= 0;
+ return DecCalc.VarDecCmp(in d1, in d2) >= 0;
}
//
@@ -1095,7 +1050,7 @@ namespace System
char IConvertible.ToChar(IFormatProvider provider)
{
- throw new InvalidCastException(String.Format(SR.InvalidCast_FromTo, "Decimal", "Char"));
+ throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Decimal", "Char"));
}
sbyte IConvertible.ToSByte(IFormatProvider provider)
@@ -1148,17 +1103,17 @@ namespace System
return Convert.ToDouble(this);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return this;
}
DateTime IConvertible.ToDateTime(IFormatProvider provider)
{
- throw new InvalidCastException(String.Format(SR.InvalidCast_FromTo, "Decimal", "DateTime"));
+ throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Decimal", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Debug.Unix.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Debug.Unix.cs
index 627ea4ab7..86b095e47 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Debug.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Debug.Unix.cs
@@ -22,11 +22,11 @@ namespace System.Diagnostics
// Fail in order to avoid anyone catching an exception and masking
// an assert failure.
DebugAssertException ex;
- if (message == String.Empty)
+ if (message == string.Empty)
{
ex = new DebugAssertException(stackTrace);
}
- else if (detailMessage == String.Empty)
+ else if (detailMessage == string.Empty)
{
ex = new DebugAssertException(message, stackTrace);
}
diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/StackFrame.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/StackFrame.cs
index fe06d85f2..22c9b8399 100644
--- a/src/System.Private.CoreLib/src/System/Diagnostics/StackFrame.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/StackFrame.cs
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-
using System.Text;
using System;
using System.IO;
@@ -35,7 +34,7 @@ namespace System.Diagnostics
/// <summary>
/// Source file name representing the current code location if available, null otherwise.
/// </summary>
- private String _fileName;
+ private string _fileName;
/// <summary>
/// Line number representing the current code location if available, 0 otherwise.
@@ -52,7 +51,7 @@ namespace System.Diagnostics
/// </summary>
private bool _isLastFrameFromForeignExceptionStackTrace;
- internal void InitMembers()
+ private void InitMembers()
{
_method = null;
_nativeOffset = OFFSET_UNKNOWN;
@@ -104,7 +103,7 @@ namespace System.Diagnostics
/// name and line number. Use when you don't want to use the
/// debugger's line mapping logic.
/// </summary>
- public StackFrame(String fileName, int lineNumber)
+ public StackFrame(string fileName, int lineNumber)
{
InitMembers();
BuildStackFrame(StackTrace.METHODS_TO_SKIP, false);
@@ -118,7 +117,7 @@ namespace System.Diagnostics
/// name, line number and column number. Use when you don't want to
/// use the debugger's line mapping logic.
/// </summary>
- public StackFrame(String fileName, int lineNumber, int colNumber)
+ public StackFrame(string fileName, int lineNumber, int colNumber)
{
InitMembers();
BuildStackFrame(StackTrace.METHODS_TO_SKIP, false);
@@ -147,7 +146,7 @@ namespace System.Diagnostics
_ilOffset = iOffset;
}
- internal virtual void SetFileName(String strFName)
+ internal virtual void SetFileName(string strFName)
{
_fileName = strFName;
}
@@ -205,7 +204,7 @@ namespace System.Diagnostics
/// information is normally extracted from the debugging symbols
/// for the executable.
/// </summary>
- public virtual String GetFileName()
+ public virtual string GetFileName()
{
return _fileName;
}
@@ -233,7 +232,7 @@ namespace System.Diagnostics
/// <summary>
/// Builds a readable representation of the stack frame
/// </summary>
- public override String ToString()
+ public override string ToString()
{
StringBuilder sb = new StringBuilder(255);
bool includeFileInfoIfAvailable;
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/ActivityTracker.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/ActivityTracker.cs
index 9ac32c3bd..d9f9f081c 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/ActivityTracker.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/ActivityTracker.cs
@@ -248,11 +248,6 @@ namespace System.Diagnostics.Tracing
#region private
/// <summary>
- /// The current activity ID. Use this to log normal events.
- /// </summary>
- private Guid CurrentActivityId { get { return m_current.Value.ActivityId; } }
-
- /// <summary>
/// Searched for a active (nonstopped) activity with the given name. Returns null if not found.
/// </summary>
private ActivityInfo FindActiveActivity(string name, ActivityInfo startLocation)
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventDescriptor.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventDescriptor.cs
index b036b28b4..0fed7b5c0 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventDescriptor.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventDescriptor.cs
@@ -168,6 +168,14 @@ namespace System.Diagnostics.Tracing
}
}
+ internal int TraceLoggingId
+ {
+ get
+ {
+ return m_traceloggingId;
+ }
+ }
+
public override bool Equals(object obj)
{
if (!(obj is EventDescriptor))
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventProvider.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventProvider.cs
index fafdd7c6d..36b363fa3 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventProvider.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventProvider.cs
@@ -30,6 +30,13 @@ namespace Microsoft.Diagnostics.Tracing
namespace System.Diagnostics.Tracing
#endif
{
+ internal enum EventProviderType
+ {
+ None = 0,
+ ETW,
+ EventPipe
+ };
+
// New in CLR4.0
internal enum ControllerCommand
{
@@ -120,15 +127,28 @@ namespace System.Diagnostics.Tracing
// it registers a callback from native code you MUST dispose it BEFORE shutdown, otherwise
// you may get native callbacks during shutdown when we have destroyed the delegate.
// EventSource has special logic to do this, no one else should be calling EventProvider.
- internal EventProvider()
+ internal EventProvider(EventProviderType providerType)
{
+ switch (providerType)
+ {
+ case EventProviderType.ETW:
#if PLATFORM_WINDOWS
- m_eventProvider = new EtwEventProvider();
-#elif FEATURE_PERFTRACING
- m_eventProvider = new EventPipeEventProvider();
+ m_eventProvider = new EtwEventProvider();
+#else
+ m_eventProvider = new NoOpEventProvider();
+#endif
+ break;
+ case EventProviderType.EventPipe:
+#if FEATURE_PERFTRACING
+ m_eventProvider = new EventPipeEventProvider();
#else
- m_eventProvider = new NoOpEventProvider();
+ m_eventProvider = new NoOpEventProvider();
#endif
+ break;
+ default:
+ m_eventProvider = new NoOpEventProvider();
+ break;
+ };
}
/// <summary>
@@ -331,7 +351,7 @@ namespace System.Diagnostics.Tracing
protected EventKeywords MatchAnyKeyword { get { return (EventKeywords)m_anyKeywordMask; } set { m_anyKeywordMask = unchecked((long)value); } }
protected EventKeywords MatchAllKeyword { get { return (EventKeywords)m_allKeywordMask; } set { m_allKeywordMask = unchecked((long)value); } }
- static private int FindNull(byte[] buffer, int idx)
+ private static int FindNull(byte[] buffer, int idx)
{
while (idx < buffer.Length && buffer[idx] != 0)
idx++;
@@ -475,7 +495,7 @@ namespace System.Diagnostics.Tracing
var structBase = (byte*)providerInstance;
providerInstance = (UnsafeNativeMethods.ManifestEtw.TRACE_PROVIDER_INSTANCE_INFO*)&structBase[providerInstance->NextOffset];
}
-#else
+#else
#if !ES_BUILD_PCL && PLATFORM_WINDOWS // TODO command arguments don't work on PCL builds...
// This code is only used in the Nuget Package Version of EventSource. because
// the code above is using APIs baned from UWP apps.
@@ -761,10 +781,10 @@ namespace System.Diagnostics.Tracing
*uintptr = (uint)data;
dataDescriptor->Ptr = (ulong)uintptr;
}
- else if (data is UInt64)
+ else if (data is ulong)
{
dataDescriptor->Size = (uint)sizeof(ulong);
- UInt64* ulongptr = (ulong*)dataBuffer;
+ ulong* ulongptr = (ulong*)dataBuffer;
*ulongptr = (ulong)data;
dataDescriptor->Ptr = (ulong)ulongptr;
}
@@ -863,25 +883,18 @@ namespace System.Diagnostics.Tracing
{
if (data is System.Enum)
{
- Type underlyingType = Enum.GetUnderlyingType(data.GetType());
- if (underlyingType == typeof(int))
- {
-#if !ES_BUILD_PCL
- data = ((IConvertible)data).ToInt32(null);
-#else
- data = (int)data;
-#endif
- goto Again;
- }
- else if (underlyingType == typeof(long))
+ try
{
-#if !ES_BUILD_PCL
- data = ((IConvertible)data).ToInt64(null);
-#else
- data = (long)data;
-#endif
+ Type underlyingType = Enum.GetUnderlyingType(data.GetType());
+ if (underlyingType == typeof(ulong))
+ data = (ulong)data;
+ else if (underlyingType == typeof(long))
+ data = (long)data;
+ else
+ data = (int)Convert.ToInt64(data); // This handles all int/uint or below (we treat them like 32 bit ints)
goto Again;
}
+ catch { } // On wierd cases (e.g. enums of type double), give up and for compat simply tostring.
}
// To our eyes, everything else is a just a string
@@ -959,7 +972,7 @@ namespace System.Diagnostics.Tracing
List<object> dataRefObj = new List<object>(s_etwAPIMaxRefObjCount);
EventData* userData = stackalloc EventData[2 * argCount];
for (int i = 0; i < 2 * argCount; i++)
- userData[i] = default(EventData);
+ userData[i] = default;
EventData* userDataPtr = (EventData*)userData;
byte* dataBuffer = stackalloc byte[s_basicTypeAllocationBufferSize * 2 * argCount]; // Assume 16 chars for non-string argument
byte* currentBuffer = dataBuffer;
@@ -1133,7 +1146,7 @@ namespace System.Diagnostics.Tracing
// <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.ManifestEtw.EventWrite(System.Int64,EventDescriptor&,System.UInt32,System.Void*):System.UInt32" />
// </SecurityKernel>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
- internal unsafe protected bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityID, Guid* childActivityID, int dataCount, IntPtr data)
+ internal protected unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, IntPtr eventHandle, Guid* activityID, Guid* childActivityID, int dataCount, IntPtr data)
{
if (childActivityID != null)
{
@@ -1157,6 +1170,7 @@ namespace System.Diagnostics.Tracing
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
internal unsafe bool WriteEventRaw(
ref EventDescriptor eventDescriptor,
+ IntPtr eventHandle,
Guid* activityID,
Guid* relatedActivityID,
int dataCount,
@@ -1167,7 +1181,7 @@ namespace System.Diagnostics.Tracing
status = m_eventProvider.EventWriteTransferWrapper(
m_regHandle,
ref eventDescriptor,
- IntPtr.Zero,
+ eventHandle,
activityID,
relatedActivityID,
dataCount,
@@ -1269,14 +1283,13 @@ namespace System.Diagnostics.Tracing
}
// Define an EventPipeEvent handle.
- unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, Int64 keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength)
+ unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, long keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength)
{
throw new System.NotSupportedException();
}
}
-#elif !FEATURE_PERFTRACING
-
+#endif
internal sealed class NoOpEventProvider : IEventProvider
{
unsafe uint IEventProvider.EventRegister(
@@ -1311,12 +1324,10 @@ namespace System.Diagnostics.Tracing
}
// Define an EventPipeEvent handle.
- unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, Int64 keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength)
+ unsafe IntPtr IEventProvider.DefineEventHandle(uint eventID, string eventName, long keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength)
{
- throw new System.NotSupportedException();
+ return IntPtr.Zero;
}
}
-
-#endif
}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSource.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSource.cs
index 40d39ced7..b309eb5aa 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSource.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSource.cs
@@ -18,12 +18,12 @@
//
// PRINCIPLE: EventSource - ETW decoupling
//
-// Conceptually and EventSouce is something takes event logging data from the source methods
-// To the EventListener that can subscribe them. Note that CONCEPTUALLY EVENTSOURCES DON'T
-// KNOW ABOUT ETW!. The MODEL of the system is that there is a special EventListener Which
+// Conceptually an EventSouce is something that takes event logging data from the source methods
+// to the EventListener that can subscribe to them. Note that CONCEPTUALLY EVENTSOURCES DON'T
+// KNOW ABOUT ETW!. The MODEL of the system is that there is a special EventListener which
// we will call the EtwEventListener, that forwards commands from ETW to EventSources and
-// listeners to the EventSources and forwards on those events to ETW. THus the model should
-// be that you DON'T NEED ETW.
+// listens to EventSources and forwards on those events to ETW. Thus the model should
+// be that you DON'T NEED ETW.
//
// Now in actual practice, EventSouce have rather intimate knowledge of ETW and send events
// to it directly, but this can be VIEWED AS AN OPTIMIZATION.
@@ -33,20 +33,20 @@
// There are two ways for event Data to enter the system
// 1) WriteEvent* and friends. This is called the 'contract' based approach because
// you write a method per event which forms a contract that is know at compile time.
-// In this scheme each event is given an EVENTID (small integer). which is its identity
+// In this scheme each event is given an EVENTID (small integer), which is its identity
// 2) Write<T> methods. This is called the 'dynamic' approach because new events
// can be created on the fly. Event identity is determined by the event NAME, and these
// are not quite as efficient at runtime since you have at least a hash table lookup
// on every event write.
//
-// EventSource-EventListener transfer fully support both ways of writing events (either contract
-// based (WriteEvent*) or dynamic (Write<T>). Both way fully support the same set of data
-// types. It is suggested, however, that you use the contract based approach when the event scheme
+// EventSource-EventListener transfer fully supports both ways of writing events (either contract
+// based (WriteEvent*) or dynamic (Write<T>)). Both ways fully support the same set of data
+// types. It is recommended, however, that you use the contract based approach when the event scheme
// is known at compile time (that is whenever possible). It is more efficient, but more importantly
// it makes the contract very explicit, and centralizes all policy about logging. These are good
-// things. The Write<T> API is really meant for more ad-hoc
+// things. The Write<T> API is really meant for more ad-hoc cases.
//
-// Allowed Data.
+// Allowed Data:
//
// Note that EventSource-EventListeners have a conceptual serialization-deserialization that happens
// during the transfer. In particular object identity is not preserved, some objects are morphed,
@@ -57,7 +57,7 @@
// * IEnumerable<T> of valid types T (this include arrays) (* New for V4.6)
// * Explicitly Opted in class or struct with public property Getters over Valid types. (* New for V4.6)
//
-// This set of types is roughly a generalization of JSON support (Basically primitives, bags, and arrays).
+// This set of types is roughly a generalization of JSON support (basically primitives, bags, and arrays).
//
// Explicitly allowed structs include (* New for V4.6)
// * Marked with the EventData attribute
@@ -67,27 +67,27 @@
// When classes are returned in an EventListener, what is returned is something that implements
// IDictionary<string, T>. Thus when objects are passed to an EventSource they are transformed
// into a key-value bag (the IDictionary<string, T>) for consumption in the listener. These
-// are obvious NOT the original objects.
+// are obviously NOT the original objects.
//
-// ETWserialization formats:
+// ETW serialization formats:
//
-// As mentioned conceptually EventSource's send data to EventListeners and there is a conceptual
+// As mentioned, conceptually EventSources send data to EventListeners and there is a conceptual
// copy/morph of that data as described above. In addition the .NET framework supports a conceptual
-// ETWListener that will send the data to then ETW stream. If you use this feature, the data needs
+// ETWListener that will send the data to the ETW stream. If you use this feature, the data needs
// to be serialized in a way that ETW supports. ETW supports the following serialization formats
//
// 1) Manifest Based serialization.
// 2) SelfDescribing serialization (TraceLogging style in the TraceLogging directory)
//
-// A key factor is that the Write<T> method, which support on the fly definition of events, can't
+// A key factor is that the Write<T> method, which supports on the fly definition of events, can't
// support the manifest based serialization because the manifest needs the schema of all events
-// to be known before any events are emitted. This implies the following
+// to be known before any events are emitted. This implies the following:
//
// If you use Write<T> and the output goes to ETW it will use the SelfDescribing format.
// If you use the EventSource(string) constructor for an eventSource (in which you don't
// create a subclass), the default is also to use Self-Describing serialization. In addition
// you can use the EventSoruce(EventSourceSettings) constructor to also explicitly specify
-// Self-Describing serialization format. These effect the WriteEvent* APIs going to ETW.
+// Self-Describing serialization format. These affect the WriteEvent* APIs going to ETW.
//
// Note that none of this ETW serialization logic affects EventListeners. Only the ETW listener.
//
@@ -111,13 +111,13 @@
//
// On output there are the following routines
// Writing to all listeners that are NOT ETW, we have the following routines
-// * WriteToAllListeners(ID, Guid*, COUNT, EventData*)
-// * WriteToAllListeners(ID, Guid*, object[])
-// * WriteToAllListeners(NAME, Guid*, EventPayload)
+// * WriteToAllListeners(ID, Guid*, Guid*, COUNT, EventData*)
+// * WriteToAllListeners(ID, Guid*, Guid*, object[])
+// * WriteToAllListeners(NAME, Guid*, Guid*, EventPayload)
//
// EventPayload is the internal type that implements the IDictionary<string, object> interface
// The EventListeners will pass back for serialized classes for nested object, but
-// WriteToAllListeners(NAME, Guid*, EventPayload) unpacks this uses the fields as if they
+// WriteToAllListeners(NAME, Guid*, Guid*, EventPayload) unpacks this and uses the fields as if they
// were parameters to a method.
//
// The first two are used for the WriteEvent* case, and the later is used for the Write<T> case.
@@ -129,7 +129,7 @@
// WriteMultiMerge(NAME, Options, Types, EventData*)
// WriteMultiMerge(NAME, Options, Types, object[])
// WriteImpl<T> has logic that knows how to serialize (like WriteMultiMerge) but also knows
-// will write it to
+// where it will write it to
//
// All ETW writes eventually call
// EventWriteTransfer (native PINVOKE wrapper)
@@ -146,7 +146,7 @@
// since it is the TraceLoggingTypeInfo structure that knows how to do this. Effectively for a type you
// can call one of these
// WriteMetadata - transforms the type T into serialization meta data blob for that type
-// WriteObjectData - transforms an object of T into serialization meta data blob for that type
+// WriteObjectData - transforms an object of T into serialization data blob for that instance
// GetData - transforms an object of T into its deserialized form suitable for passing to EventListener.
// The first two are used to serialize something for ETW. The second one is used to transform the object
// for use by the EventListener. We also have a 'DecodeObject' method that will take a EventData* and
@@ -181,6 +181,7 @@ using System.Security.Permissions;
using System.Text;
using System.Threading;
using Microsoft.Win32;
+using Internal.Runtime.Augments;
#if ES_BUILD_STANDALONE
using EventDescriptor = Microsoft.Diagnostics.Tracing.EventDescriptor;
@@ -196,10 +197,6 @@ using Contract = System.Diagnostics.Contracts.Contract;
using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
#endif
-#if CORECLR || ES_BUILD_PN
-using Internal.Runtime.Augments;
-#endif
-
#if ES_BUILD_STANDALONE
namespace Microsoft.Diagnostics.Tracing
#else
@@ -434,7 +431,7 @@ namespace System.Diagnostics.Tracing
throw new ArgumentException(SR.EventSource_InvalidCommand, nameof(command));
}
- eventSource.SendCommand(null, 0, 0, command, true, EventLevel.LogAlways, EventKeywords.None, commandArguments);
+ eventSource.SendCommand(null, EventProviderType.ETW, 0, 0, command, true, EventLevel.LogAlways, EventKeywords.None, commandArguments);
}
#if !ES_BUILD_STANDALONE
@@ -537,7 +534,7 @@ namespace System.Diagnostics.Tracing
}
}
- #region protected
+#region protected
/// <summary>
/// This is the constructor that most users will use to create their eventSource. It takes
/// no parameters. The ETW provider name and GUID of the EventSource are determined by the EventSource
@@ -606,8 +603,15 @@ namespace System.Diagnostics.Tracing
// typed event methods. Dynamically defined events (that use Write) hare defined on the fly and are handled elsewhere.
private unsafe void DefineEventPipeEvents()
{
+ // If the EventSource is set to emit all events as TraceLogging events, skip this initialization.
+ // Events will be defined when they are emitted for the first time.
+ if(SelfDescribingEvents)
+ {
+ return;
+ }
+
Debug.Assert(m_eventData != null);
- Debug.Assert(m_provider != null);
+ Debug.Assert(m_eventPipeProvider != null);
int cnt = m_eventData.Length;
for (int i = 0; i < cnt; i++)
{
@@ -615,102 +619,30 @@ namespace System.Diagnostics.Tracing
if (eventID == 0)
continue;
+ byte[] metadata = EventPipeMetadataGenerator.Instance.GenerateEventMetadata(m_eventData[i]);
+ uint metadataLength = (metadata != null) ? (uint)metadata.Length : 0;
+
string eventName = m_eventData[i].Name;
- Int64 keywords = m_eventData[i].Descriptor.Keywords;
+ long keywords = m_eventData[i].Descriptor.Keywords;
uint eventVersion = m_eventData[i].Descriptor.Version;
uint level = m_eventData[i].Descriptor.Level;
- // evnetID : 4 bytes
- // eventName : (eventName.Length + 1) * 2 bytes
- // keywords : 8 bytes
- // eventVersion : 4 bytes
- // level : 4 bytes
- // parameterCount : 4 bytes
- uint metadataLength = 24 + ((uint)eventName.Length + 1) * 2;
-
- // Increase the metadataLength for the types of all parameters.
- metadataLength += (uint)m_eventData[i].Parameters.Length * 4;
-
- // Increase the metadataLength for the names of all parameters.
- foreach (var parameter in m_eventData[i].Parameters)
- {
- string parameterName = parameter.Name;
- metadataLength = metadataLength + ((uint)parameterName.Length + 1) * 2;
- }
-
- byte[] metadata = new byte[metadataLength];
-
- // Write metadata: evnetID, eventName, keywords, eventVersion, level, parameterCount, param1 type, param1 name...
fixed (byte *pMetadata = metadata)
{
- uint offset = 0;
- WriteToBuffer(pMetadata, metadataLength, ref offset, eventID);
- fixed(char *pEventName = eventName)
- {
- WriteToBuffer(pMetadata, metadataLength, ref offset, (byte *)pEventName, ((uint)eventName.Length + 1) * 2);
- }
- WriteToBuffer(pMetadata, metadataLength, ref offset, keywords);
- WriteToBuffer(pMetadata, metadataLength, ref offset, eventVersion);
- WriteToBuffer(pMetadata, metadataLength, ref offset, level);
- WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)m_eventData[i].Parameters.Length);
- foreach (var parameter in m_eventData[i].Parameters)
- {
- // Write parameter type.
- WriteToBuffer(pMetadata, metadataLength, ref offset, (uint)GetTypeCodeExtended(parameter.ParameterType));
-
- // Write parameter name.
- string parameterName = parameter.Name;
- fixed (char *pParameterName = parameterName)
- {
- WriteToBuffer(pMetadata, metadataLength, ref offset, (byte *)pParameterName, ((uint)parameterName.Length + 1) * 2);
- }
- }
- Debug.Assert(metadataLength == offset);
- IntPtr eventHandle = m_provider.m_eventProvider.DefineEventHandle(eventID, eventName, keywords, eventVersion, level, pMetadata, metadataLength);
- m_eventData[i].EventHandle = eventHandle;
+ IntPtr eventHandle = m_eventPipeProvider.m_eventProvider.DefineEventHandle(
+ eventID,
+ eventName,
+ keywords,
+ eventVersion,
+ level,
+ pMetadata,
+ metadataLength);
+
+ Debug.Assert(eventHandle != IntPtr.Zero);
+ m_eventData[i].EventHandle = eventHandle;
}
}
}
-
- // Copy src to buffer and modify the offset.
- // Note: We know the buffer size ahead of time to make sure no buffer overflow.
- private static unsafe void WriteToBuffer(byte *buffer, uint bufferLength, ref uint offset, byte *src, uint srcLength)
- {
- Debug.Assert(bufferLength >= (offset + srcLength));
- for (int i = 0; i < srcLength; i++)
- {
- *(byte *)(buffer + offset + i) = *(byte *)(src + i);
- }
- offset += srcLength;
- }
-
- // Copy uint value to buffer.
- private static unsafe void WriteToBuffer(byte *buffer, uint bufferLength, ref uint offset, uint value)
- {
- Debug.Assert(bufferLength >= (offset + 4));
- *(uint *)(buffer + offset) = value;
- offset += 4;
- }
-
- // Copy long value to buffer.
- private static unsafe void WriteToBuffer(byte *buffer, uint bufferLength, ref uint offset, long value)
- {
- Debug.Assert(bufferLength >= (offset + 8));
- *(long *)(buffer + offset) = value;
- offset += 8;
- }
-
- private static TypeCode GetTypeCodeExtended(Type parameterType)
- {
- // Guid is not part of TypeCode, we decided to use 17 to represent it, as it's the "free slot"
- // see https://github.com/dotnet/coreclr/issues/16105#issuecomment-361749750 for more
- const TypeCode GuidTypeCode = (TypeCode)17;
-
- if (parameterType == typeof(Guid)) // Guid is not a part of TypeCode enum
- return GuidTypeCode;
-
- return Type.GetTypeCode(parameterType);
- }
#endif
internal virtual void GetMetadata(out Guid eventSourceGuid, out string eventSourceName, out EventMetadata[] eventData, out byte[] manifestBytes)
@@ -966,7 +898,7 @@ namespace System.Diagnostics.Tracing
EventSource.EventData* descrs = stackalloc EventSource.EventData[2];
descrs[0].DataPointer = (IntPtr)string1Bytes;
descrs[0].Size = ((arg1.Length + 1) * 2);
- descrs[1].Reserved = 0;
+ descrs[0].Reserved = 0;
descrs[1].DataPointer = (IntPtr)(&arg2);
descrs[1].Size = 8;
descrs[1].Reserved = 0;
@@ -1112,7 +1044,7 @@ namespace System.Diagnostics.Tracing
/// </summary>
internal int Reserved { get { return m_Reserved; } set { m_Reserved = value; } }
- #region private
+#region private
/// <summary>
/// Initializes the members of this EventData object to point at a previously-pinned
/// tracelogging-compatible metadata blob.
@@ -1134,7 +1066,7 @@ namespace System.Diagnostics.Tracing
#pragma warning disable 0649
internal int m_Reserved; // Used to pad the size to match the Win32 API
#pragma warning restore 0649
- #endregion
+#endregion
}
/// <summary>
@@ -1230,12 +1162,20 @@ namespace System.Diagnostics.Tracing
}
#if FEATURE_MANAGED_ETW
- if (m_eventData[eventId].EnabledForETW)
+ if (m_eventData[eventId].EnabledForETW
+#if FEATURE_PERFTRACING
+ || m_eventData[eventId].EnabledForEventPipe
+#endif // FEATURE_PERFTRACING
+ )
{
if (!SelfDescribingEvents)
{
- if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
+ if (!m_etwProvider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
ThrowEventSourceException(m_eventData[eventId].Name);
+#if FEATURE_PERFTRACING
+ if (!m_eventPipeProvider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
+ ThrowEventSourceException(m_eventData[eventId].Name);
+#endif // FEATURE_PERFTRACING
}
else
{
@@ -1261,7 +1201,7 @@ namespace System.Diagnostics.Tracing
#endif // FEATURE_MANAGED_ETW
if (m_Dispatchers != null && m_eventData[eventId].EnabledForAnyListener)
- WriteToAllListeners(eventId, relatedActivityId, eventDataCount, data);
+ WriteToAllListeners(eventId, pActivityId, relatedActivityId, eventDataCount, data);
}
catch (Exception ex)
{
@@ -1300,9 +1240,9 @@ namespace System.Diagnostics.Tracing
WriteEventVarargs(eventId, &relatedActivityId, args);
}
- #endregion
+#endregion
- #region IDisposable Members
+#region IDisposable Members
/// <summary>
/// Disposes of an EventSource.
/// </summary>
@@ -1326,7 +1266,6 @@ namespace System.Diagnostics.Tracing
if (disposing)
{
#if FEATURE_MANAGED_ETW
-#if !FEATURE_PERFTRACING
// Send the manifest one more time to ensure circular buffers have a chance to get to this information
// even in scenarios with a high volume of ETW events.
if (m_eventSourceEnabled)
@@ -1339,11 +1278,17 @@ namespace System.Diagnostics.Tracing
{ } // If it fails, simply give up.
m_eventSourceEnabled = false;
}
+ if (m_etwProvider != null)
+ {
+ m_etwProvider.Dispose();
+ m_etwProvider = null;
+ }
#endif
- if (m_provider != null)
+#if FEATURE_PERFTRACING
+ if (m_eventPipeProvider != null)
{
- m_provider.Dispose();
- m_provider = null;
+ m_eventPipeProvider.Dispose();
+ m_eventPipeProvider = null;
}
#endif
}
@@ -1357,29 +1302,41 @@ namespace System.Diagnostics.Tracing
{
this.Dispose(false);
}
- #endregion
+#endregion
- #region private
+#region private
private unsafe void WriteEventRaw(
string eventName,
ref EventDescriptor eventDescriptor,
+ IntPtr eventHandle,
Guid* activityID,
Guid* relatedActivityID,
int dataCount,
IntPtr data)
{
#if FEATURE_MANAGED_ETW
- if (m_provider == null)
+ if (m_etwProvider == null)
{
ThrowEventSourceException(eventName);
}
else
{
- if (!m_provider.WriteEventRaw(ref eventDescriptor, activityID, relatedActivityID, dataCount, data))
+ if (!m_etwProvider.WriteEventRaw(ref eventDescriptor, eventHandle, activityID, relatedActivityID, dataCount, data))
ThrowEventSourceException(eventName);
}
#endif // FEATURE_MANAGED_ETW
+#if FEATURE_PERFTRACING
+ if (m_eventPipeProvider == null)
+ {
+ ThrowEventSourceException(eventName);
+ }
+ else
+ {
+ if (!m_eventPipeProvider.WriteEventRaw(ref eventDescriptor, eventHandle, activityID, relatedActivityID, dataCount, data))
+ ThrowEventSourceException(eventName);
+ }
+#endif // FEATURE_PERFTRACING
}
// FrameworkEventSource is on the startup path for the framework, so we have this internal overload that it can use
@@ -1428,14 +1385,20 @@ namespace System.Diagnostics.Tracing
//Enable Implicit Activity tracker
m_activityTracker = ActivityTracker.Instance;
-#if FEATURE_MANAGED_ETW
+#if FEATURE_MANAGED_ETW || FEATURE_PERFTRACING
// Create and register our provider traits. We do this early because it is needed to log errors
// In the self-describing event case.
this.InitializeProviderMetadata();
-
+#endif
+#if FEATURE_MANAGED_ETW
// Register the provider with ETW
- var provider = new OverideEventProvider(this);
- provider.Register(this);
+ var etwProvider = new OverideEventProvider(this, EventProviderType.ETW);
+ etwProvider.Register(this);
+#endif
+#if FEATURE_PERFTRACING
+ // Register the provider with EventPipe
+ var eventPipeProvider = new OverideEventProvider(this, EventProviderType.EventPipe);
+ eventPipeProvider.Register(this);
#endif
// Add the eventSource to the global (weak) list.
// This also sets m_id, which is the index in the list.
@@ -1444,7 +1407,7 @@ namespace System.Diagnostics.Tracing
#if FEATURE_MANAGED_ETW
// OK if we get this far without an exception, then we can at least write out error messages.
// Set m_provider, which allows this.
- m_provider = provider;
+ m_etwProvider = etwProvider;
#if PLATFORM_WINDOWS
#if (!ES_BUILD_STANDALONE && !ES_BUILD_PN)
@@ -1458,7 +1421,7 @@ namespace System.Diagnostics.Tracing
System.Runtime.InteropServices.GCHandle.Alloc(this.providerMetadata, System.Runtime.InteropServices.GCHandleType.Pinned);
IntPtr providerMetadata = metadataHandle.AddrOfPinnedObject();
- setInformationResult = m_provider.SetInformation(
+ setInformationResult = m_etwProvider.SetInformation(
UnsafeNativeMethods.ManifestEtw.EVENT_INFO_CLASS.SetTraits,
providerMetadata,
(uint)this.providerMetadata.Length);
@@ -1467,6 +1430,10 @@ namespace System.Diagnostics.Tracing
}
#endif // PLATFORM_WINDOWS
#endif // FEATURE_MANAGED_ETW
+
+#if FEATURE_PERFTRACING
+ m_eventPipeProvider = eventPipeProvider;
+#endif
Debug.Assert(!m_eventSourceEnabled); // We can't be enabled until we are completely initted.
// We are logically completely initialized at this point.
m_completelyInited = true;
@@ -1683,6 +1650,14 @@ namespace System.Diagnostics.Tracing
private static Guid GenerateGuidFromName(string name)
{
+ if (namespaceBytes == null)
+ {
+ namespaceBytes = new byte[] {
+ 0x48, 0x2C, 0x2D, 0xB2, 0xC3, 0x90, 0x47, 0xC8,
+ 0x87, 0xF8, 0x1A, 0x15, 0xBF, 0xC1, 0x30, 0xFB,
+ };
+ }
+
byte[] bytes = Encoding.BigEndianUnicode.GetBytes(name);
var hash = new Sha1ForNonSecretPurposes();
hash.Start();
@@ -1810,10 +1785,16 @@ namespace System.Diagnostics.Tracing
if (dataType.IsEnum())
{
dataType = Enum.GetUnderlyingType(dataType);
+#if ES_BUILD_PN
+ int dataTypeSize = (int)dataType.TypeHandle.ToEETypePtr().ValueTypeSize;
+#else
+ int dataTypeSize = System.Runtime.InteropServices.Marshal.SizeOf(dataType);
+#endif
+ if (dataTypeSize < sizeof(int))
+ dataType = typeof(int);
goto Again;
}
-
// Everything else is marshaled as a string.
// ETW strings are NULL-terminated, so marshal everything up to the first
// null in the string.
@@ -1824,7 +1805,6 @@ namespace System.Diagnostics.Tracing
}
return new string((char *)dataPointer);
-
}
finally
{
@@ -1899,12 +1879,20 @@ namespace System.Diagnostics.Tracing
}
#if FEATURE_MANAGED_ETW
- if (m_eventData[eventId].EnabledForETW)
+ if (m_eventData[eventId].EnabledForETW
+#if FEATURE_PERFTRACING
+ || m_eventData[eventId].EnabledForEventPipe
+#endif // FEATURE_PERFTRACING
+ )
{
if (!SelfDescribingEvents)
{
- if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args))
+ if (!m_etwProvider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args))
+ ThrowEventSourceException(m_eventData[eventId].Name);
+#if FEATURE_PERFTRACING
+ if (!m_eventPipeProvider.WriteEvent(ref m_eventData[eventId].Descriptor, m_eventData[eventId].EventHandle, pActivityId, childActivityID, args))
ThrowEventSourceException(m_eventData[eventId].Name);
+#endif // FEATURE_PERFTRACING
}
else
{
@@ -1929,19 +1917,31 @@ namespace System.Diagnostics.Tracing
}
}
#endif // FEATURE_MANAGED_ETW
- if (m_Dispatchers != null && m_eventData[eventId].EnabledForAnyListener)
+ if (m_Dispatchers != null && m_eventData[eventId].EnabledForAnyListener)
{
#if (!ES_BUILD_STANDALONE && !ES_BUILD_PN)
// Maintain old behavior - object identity is preserved
if (AppContextSwitches.PreserveEventListnerObjectIdentity)
{
- WriteToAllListeners(eventId, childActivityID, args);
+ WriteToAllListeners(
+ eventId: eventId,
+ osThreadId: null,
+ timeStamp: null,
+ activityID: pActivityId,
+ childActivityID: childActivityID,
+ args: args);
}
else
#endif // !ES_BUILD_STANDALONE
{
object[] serializedArgs = SerializeEventArgs(eventId, args);
- WriteToAllListeners(eventId, childActivityID, serializedArgs);
+ WriteToAllListeners(
+ eventId: eventId,
+ osThreadId: null,
+ timeStamp: null,
+ activityID: pActivityId,
+ childActivityID: childActivityID,
+ args: serializedArgs);
}
}
}
@@ -1955,7 +1955,7 @@ namespace System.Diagnostics.Tracing
}
}
- unsafe private object[] SerializeEventArgs(int eventId, object[] args)
+ private unsafe object[] SerializeEventArgs(int eventId, object[] args)
{
TraceLoggingEventTypes eventTypes = m_eventData[eventId].TraceLoggingEventTypes;
if (eventTypes == null)
@@ -2012,7 +2012,7 @@ namespace System.Diagnostics.Tracing
#endif //!ES_BUILD_PCL
}
- unsafe private void WriteToAllListeners(int eventId, Guid* childActivityID, int eventDataCount, EventSource.EventData* data)
+ private unsafe void WriteToAllListeners(int eventId, Guid* activityID, Guid* childActivityID, int eventDataCount, EventSource.EventData* data)
{
// We represent a byte[] as a integer denoting the length and then a blob of bytes in the data pointer. This causes a spurious
// warning because eventDataCount is off by one for the byte[] case since a byte[] has 2 items associated it. So we want to check
@@ -2043,14 +2043,26 @@ namespace System.Diagnostics.Tracing
EventSource.EventData* dataPtr = data;
for (int i = 0; i < paramCount; i++)
args[i] = DecodeObject(eventId, i, ref dataPtr);
- WriteToAllListeners(eventId, childActivityID, args);
+ WriteToAllListeners(
+ eventId: eventId,
+ osThreadId: null,
+ timeStamp: null,
+ activityID: activityID,
+ childActivityID: childActivityID,
+ args: args);
}
// helper for writing to all EventListeners attached the current eventSource.
- unsafe private void WriteToAllListeners(int eventId, Guid* childActivityID, params object[] args)
+ internal unsafe void WriteToAllListeners(int eventId, uint* osThreadId, DateTime* timeStamp, Guid* activityID, Guid* childActivityID, params object[] args)
{
EventWrittenEventArgs eventCallbackArgs = new EventWrittenEventArgs(this);
eventCallbackArgs.EventId = eventId;
+ if (osThreadId != null)
+ eventCallbackArgs.OSThreadId = (int)*osThreadId;
+ if (timeStamp != null)
+ eventCallbackArgs.TimeStamp = *timeStamp;
+ if (activityID != null)
+ eventCallbackArgs.ActivityId = *activityID;
if (childActivityID != null)
eventCallbackArgs.RelatedActivityId = *childActivityID;
eventCallbackArgs.EventName = m_eventData[eventId].Name;
@@ -2092,8 +2104,8 @@ namespace System.Diagnostics.Tracing
[SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
private unsafe void WriteEventString(EventLevel level, long keywords, string msgString)
{
-#if FEATURE_MANAGED_ETW && !FEATURE_PERFTRACING
- if (m_provider != null)
+#if FEATURE_MANAGED_ETW
+ if (m_etwProvider != null)
{
string eventName = "EventSourceMessage";
if (SelfDescribingEvents)
@@ -2128,7 +2140,7 @@ namespace System.Diagnostics.Tracing
data.Ptr = (ulong)msgStringPtr;
data.Size = (uint)(2 * (msgString.Length + 1));
data.Reserved = 0;
- m_provider.WriteEvent(ref descr, IntPtr.Zero, null, null, 1, (IntPtr)((void*)&data));
+ m_etwProvider.WriteEvent(ref descr, IntPtr.Zero, null, null, 1, (IntPtr)((void*)&data));
}
}
}
@@ -2273,7 +2285,10 @@ namespace System.Diagnostics.Tracing
break;
default:
if (innerEx != null)
+ {
+ innerEx = innerEx.GetBaseException();
ReportOutOfBandMessage(errorPrefix + ": " + innerEx.GetType() + ":" + innerEx.Message, true);
+ }
else
ReportOutOfBandMessage(errorPrefix, true);
if (ThrowOnEventWriteErrors) throw new EventSourceException(innerEx);
@@ -2319,19 +2334,22 @@ namespace System.Diagnostics.Tracing
/// </summary>
private class OverideEventProvider : EventProvider
{
- public OverideEventProvider(EventSource eventSource)
+ public OverideEventProvider(EventSource eventSource, EventProviderType providerType)
+ : base(providerType)
{
this.m_eventSource = eventSource;
+ this.m_eventProviderType = providerType;
}
protected override void OnControllerCommand(ControllerCommand command, IDictionary<string, string> arguments,
int perEventSourceSessionId, int etwSessionId)
{
// We use null to represent the ETW EventListener.
EventListener listener = null;
- m_eventSource.SendCommand(listener, perEventSourceSessionId, etwSessionId,
+ m_eventSource.SendCommand(listener, m_eventProviderType, perEventSourceSessionId, etwSessionId,
(EventCommand)command, IsEnabled(), Level, MatchAnyKeyword, arguments);
}
private EventSource m_eventSource;
+ private EventProviderType m_eventProviderType;
}
#endif
@@ -2360,7 +2378,10 @@ namespace System.Diagnostics.Tracing
public IntPtr EventHandle; // EventPipeEvent handle.
public EventTags Tags;
public bool EnabledForAnyListener; // true if any dispatcher has this event turned on
- public bool EnabledForETW; // is this event on for the OS ETW data dispatcher?
+ public bool EnabledForETW; // is this event on for ETW?
+#if FEATURE_PERFTRACING
+ public bool EnabledForEventPipe; // is this event on for EventPipe?
+#endif
public bool HasRelatedActivityID; // Set if the event method's first parameter is a Guid named 'relatedActivityId'
#pragma warning disable 0649
@@ -2404,12 +2425,12 @@ namespace System.Diagnostics.Tracing
// * The 'enabled' 'level', matchAnyKeyword' arguments are ignored (must be true, 0, 0).
//
// dispatcher == null has special meaning. It is the 'ETW' dispatcher.
- internal void SendCommand(EventListener listener, int perEventSourceSessionId, int etwSessionId,
+ internal void SendCommand(EventListener listener, EventProviderType eventProviderType, int perEventSourceSessionId, int etwSessionId,
EventCommand command, bool enable,
EventLevel level, EventKeywords matchAnyKeyword,
IDictionary<string, string> commandArguments)
{
- var commandArgs = new EventCommandEventArgs(command, commandArguments, this, listener, perEventSourceSessionId, etwSessionId, enable, level, matchAnyKeyword);
+ var commandArgs = new EventCommandEventArgs(command, commandArguments, this, listener, eventProviderType, perEventSourceSessionId, etwSessionId, enable, level, matchAnyKeyword);
lock (EventListener.EventListenersLock)
{
if (m_completelyInited)
@@ -2449,9 +2470,13 @@ namespace System.Diagnostics.Tracing
Debug.Assert(m_completelyInited);
#if FEATURE_MANAGED_ETW
- if (m_provider == null) // If we failed to construct
+ if (m_etwProvider == null) // If we failed to construct
return;
#endif // FEATURE_MANAGED_ETW
+#if FEATURE_PERFTRACING
+ if (m_eventPipeProvider == null)
+ return;
+#endif
m_outOfBandMessageCount = 0;
bool shouldReport = (commandArgs.perEventSourceSessionId > 0) && (commandArgs.perEventSourceSessionId <= SessionMask.MAX);
@@ -2474,7 +2499,7 @@ namespace System.Diagnostics.Tracing
{
// Set it up using the 'standard' filtering bitfields (use the "global" enable, not session specific one)
for (int i = 0; i < m_eventData.Length; i++)
- EnableEventForDispatcher(commandArgs.dispatcher, i, IsEnabledByDefault(i, commandArgs.enable, commandArgs.level, commandArgs.matchAnyKeyword));
+ EnableEventForDispatcher(commandArgs.dispatcher, commandArgs.eventProviderType, i, IsEnabledByDefault(i, commandArgs.enable, commandArgs.level, commandArgs.matchAnyKeyword));
if (commandArgs.enable)
{
@@ -2524,13 +2549,11 @@ namespace System.Diagnostics.Tracing
{
// eventSourceDispatcher == null means this is the ETW manifest
-#if !FEATURE_PERFTRACING
// Note that we unconditionally send the manifest whenever we are enabled, even if
// we were already enabled. This is because there may be multiple sessions active
// and we can't know that all the sessions have seen the manifest.
if (!SelfDescribingEvents)
SendManifest(m_rawManifest);
-#endif
}
// Turn on the enable bit before making the OnEventCommand callback This allows you to do useful
@@ -2612,16 +2635,20 @@ namespace System.Diagnostics.Tracing
/// of 'eventId. If value is 'false' disable the event for that dispatcher. If 'eventId' is out of
/// range return false, otherwise true.
/// </summary>
- internal bool EnableEventForDispatcher(EventDispatcher dispatcher, int eventId, bool value)
+ internal bool EnableEventForDispatcher(EventDispatcher dispatcher, EventProviderType eventProviderType, int eventId, bool value)
{
if (dispatcher == null)
{
if (eventId >= m_eventData.Length)
return false;
#if FEATURE_MANAGED_ETW
- if (m_provider != null)
+ if (m_etwProvider != null && eventProviderType == EventProviderType.ETW)
m_eventData[eventId].EnabledForETW = value;
#endif
+#if FEATURE_PERFTRACING
+ if (m_eventPipeProvider != null && eventProviderType == EventProviderType.EventPipe)
+ m_eventData[eventId].EnabledForEventPipe = value;
+#endif
}
else
{
@@ -2640,7 +2667,11 @@ namespace System.Diagnostics.Tracing
private bool AnyEventEnabled()
{
for (int i = 0; i < m_eventData.Length; i++)
- if (m_eventData[i].EnabledForETW || m_eventData[i].EnabledForAnyListener)
+ if (m_eventData[i].EnabledForETW || m_eventData[i].EnabledForAnyListener
+#if FEATURE_PERFTRACING
+ || m_eventData[i].EnabledForEventPipe
+#endif // FEATURE_PERFTRACING
+ )
return true;
return false;
}
@@ -2730,7 +2761,7 @@ namespace System.Diagnostics.Tracing
Debug.Assert(!SelfDescribingEvents);
-#if FEATURE_MANAGED_ETW
+#if FEATURE_MANAGED_ETW
fixed (byte* dataPtr = rawManifest)
{
// we don't want the manifest to show up in the event log channels so we specify as keywords
@@ -2760,9 +2791,9 @@ namespace System.Diagnostics.Tracing
while (dataLeft > 0)
{
dataDescrs[1].Size = (uint)Math.Min(dataLeft, chunkSize);
- if (m_provider != null)
+ if (m_etwProvider != null)
{
- if (!m_provider.WriteEvent(ref manifestDescr, IntPtr.Zero, null, null, 2, (IntPtr)dataDescrs))
+ if (!m_etwProvider.WriteEvent(ref manifestDescr, IntPtr.Zero, null, null, 2, (IntPtr)dataDescrs))
{
// Turns out that if users set the BufferSize to something less than 64K then WriteEvent
// can fail. If we get this failure on the first chunk try again with something smaller
@@ -3230,7 +3261,7 @@ namespace System.Diagnostics.Tracing
if ((flags & EventManifestOptions.Strict) != 0 && (manifest.Errors.Count > 0 || exception != null))
{
- string msg = String.Empty;
+ string msg = string.Empty;
if (manifest.Errors.Count > 0)
{
bool firstError = true;
@@ -3255,7 +3286,7 @@ namespace System.Diagnostics.Tracing
{
// If the first parameter is (case insensitive) 'relatedActivityId' then skip it.
if (args.Length > 0 && args[0].ParameterType == typeof(Guid) &&
- string.Compare(args[0].Name, "relatedActivityId", StringComparison.OrdinalIgnoreCase) == 0)
+ string.Equals(args[0].Name, "relatedActivityId", StringComparison.OrdinalIgnoreCase))
{
var newargs = new ParameterInfo[args.Length - 1];
Array.Copy(args, 1, newargs, 0, args.Length - 1);
@@ -3465,7 +3496,7 @@ namespace System.Diagnostics.Tracing
/// <param name="method">The method to probe.</param>
/// <returns>The literal value or -1 if the value could not be determined. </returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Switch statement is clearer than alternatives")]
- static private int GetHelperCallFirstArg(MethodInfo method)
+ private static int GetHelperCallFirstArg(MethodInfo method)
{
#if (!ES_BUILD_PCL && !ES_BUILD_PN)
// Currently searches for the following pattern
@@ -3612,7 +3643,7 @@ namespace System.Diagnostics.Tracing
{
#if (!ES_BUILD_PCL && !ES_BUILD_PN)
// send message to debugger without delay
- System.Diagnostics.Debugger.Log(0, null, String.Format("EventSource Error: {0}{1}", msg, Environment.NewLine));
+ System.Diagnostics.Debugger.Log(0, null, string.Format("EventSource Error: {0}{1}", msg, Environment.NewLine));
#endif
// Send it to all listeners.
@@ -3701,7 +3732,10 @@ namespace System.Diagnostics.Tracing
// Dispatching state
internal volatile EventDispatcher m_Dispatchers; // Linked list of code:EventDispatchers we write the data to (we also do ETW specially)
#if FEATURE_MANAGED_ETW
- private volatile OverideEventProvider m_provider; // This hooks up ETW commands to our 'OnEventCommand' callback
+ private volatile OverideEventProvider m_etwProvider; // This hooks up ETW commands to our 'OnEventCommand' callback
+#endif
+#if FEATURE_PERFTRACING
+ private volatile OverideEventProvider m_eventPipeProvider;
#endif
private bool m_completelyInited; // The EventSource constructor has returned without exception.
private Exception m_constructionException; // If there was an exception construction, this is it
@@ -3727,11 +3761,12 @@ namespace System.Diagnostics.Tracing
internal const string s_ActivityStartSuffix = "Start";
internal const string s_ActivityStopSuffix = "Stop";
+ // WARNING: Do not depend upon initialized statics during creation of EventSources, as it is possible for creation of an EventSource to trigger
+ // creation of yet another EventSource. When this happens, these statics may not yet be initialized.
+ // Rather than depending on initialized statics, use lazy initialization to ensure that the statics are initialized exactly when they are needed.
+
// used for generating GUID from eventsource name
- private static readonly byte[] namespaceBytes = new byte[] {
- 0x48, 0x2C, 0x2D, 0xB2, 0xC3, 0x90, 0x47, 0xC8,
- 0x87, 0xF8, 0x1A, 0x15, 0xBF, 0xC1, 0x30, 0xFB,
- };
+ private static byte[] namespaceBytes;
#endregion
}
@@ -3840,6 +3875,16 @@ namespace System.Diagnostics.Tracing
/// </summary>
public event EventHandler<EventWrittenEventArgs> EventWritten;
+ static EventListener()
+ {
+#if FEATURE_PERFTRACING
+ // Ensure that RuntimeEventSource is initialized so that EventListeners get an opportunity to subscribe to its events.
+ // This is required because RuntimeEventSource never emit events on its own, and thus will never be initialized
+ // in the normal way that EventSources are initialized.
+ GC.KeepAlive(RuntimeEventSource.Log);
+#endif // FEATURE_PERFTRACING
+ }
+
/// <summary>
/// Create a new EventListener in which all events start off turned off (use EnableEvents to turn
/// them on).
@@ -3945,7 +3990,14 @@ namespace System.Diagnostics.Tracing
throw new ArgumentNullException(nameof(eventSource));
}
- eventSource.SendCommand(this, 0, 0, EventCommand.Update, true, level, matchAnyKeyword, arguments);
+ eventSource.SendCommand(this, EventProviderType.None, 0, 0, EventCommand.Update, true, level, matchAnyKeyword, arguments);
+
+#if FEATURE_PERFTRACING
+ if (eventSource.GetType() == typeof(RuntimeEventSource))
+ {
+ EventPipeEventDispatcher.Instance.SendCommand(this, EventCommand.Update, true, level, matchAnyKeyword);
+ }
+#endif // FEATURE_PERFTRACING
}
/// <summary>
/// Disables all events coming from eventSource identified by 'eventSource'.
@@ -3959,7 +4011,14 @@ namespace System.Diagnostics.Tracing
throw new ArgumentNullException(nameof(eventSource));
}
- eventSource.SendCommand(this, 0, 0, EventCommand.Update, false, EventLevel.LogAlways, EventKeywords.None, null);
+ eventSource.SendCommand(this, EventProviderType.None, 0, 0, EventCommand.Update, false, EventLevel.LogAlways, EventKeywords.None, null);
+
+#if FEATURE_PERFTRACING
+ if (eventSource.GetType() == typeof(RuntimeEventSource))
+ {
+ EventPipeEventDispatcher.Instance.SendCommand(this, EventCommand.Update, false, EventLevel.LogAlways, EventKeywords.None);
+ }
+#endif // FEATURE_PERFTRACING
}
/// <summary>
@@ -4033,6 +4092,12 @@ namespace System.Diagnostics.Tracing
if (!s_EventSourceShutdownRegistered)
{
s_EventSourceShutdownRegistered = true;
+#if ES_BUILD_PN
+ AppContext.ProcessExit += DisposeOnShutdown;
+#else
+ AppDomain.CurrentDomain.ProcessExit += DisposeOnShutdown;
+ AppDomain.CurrentDomain.DomainUnload += DisposeOnShutdown;
+#endif
}
@@ -4061,9 +4126,24 @@ namespace System.Diagnostics.Tracing
}
newEventSource.m_id = newIndex;
- // Add every existing dispatcher to the new EventSource
- for (EventListener listener = s_Listeners; listener != null; listener = listener.m_Next)
- newEventSource.AddListener(listener);
+#if DEBUG
+ // Disable validation of EventSource/EventListener connections in case a call to EventSource.AddListener
+ // causes a recursive call into this method.
+ bool previousValue = s_ConnectingEventSourcesAndListener;
+ s_ConnectingEventSourcesAndListener = true;
+ try
+ {
+#endif
+ // Add every existing dispatcher to the new EventSource
+ for (EventListener listener = s_Listeners; listener != null; listener = listener.m_Next)
+ newEventSource.AddListener(listener);
+#if DEBUG
+ }
+ finally
+ {
+ s_ConnectingEventSourcesAndListener = previousValue;
+ }
+#endif
Validate();
}
@@ -4131,6 +4211,11 @@ namespace System.Diagnostics.Tracing
}
}
}
+
+#if FEATURE_PERFTRACING
+ // Remove the listener from the EventPipe dispatcher.
+ EventPipeEventDispatcher.Instance.RemoveEventListener(listenerToRemove);
+#endif // FEATURE_PERFTRACING
}
/// <summary>
@@ -4139,6 +4224,14 @@ namespace System.Diagnostics.Tracing
[Conditional("DEBUG")]
internal static void Validate()
{
+#if DEBUG
+ // Don't run validation code if we're in the middle of modifying the connections between EventSources and EventListeners.
+ if (s_ConnectingEventSourcesAndListener)
+ {
+ return;
+ }
+#endif
+
lock (EventListenersLock)
{
// Get all listeners
@@ -4228,18 +4321,30 @@ namespace System.Diagnostics.Tracing
// is created.
WeakReference[] eventSourcesSnapshot = s_EventSources.ToArray();
- for (int i = 0; i < eventSourcesSnapshot.Length; i++)
+#if DEBUG
+ bool previousValue = s_ConnectingEventSourcesAndListener;
+ s_ConnectingEventSourcesAndListener = true;
+ try
{
- WeakReference eventSourceRef = eventSourcesSnapshot[i];
- EventSource eventSource = eventSourceRef.Target as EventSource;
- if (eventSource != null)
+#endif
+ for (int i = 0; i < eventSourcesSnapshot.Length; i++)
{
- EventSourceCreatedEventArgs args = new EventSourceCreatedEventArgs();
- args.EventSource = eventSource;
- callback(this, args);
+ WeakReference eventSourceRef = eventSourcesSnapshot[i];
+ EventSource eventSource = eventSourceRef.Target as EventSource;
+ if (eventSource != null)
+ {
+ EventSourceCreatedEventArgs args = new EventSourceCreatedEventArgs();
+ args.EventSource = eventSource;
+ callback(this, args);
+ }
}
+#if DEBUG
}
-
+ finally
+ {
+ s_ConnectingEventSourcesAndListener = previousValue;
+ }
+#endif
Validate();
}
finally
@@ -4273,6 +4378,16 @@ namespace System.Diagnostics.Tracing
/// </summary>
private static bool s_CreatingListener = false;
+#if DEBUG
+ /// <summary>
+ /// Used to disable validation of EventSource and EventListener connectivity.
+ /// This is needed when an EventListener is in the middle of being published to all EventSources
+ /// and another EventSource is created as part of the process.
+ /// </summary>
+ [ThreadStatic]
+ private static bool s_ConnectingEventSourcesAndListener = false;
+#endif
+
/// <summary>
/// Used to register AD/Process shutdown callbacks.
/// </summary>
@@ -4293,7 +4408,7 @@ namespace System.Diagnostics.Tracing
/// <summary>
/// Gets the arguments for the callback.
/// </summary>
- public IDictionary<String, String> Arguments { get; internal set; }
+ public IDictionary<string, string> Arguments { get; internal set; }
/// <summary>
/// Enables the event that has the specified identifier.
@@ -4304,7 +4419,7 @@ namespace System.Diagnostics.Tracing
{
if (Command != EventCommand.Enable && Command != EventCommand.Disable)
throw new InvalidOperationException();
- return eventSource.EnableEventForDispatcher(dispatcher, eventId, true);
+ return eventSource.EnableEventForDispatcher(dispatcher, eventProviderType, eventId, true);
}
/// <summary>
@@ -4316,18 +4431,19 @@ namespace System.Diagnostics.Tracing
{
if (Command != EventCommand.Enable && Command != EventCommand.Disable)
throw new InvalidOperationException();
- return eventSource.EnableEventForDispatcher(dispatcher, eventId, false);
+ return eventSource.EnableEventForDispatcher(dispatcher, eventProviderType, eventId, false);
}
#region private
internal EventCommandEventArgs(EventCommand command, IDictionary<string, string> arguments, EventSource eventSource,
- EventListener listener, int perEventSourceSessionId, int etwSessionId, bool enable, EventLevel level, EventKeywords matchAnyKeyword)
+ EventListener listener, EventProviderType eventProviderType, int perEventSourceSessionId, int etwSessionId, bool enable, EventLevel level, EventKeywords matchAnyKeyword)
{
this.Command = command;
this.Arguments = arguments;
this.eventSource = eventSource;
this.listener = listener;
+ this.eventProviderType = eventProviderType;
this.perEventSourceSessionId = perEventSourceSessionId;
this.etwSessionId = etwSessionId;
this.enable = enable;
@@ -4337,6 +4453,7 @@ namespace System.Diagnostics.Tracing
internal EventSource eventSource;
internal EventDispatcher dispatcher;
+ internal EventProviderType eventProviderType;
// These are the arguments of sendCommand and are only used for deferring commands until after we are fully initialized.
internal EventListener listener;
@@ -4401,7 +4518,20 @@ namespace System.Diagnostics.Tracing
/// </summary>
public Guid ActivityId
{
- get { return EventSource.CurrentThreadActivityId; }
+ get
+ {
+ Guid activityId = m_activityId;
+ if (activityId == Guid.Empty)
+ {
+ activityId = EventSource.CurrentThreadActivityId;
+ }
+
+ return activityId;
+ }
+ internal set
+ {
+ m_activityId = value;
+ }
}
/// <summary>
@@ -4416,7 +4546,7 @@ namespace System.Diagnostics.Tracing
/// <summary>
/// Gets the payload for the event.
/// </summary>
- public ReadOnlyCollection<Object> Payload { get; internal set; }
+ public ReadOnlyCollection<object> Payload { get; internal set; }
/// <summary>
/// Gets the payload argument names.
@@ -4567,15 +4697,47 @@ namespace System.Diagnostics.Tracing
}
}
+ /// <summary>
+ /// Gets the identifier for the OS thread that wrote the event.
+ /// </summary>
+ public long OSThreadId
+ {
+ get
+ {
+ if (!m_osThreadId.HasValue)
+ {
+ m_osThreadId = (long)RuntimeThread.CurrentOSThreadId;
+ }
+
+ return m_osThreadId.Value;
+ }
+ internal set
+ {
+ m_osThreadId = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets a UTC DateTime that specifies when the event was written.
+ /// </summary>
+ public DateTime TimeStamp
+ {
+ get;
+ internal set;
+ }
+
#region private
internal EventWrittenEventArgs(EventSource eventSource)
{
m_eventSource = eventSource;
+ TimeStamp = DateTime.UtcNow;
}
private string m_message;
private string m_eventName;
private EventSource m_eventSource;
private ReadOnlyCollection<string> m_payloadNames;
+ private Guid m_activityId;
+ private long? m_osThreadId;
internal EventTags m_tags;
internal EventOpcode m_opcode;
internal EventLevel m_level;
@@ -5215,7 +5377,7 @@ namespace System.Diagnostics.Tracing
templates.Append(" length=\"").Append(name).Append("Size\"");
}
// ETW does not support 64-bit value maps, so we don't specify these as ETW maps
- if (type.IsEnum() && Enum.GetUnderlyingType(type) != typeof(UInt64) && Enum.GetUnderlyingType(type) != typeof(Int64))
+ if (type.IsEnum() && Enum.GetUnderlyingType(type) != typeof(ulong) && Enum.GetUnderlyingType(type) != typeof(long))
{
templates.Append(" map=\"").Append(type.Name).Append("\"");
if (mapsTab == null)
@@ -5412,29 +5574,38 @@ namespace System.Diagnostics.Tracing
// write out each enum value
FieldInfo[] staticFields = enumType.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static);
+ bool anyValuesWritten = false;
foreach (FieldInfo staticField in staticFields)
{
object constantValObj = staticField.GetRawConstantValue();
+
if (constantValObj != null)
{
- long hexValue;
- if (constantValObj is int)
- hexValue = ((int)constantValObj);
- else if (constantValObj is long)
- hexValue = ((long)constantValObj);
- else
- continue;
+ ulong hexValue;
+ if (constantValObj is ulong)
+ hexValue = (ulong)constantValObj; // This is the only integer type that can't be represented by a long.
+ else
+ hexValue = (ulong) Convert.ToInt64(constantValObj); // Handles all integer types except ulong.
// ETW requires all bitmap values to be powers of 2. Skip the ones that are not.
// TODO: Warn people about the dropping of values.
if (isbitmap && ((hexValue & (hexValue - 1)) != 0 || hexValue == 0))
continue;
-
sb.Append(" <map value=\"0x").Append(hexValue.ToString("x", CultureInfo.InvariantCulture)).Append("\"");
WriteMessageAttrib(sb, "map", enumType.Name + "." + staticField.Name, staticField.Name);
sb.Append("/>").AppendLine();
+ anyValuesWritten = true;
}
}
+
+ // the OS requires that bitmaps and valuemaps have at least one value or it reject the whole manifest.
+ // To avoid that put a 'None' entry if there are no other values.
+ if (!anyValuesWritten)
+ {
+ sb.Append(" <map value=\"0x0\"");
+ WriteMessageAttrib(sb, "map", enumType.Name + "." + "None", "None");
+ sb.Append("/>").AppendLine();
+ }
sb.Append(" </").Append(mapKind).Append(">").AppendLine();
}
sb.Append(" </maps>").AppendLine();
@@ -5778,7 +5949,7 @@ namespace System.Diagnostics.Tracing
int leftBracket = i;
i++;
int argNum = 0;
- while (i < eventMessage.Length && Char.IsDigit(eventMessage[i]))
+ while (i < eventMessage.Length && char.IsDigit(eventMessage[i]))
{
argNum = argNum * 10 + eventMessage[i] - '0';
i++;
@@ -5904,4 +6075,3 @@ namespace System.Diagnostics.Tracing
#endregion
}
-
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IEventProvider.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IEventProvider.cs
index d34f80eb5..9bbebc79e 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IEventProvider.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/IEventProvider.cs
@@ -38,6 +38,6 @@ namespace System.Diagnostics.Tracing
int EventActivityIdControl(UnsafeNativeMethods.ManifestEtw.ActivityControl ControlCode, ref Guid ActivityId);
// Define an EventPipeEvent handle.
- unsafe IntPtr DefineEventHandle(uint eventID, string eventName, Int64 keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength);
+ unsafe IntPtr DefineEventHandle(uint eventID, string eventName, long keywords, uint eventVersion, uint level, byte *pMetadata, uint metadataLength);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/StubEnvironment.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/StubEnvironment.cs
index 1b3ca8004..6f2eb9ba2 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/StubEnvironment.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/StubEnvironment.cs
@@ -30,10 +30,10 @@ namespace System.Diagnostics.Tracing.Internal
if (fmt != null)
return string.Format(fmt, args);
- string sargs = String.Empty;
+ string sargs = string.Empty;
foreach(var arg in args)
{
- if (sargs != String.Empty)
+ if (sargs != string.Empty)
sargs += ", ";
sargs += arg.ToString();
}
@@ -301,7 +301,7 @@ namespace Microsoft.Reflection
else if (type == typeof(float)) return TypeCode.Single;
else if (type == typeof(double)) return TypeCode.Double;
else if (type == typeof(DateTime)) return TypeCode.DateTime;
- else if (type == (typeof(Decimal))) return TypeCode.Decimal;
+ else if (type == (typeof(decimal))) return TypeCode.Decimal;
else return TypeCode.Object;
}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/DataCollector.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/DataCollector.cs
index 1444c267c..11c18a260 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/DataCollector.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/DataCollector.cs
@@ -143,6 +143,45 @@ namespace System.Diagnostics.Tracing
}
}
+ internal unsafe void AddNullTerminatedString(string value)
+ {
+ // Treat null strings as empty strings.
+ if (value == null)
+ {
+ value = string.Empty;
+ }
+
+ // Calculate the size of the string including the trailing NULL char.
+ // Don't use value.Length here because string allows for embedded NULL characters.
+ int nullCharIndex = value.IndexOf((char)0);
+ if (nullCharIndex < 0)
+ {
+ nullCharIndex = value.Length;
+ }
+ int size = (nullCharIndex + 1) * 2;
+
+ if (this.bufferNesting != 0)
+ {
+ this.EnsureBuffer(size);
+ }
+
+ if (this.bufferNesting == 0)
+ {
+ this.ScalarsEnd();
+ this.PinArray(value, size);
+ }
+ else
+ {
+ var oldPos = this.bufferPos;
+ this.bufferPos = checked(this.bufferPos + size);
+ this.EnsureBuffer();
+ fixed (void* p = value)
+ {
+ Marshal.Copy((IntPtr)p, buffer, oldPos, size);
+ }
+ }
+ }
+
internal void AddBinary(Array value, int size)
{
this.AddArray(value, size, 1);
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventPayload.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventPayload.cs
index 30a941195..3febe6ff9 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventPayload.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventPayload.cs
@@ -144,7 +144,7 @@ namespace System.Diagnostics.Tracing
position++;
}
- value = default(object);
+ value = default;
return false;
}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventSourceActivity.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventSourceActivity.cs
index 865082f76..2d7155080 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventSourceActivity.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/EventSourceActivity.cs
@@ -314,7 +314,7 @@ namespace System.Diagnostics.Tracing
private State state;
private string eventName;
- static internal Guid s_empty;
+ internal static Guid s_empty;
#endregion
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/FieldMetadata.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/FieldMetadata.cs
index 9c7c6369e..f15373475 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/FieldMetadata.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/FieldMetadata.cs
@@ -135,13 +135,11 @@ namespace System.Diagnostics.Tracing
{
throw new NotSupportedException(SR.EventSource_NotSupportedArrayOfBinary);
}
-#if !BROKEN_UNTIL_M3
if (coreType == (int)TraceLoggingDataType.Utf16String ||
coreType == (int)TraceLoggingDataType.MbcsString)
{
throw new NotSupportedException(SR.EventSource_NotSupportedArrayOfNullTerminatedString);
}
-#endif
}
if (((int)this.tags & 0xfffffff) != 0)
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/InvokeTypeInfo.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/InvokeTypeInfo.cs
index 3e5997bc9..2a7113e5d 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/InvokeTypeInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/InvokeTypeInfo.cs
@@ -21,7 +21,7 @@ namespace System.Diagnostics.Tracing
/// </typeparam>
internal sealed class InvokeTypeInfo : TraceLoggingTypeInfo
{
- private readonly PropertyAnalysis[] properties;
+ internal readonly PropertyAnalysis[] properties;
public InvokeTypeInfo(
Type type,
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/NameInfo.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/NameInfo.cs
index 668043ae6..a7daf5e75 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/NameInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/NameInfo.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
+using System.Collections.Concurrent;
using Interlocked = System.Threading.Interlocked;
#if ES_BUILD_STANDALONE
@@ -75,5 +76,50 @@ namespace System.Diagnostics.Tracing
}
return result;
}
+
+#if FEATURE_PERFTRACING
+ public IntPtr GetOrCreateEventHandle(EventProvider provider, TraceLoggingEventHandleTable eventHandleTable, EventDescriptor descriptor, TraceLoggingEventTypes eventTypes)
+ {
+ IntPtr eventHandle;
+ if ((eventHandle = eventHandleTable[descriptor.EventId]) == IntPtr.Zero)
+ {
+ lock (eventHandleTable)
+ {
+ if ((eventHandle = eventHandleTable[descriptor.EventId]) == IntPtr.Zero)
+ {
+ byte[] metadataBlob = EventPipeMetadataGenerator.Instance.GenerateEventMetadata(
+ descriptor.EventId,
+ name,
+ (EventKeywords)descriptor.Keywords,
+ (EventLevel)descriptor.Level,
+ descriptor.Version,
+ eventTypes);
+ uint metadataLength = (metadataBlob != null) ? (uint)metadataBlob.Length : 0;
+
+ unsafe
+ {
+ fixed (byte* pMetadataBlob = metadataBlob)
+ {
+ // Define the event.
+ eventHandle = provider.m_eventProvider.DefineEventHandle(
+ (uint)descriptor.EventId,
+ name,
+ descriptor.Keywords,
+ descriptor.Version,
+ descriptor.Level,
+ pMetadataBlob,
+ metadataLength);
+ }
+ }
+
+ // Cache the event handle.
+ eventHandleTable.SetEventHandle(descriptor.EventId, eventHandle);
+ }
+ }
+ }
+
+ return eventHandle;
+ }
+#endif
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/PropertyValue.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/PropertyValue.cs
index ae6088849..daa6d9736 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/PropertyValue.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/PropertyValue.cs
@@ -40,33 +40,33 @@ namespace System.Diagnostics.Tracing
public struct Scalar
{
[FieldOffset(0)]
- public Boolean AsBoolean;
+ public bool AsBoolean;
[FieldOffset(0)]
- public Byte AsByte;
+ public byte AsByte;
[FieldOffset(0)]
- public SByte AsSByte;
+ public sbyte AsSByte;
[FieldOffset(0)]
- public Char AsChar;
+ public char AsChar;
[FieldOffset(0)]
- public Int16 AsInt16;
+ public short AsInt16;
[FieldOffset(0)]
- public UInt16 AsUInt16;
+ public ushort AsUInt16;
[FieldOffset(0)]
- public Int32 AsInt32;
+ public int AsInt32;
[FieldOffset(0)]
- public UInt32 AsUInt32;
+ public uint AsUInt32;
[FieldOffset(0)]
- public Int64 AsInt64;
+ public long AsInt64;
[FieldOffset(0)]
- public UInt64 AsUInt64;
+ public ulong AsUInt64;
[FieldOffset(0)]
public IntPtr AsIntPtr;
[FieldOffset(0)]
public UIntPtr AsUIntPtr;
[FieldOffset(0)]
- public Single AsSingle;
+ public float AsSingle;
[FieldOffset(0)]
- public Double AsDouble;
+ public double AsDouble;
[FieldOffset(0)]
public Guid AsGuid;
[FieldOffset(0)]
@@ -76,7 +76,7 @@ namespace System.Diagnostics.Tracing
[FieldOffset(0)]
public TimeSpan AsTimeSpan;
[FieldOffset(0)]
- public Decimal AsDecimal;
+ public decimal AsDecimal;
}
// Anything not covered by the Scalar union gets stored in this reference.
@@ -87,7 +87,7 @@ namespace System.Diagnostics.Tracing
private PropertyValue(object value)
{
_reference = value;
- _scalar = default(Scalar);
+ _scalar = default;
_scalarLength = 0;
}
@@ -98,47 +98,47 @@ namespace System.Diagnostics.Tracing
_scalarLength = scalarLength;
}
- private PropertyValue(Boolean value) : this(new Scalar() { AsBoolean = value }, sizeof(Boolean)) { }
- private PropertyValue(Byte value) : this(new Scalar() { AsByte = value }, sizeof(Byte)) { }
- private PropertyValue(SByte value) : this(new Scalar() { AsSByte = value }, sizeof(SByte)) { }
- private PropertyValue(Char value) : this(new Scalar() { AsChar = value }, sizeof(Char)) { }
- private PropertyValue(Int16 value) : this(new Scalar() { AsInt16 = value }, sizeof(Int16)) { }
- private PropertyValue(UInt16 value) : this(new Scalar() { AsUInt16 = value }, sizeof(UInt16)) { }
- private PropertyValue(Int32 value) : this(new Scalar() { AsInt32 = value }, sizeof(Int32)) { }
- private PropertyValue(UInt32 value) : this(new Scalar() { AsUInt32 = value }, sizeof(UInt32)) { }
- private PropertyValue(Int64 value) : this(new Scalar() { AsInt64 = value }, sizeof(Int64)) { }
- private PropertyValue(UInt64 value) : this(new Scalar() { AsUInt64 = value }, sizeof(UInt64)) { }
+ private PropertyValue(bool value) : this(new Scalar() { AsBoolean = value }, sizeof(bool)) { }
+ private PropertyValue(byte value) : this(new Scalar() { AsByte = value }, sizeof(byte)) { }
+ private PropertyValue(sbyte value) : this(new Scalar() { AsSByte = value }, sizeof(sbyte)) { }
+ private PropertyValue(char value) : this(new Scalar() { AsChar = value }, sizeof(char)) { }
+ private PropertyValue(short value) : this(new Scalar() { AsInt16 = value }, sizeof(short)) { }
+ private PropertyValue(ushort value) : this(new Scalar() { AsUInt16 = value }, sizeof(ushort)) { }
+ private PropertyValue(int value) : this(new Scalar() { AsInt32 = value }, sizeof(int)) { }
+ private PropertyValue(uint value) : this(new Scalar() { AsUInt32 = value }, sizeof(uint)) { }
+ private PropertyValue(long value) : this(new Scalar() { AsInt64 = value }, sizeof(long)) { }
+ private PropertyValue(ulong value) : this(new Scalar() { AsUInt64 = value }, sizeof(ulong)) { }
private PropertyValue(IntPtr value) : this(new Scalar() { AsIntPtr = value }, sizeof(IntPtr)) { }
private PropertyValue(UIntPtr value) : this(new Scalar() { AsUIntPtr = value }, sizeof(UIntPtr)) { }
- private PropertyValue(Single value) : this(new Scalar() { AsSingle = value }, sizeof(Single)) { }
- private PropertyValue(Double value) : this(new Scalar() { AsDouble = value }, sizeof(Double)) { }
+ private PropertyValue(float value) : this(new Scalar() { AsSingle = value }, sizeof(float)) { }
+ private PropertyValue(double value) : this(new Scalar() { AsDouble = value }, sizeof(double)) { }
private PropertyValue(Guid value) : this(new Scalar() { AsGuid = value }, sizeof(Guid)) { }
private PropertyValue(DateTime value) : this(new Scalar() { AsDateTime = value }, sizeof(DateTime)) { }
private PropertyValue(DateTimeOffset value) : this(new Scalar() { AsDateTimeOffset = value }, sizeof(DateTimeOffset)) { }
private PropertyValue(TimeSpan value) : this(new Scalar() { AsTimeSpan = value }, sizeof(TimeSpan)) { }
- private PropertyValue(Decimal value) : this(new Scalar() { AsDecimal = value }, sizeof(Decimal)) { }
+ private PropertyValue(decimal value) : this(new Scalar() { AsDecimal = value }, sizeof(decimal)) { }
public static Func<object, PropertyValue> GetFactory(Type type)
{
- if (type == typeof(Boolean)) return value => new PropertyValue((Boolean)value);
- if (type == typeof(Byte)) return value => new PropertyValue((Byte)value);
- if (type == typeof(SByte)) return value => new PropertyValue((SByte)value);
- if (type == typeof(Char)) return value => new PropertyValue((Char)value);
- if (type == typeof(Int16)) return value => new PropertyValue((Int16)value);
- if (type == typeof(UInt16)) return value => new PropertyValue((UInt16)value);
- if (type == typeof(Int32)) return value => new PropertyValue((Int32)value);
- if (type == typeof(UInt32)) return value => new PropertyValue((UInt32)value);
- if (type == typeof(Int64)) return value => new PropertyValue((Int64)value);
- if (type == typeof(UInt64)) return value => new PropertyValue((UInt64)value);
+ if (type == typeof(bool)) return value => new PropertyValue((bool)value);
+ if (type == typeof(byte)) return value => new PropertyValue((byte)value);
+ if (type == typeof(sbyte)) return value => new PropertyValue((sbyte)value);
+ if (type == typeof(char)) return value => new PropertyValue((char)value);
+ if (type == typeof(short)) return value => new PropertyValue((short)value);
+ if (type == typeof(ushort)) return value => new PropertyValue((ushort)value);
+ if (type == typeof(int)) return value => new PropertyValue((int)value);
+ if (type == typeof(uint)) return value => new PropertyValue((uint)value);
+ if (type == typeof(long)) return value => new PropertyValue((long)value);
+ if (type == typeof(ulong)) return value => new PropertyValue((ulong)value);
if (type == typeof(IntPtr)) return value => new PropertyValue((IntPtr)value);
if (type == typeof(UIntPtr)) return value => new PropertyValue((UIntPtr)value);
- if (type == typeof(Single)) return value => new PropertyValue((Single)value);
- if (type == typeof(Double)) return value => new PropertyValue((Double)value);
+ if (type == typeof(float)) return value => new PropertyValue((float)value);
+ if (type == typeof(double)) return value => new PropertyValue((double)value);
if (type == typeof(Guid)) return value => new PropertyValue((Guid)value);
if (type == typeof(DateTime)) return value => new PropertyValue((DateTime)value);
if (type == typeof(DateTimeOffset)) return value => new PropertyValue((DateTimeOffset)value);
if (type == typeof(TimeSpan)) return value => new PropertyValue((TimeSpan)value);
- if (type == typeof(Decimal)) return value => new PropertyValue((Decimal)value);
+ if (type == typeof(decimal)) return value => new PropertyValue((decimal)value);
return value => new PropertyValue(value);
}
@@ -249,25 +249,25 @@ namespace System.Diagnostics.Tracing
if (type.GetTypeInfo().IsEnum)
type = Enum.GetUnderlyingType(type);
- if (type == typeof(Boolean)) { var f = (Func<TContainer, Boolean>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(Byte)) { var f = (Func<TContainer, Byte>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(SByte)) { var f = (Func<TContainer, SByte>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(Char)) { var f = (Func<TContainer, Char>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(Int16)) { var f = (Func<TContainer, Int16>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(UInt16)) { var f = (Func<TContainer, UInt16>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(Int32)) { var f = (Func<TContainer, Int32>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(UInt32)) { var f = (Func<TContainer, UInt32>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(Int64)) { var f = (Func<TContainer, Int64>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(UInt64)) { var f = (Func<TContainer, UInt64>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(bool)) { var f = (Func<TContainer, bool>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(byte)) { var f = (Func<TContainer, byte>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(sbyte)) { var f = (Func<TContainer, sbyte>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(char)) { var f = (Func<TContainer, char>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(short)) { var f = (Func<TContainer, short>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(ushort)) { var f = (Func<TContainer, ushort>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(int)) { var f = (Func<TContainer, int>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(uint)) { var f = (Func<TContainer, uint>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(long)) { var f = (Func<TContainer, long>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(ulong)) { var f = (Func<TContainer, ulong>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
if (type == typeof(IntPtr)) { var f = (Func<TContainer, IntPtr>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
if (type == typeof(UIntPtr)) { var f = (Func<TContainer, UIntPtr>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(Single)) { var f = (Func<TContainer, Single>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(Double)) { var f = (Func<TContainer, Double>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(float)) { var f = (Func<TContainer, float>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(double)) { var f = (Func<TContainer, double>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
if (type == typeof(Guid)) { var f = (Func<TContainer, Guid>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
if (type == typeof(DateTime)) { var f = (Func<TContainer, DateTime>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
if (type == typeof(DateTimeOffset)) { var f = (Func<TContainer, DateTimeOffset>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
if (type == typeof(TimeSpan)) { var f = (Func<TContainer, TimeSpan>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
- if (type == typeof(Decimal)) { var f = (Func<TContainer, Decimal>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(decimal)) { var f = (Func<TContainer, decimal>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
return container => new PropertyValue(property.GetValue(container.ReferenceValue));
}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs
index 9b58d8251..e0a937479 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs
@@ -73,20 +73,20 @@ namespace System.Diagnostics.Tracing
collector.AddScalar(value);
}
- public static TraceLoggingTypeInfo Boolean() { return new ScalarTypeInfo(typeof(Boolean), Statics.Format8, TraceLoggingDataType.Boolean8); }
- public static TraceLoggingTypeInfo Byte() { return new ScalarTypeInfo(typeof(Byte), Statics.Format8, TraceLoggingDataType.UInt8); }
- public static TraceLoggingTypeInfo SByte() { return new ScalarTypeInfo(typeof(SByte), Statics.Format8, TraceLoggingDataType.Int8); }
- public static TraceLoggingTypeInfo Char() { return new ScalarTypeInfo(typeof(Char), Statics.Format16, TraceLoggingDataType.Char16); }
- public static TraceLoggingTypeInfo Int16() { return new ScalarTypeInfo(typeof(Int16), Statics.Format16, TraceLoggingDataType.Int16); }
- public static TraceLoggingTypeInfo UInt16() { return new ScalarTypeInfo(typeof(UInt16), Statics.Format16, TraceLoggingDataType.UInt16); }
- public static TraceLoggingTypeInfo Int32() { return new ScalarTypeInfo(typeof(Int32), Statics.Format32, TraceLoggingDataType.Int32); }
- public static TraceLoggingTypeInfo UInt32() { return new ScalarTypeInfo(typeof(UInt32), Statics.Format32, TraceLoggingDataType.UInt32); }
- public static TraceLoggingTypeInfo Int64() { return new ScalarTypeInfo(typeof(Int64), Statics.Format64, TraceLoggingDataType.Int64); }
- public static TraceLoggingTypeInfo UInt64() { return new ScalarTypeInfo(typeof(UInt64), Statics.Format64, TraceLoggingDataType.UInt64); }
+ public static TraceLoggingTypeInfo Boolean() { return new ScalarTypeInfo(typeof(bool), Statics.Format8, TraceLoggingDataType.Boolean8); }
+ public static TraceLoggingTypeInfo Byte() { return new ScalarTypeInfo(typeof(byte), Statics.Format8, TraceLoggingDataType.UInt8); }
+ public static TraceLoggingTypeInfo SByte() { return new ScalarTypeInfo(typeof(sbyte), Statics.Format8, TraceLoggingDataType.Int8); }
+ public static TraceLoggingTypeInfo Char() { return new ScalarTypeInfo(typeof(char), Statics.Format16, TraceLoggingDataType.Char16); }
+ public static TraceLoggingTypeInfo Int16() { return new ScalarTypeInfo(typeof(short), Statics.Format16, TraceLoggingDataType.Int16); }
+ public static TraceLoggingTypeInfo UInt16() { return new ScalarTypeInfo(typeof(ushort), Statics.Format16, TraceLoggingDataType.UInt16); }
+ public static TraceLoggingTypeInfo Int32() { return new ScalarTypeInfo(typeof(int), Statics.Format32, TraceLoggingDataType.Int32); }
+ public static TraceLoggingTypeInfo UInt32() { return new ScalarTypeInfo(typeof(uint), Statics.Format32, TraceLoggingDataType.UInt32); }
+ public static TraceLoggingTypeInfo Int64() { return new ScalarTypeInfo(typeof(long), Statics.Format64, TraceLoggingDataType.Int64); }
+ public static TraceLoggingTypeInfo UInt64() { return new ScalarTypeInfo(typeof(ulong), Statics.Format64, TraceLoggingDataType.UInt64); }
public static TraceLoggingTypeInfo IntPtr() { return new ScalarTypeInfo(typeof(IntPtr), Statics.FormatPtr, Statics.IntPtrType); }
public static TraceLoggingTypeInfo UIntPtr() { return new ScalarTypeInfo(typeof(UIntPtr), Statics.FormatPtr, Statics.UIntPtrType); }
- public static TraceLoggingTypeInfo Single() { return new ScalarTypeInfo(typeof(Single), Statics.Format32, TraceLoggingDataType.Float); }
- public static TraceLoggingTypeInfo Double() { return new ScalarTypeInfo(typeof(Double), Statics.Format64, TraceLoggingDataType.Double); }
+ public static TraceLoggingTypeInfo Single() { return new ScalarTypeInfo(typeof(float), Statics.Format32, TraceLoggingDataType.Float); }
+ public static TraceLoggingTypeInfo Double() { return new ScalarTypeInfo(typeof(double), Statics.Format64, TraceLoggingDataType.Double); }
public static TraceLoggingTypeInfo Guid() { return new ScalarTypeInfo(typeof(Guid), (f, t) => Statics.MakeDataType(TraceLoggingDataType.Guid, f), TraceLoggingDataType.Guid); }
}
@@ -122,21 +122,21 @@ namespace System.Diagnostics.Tracing
collector.AddArray(value, elementSize);
}
- public static TraceLoggingTypeInfo Boolean() { return new ScalarArrayTypeInfo(typeof(Boolean[]), Statics.Format8, TraceLoggingDataType.Boolean8, sizeof(Boolean)); }
- public static TraceLoggingTypeInfo Byte() { return new ScalarArrayTypeInfo(typeof(Byte[]), Statics.Format8, TraceLoggingDataType.UInt8, sizeof(Byte)); }
- public static TraceLoggingTypeInfo SByte() { return new ScalarArrayTypeInfo(typeof(SByte[]), Statics.Format8, TraceLoggingDataType.Int8, sizeof(SByte)); }
- public static TraceLoggingTypeInfo Char() { return new ScalarArrayTypeInfo(typeof(Char[]), Statics.Format16, TraceLoggingDataType.Char16, sizeof(Char)); }
- public static TraceLoggingTypeInfo Int16() { return new ScalarArrayTypeInfo(typeof(Int16[]), Statics.Format16, TraceLoggingDataType.Int16, sizeof(Int16)); }
- public static TraceLoggingTypeInfo UInt16() { return new ScalarArrayTypeInfo(typeof(UInt16[]), Statics.Format16, TraceLoggingDataType.UInt16, sizeof(UInt16)); }
- public static TraceLoggingTypeInfo Int32() { return new ScalarArrayTypeInfo(typeof(Int32[]), Statics.Format32, TraceLoggingDataType.Int32, sizeof(Int32)); }
- public static TraceLoggingTypeInfo UInt32() { return new ScalarArrayTypeInfo(typeof(UInt32[]), Statics.Format32, TraceLoggingDataType.UInt32, sizeof(UInt32)); }
- public static TraceLoggingTypeInfo Int64() { return new ScalarArrayTypeInfo(typeof(Int64[]), Statics.Format64, TraceLoggingDataType.Int64, sizeof(Int64)); }
- public static TraceLoggingTypeInfo UInt64() { return new ScalarArrayTypeInfo(typeof(UInt64[]), Statics.Format64, TraceLoggingDataType.UInt64, sizeof(UInt64)); }
+ public static TraceLoggingTypeInfo Boolean() { return new ScalarArrayTypeInfo(typeof(bool[]), Statics.Format8, TraceLoggingDataType.Boolean8, sizeof(bool)); }
+ public static TraceLoggingTypeInfo Byte() { return new ScalarArrayTypeInfo(typeof(byte[]), Statics.Format8, TraceLoggingDataType.UInt8, sizeof(byte)); }
+ public static TraceLoggingTypeInfo SByte() { return new ScalarArrayTypeInfo(typeof(sbyte[]), Statics.Format8, TraceLoggingDataType.Int8, sizeof(sbyte)); }
+ public static TraceLoggingTypeInfo Char() { return new ScalarArrayTypeInfo(typeof(char[]), Statics.Format16, TraceLoggingDataType.Char16, sizeof(char)); }
+ public static TraceLoggingTypeInfo Int16() { return new ScalarArrayTypeInfo(typeof(short[]), Statics.Format16, TraceLoggingDataType.Int16, sizeof(short)); }
+ public static TraceLoggingTypeInfo UInt16() { return new ScalarArrayTypeInfo(typeof(ushort[]), Statics.Format16, TraceLoggingDataType.UInt16, sizeof(ushort)); }
+ public static TraceLoggingTypeInfo Int32() { return new ScalarArrayTypeInfo(typeof(int[]), Statics.Format32, TraceLoggingDataType.Int32, sizeof(int)); }
+ public static TraceLoggingTypeInfo UInt32() { return new ScalarArrayTypeInfo(typeof(uint[]), Statics.Format32, TraceLoggingDataType.UInt32, sizeof(uint)); }
+ public static TraceLoggingTypeInfo Int64() { return new ScalarArrayTypeInfo(typeof(long[]), Statics.Format64, TraceLoggingDataType.Int64, sizeof(long)); }
+ public static TraceLoggingTypeInfo UInt64() { return new ScalarArrayTypeInfo(typeof(ulong[]), Statics.Format64, TraceLoggingDataType.UInt64, sizeof(ulong)); }
public static TraceLoggingTypeInfo IntPtr() { return new ScalarArrayTypeInfo(typeof(IntPtr[]), Statics.FormatPtr, Statics.IntPtrType, System.IntPtr.Size); }
public static TraceLoggingTypeInfo UIntPtr() { return new ScalarArrayTypeInfo(typeof(UIntPtr[]), Statics.FormatPtr, Statics.UIntPtrType, System.IntPtr.Size); }
- public static TraceLoggingTypeInfo Single() { return new ScalarArrayTypeInfo(typeof(Single[]), Statics.Format32, TraceLoggingDataType.Float, sizeof(Single)); }
- public static TraceLoggingTypeInfo Double() { return new ScalarArrayTypeInfo(typeof(Double[]), Statics.Format64, TraceLoggingDataType.Double, sizeof(Double)); }
- public unsafe static TraceLoggingTypeInfo Guid() { return new ScalarArrayTypeInfo(typeof(Guid), (f, t) => Statics.MakeDataType(TraceLoggingDataType.Guid, f), TraceLoggingDataType.Guid, sizeof(Guid)); }
+ public static TraceLoggingTypeInfo Single() { return new ScalarArrayTypeInfo(typeof(float[]), Statics.Format32, TraceLoggingDataType.Float, sizeof(float)); }
+ public static TraceLoggingTypeInfo Double() { return new ScalarArrayTypeInfo(typeof(double[]), Statics.Format64, TraceLoggingDataType.Double, sizeof(double)); }
+ public static unsafe TraceLoggingTypeInfo Guid() { return new ScalarArrayTypeInfo(typeof(Guid), (f, t) => Statics.MakeDataType(TraceLoggingDataType.Guid, f), TraceLoggingDataType.Guid, sizeof(Guid)); }
}
/// <summary>
@@ -151,12 +151,12 @@ namespace System.Diagnostics.Tracing
string name,
EventFieldFormat format)
{
- collector.AddBinary(name, Statics.MakeDataType(TraceLoggingDataType.CountedUtf16String, format));
+ collector.AddNullTerminatedString(name, Statics.MakeDataType(TraceLoggingDataType.Utf16String, format));
}
public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
{
- collector.AddBinary((string)value.ReferenceValue);
+ collector.AddNullTerminatedString((string)value.ReferenceValue);
}
public override object GetData(object value)
@@ -243,11 +243,11 @@ namespace System.Diagnostics.Tracing
}
/// <summary>
- /// TraceLogging: Type handler for Decimal. (Note: not full-fidelity, exposed as Double.)
+ /// TraceLogging: Type handler for decimal. (Note: not full-fidelity, exposed as Double.)
/// </summary>
internal sealed class DecimalTypeInfo : TraceLoggingTypeInfo
{
- public DecimalTypeInfo() : base(typeof(Decimal)) { }
+ public DecimalTypeInfo() : base(typeof(decimal)) { }
public override void WriteMetadata(
TraceLoggingMetadataCollector collector,
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/Statics.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/Statics.cs
index 05539ab4f..0c2167213 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/Statics.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/Statics.cs
@@ -548,51 +548,51 @@ namespace System.Diagnostics.Tracing
else if (dataType.IsArray)
{
var elementType = dataType.GetElementType();
- if (elementType == typeof(Boolean))
+ if (elementType == typeof(bool))
{
result = ScalarArrayTypeInfo.Boolean();
}
- else if (elementType == typeof(Byte))
+ else if (elementType == typeof(byte))
{
result = ScalarArrayTypeInfo.Byte();
}
- else if (elementType == typeof(SByte))
+ else if (elementType == typeof(sbyte))
{
result = ScalarArrayTypeInfo.SByte();
}
- else if (elementType == typeof(Int16))
+ else if (elementType == typeof(short))
{
result = ScalarArrayTypeInfo.Int16();
}
- else if (elementType == typeof(UInt16))
+ else if (elementType == typeof(ushort))
{
result = ScalarArrayTypeInfo.UInt16();
}
- else if (elementType == typeof(Int32))
+ else if (elementType == typeof(int))
{
result = ScalarArrayTypeInfo.Int32();
}
- else if (elementType == typeof(UInt32))
+ else if (elementType == typeof(uint))
{
result = ScalarArrayTypeInfo.UInt32();
}
- else if (elementType == typeof(Int64))
+ else if (elementType == typeof(long))
{
result = ScalarArrayTypeInfo.Int64();
}
- else if (elementType == typeof(UInt64))
+ else if (elementType == typeof(ulong))
{
result = ScalarArrayTypeInfo.UInt64();
}
- else if (elementType == typeof(Char))
+ else if (elementType == typeof(char))
{
result = ScalarArrayTypeInfo.Char();
}
- else if (elementType == typeof(Double))
+ else if (elementType == typeof(double))
{
result = ScalarArrayTypeInfo.Double();
}
- else if (elementType == typeof(Single))
+ else if (elementType == typeof(float))
{
result = ScalarArrayTypeInfo.Single();
}
@@ -618,55 +618,55 @@ namespace System.Diagnostics.Tracing
if (Statics.IsEnum(dataType))
dataType = Enum.GetUnderlyingType(dataType);
- if (dataType == typeof(String))
+ if (dataType == typeof(string))
{
result = new StringTypeInfo();
}
- else if (dataType == typeof(Boolean))
+ else if (dataType == typeof(bool))
{
result = ScalarTypeInfo.Boolean();
}
- else if (dataType == typeof(Byte))
+ else if (dataType == typeof(byte))
{
result = ScalarTypeInfo.Byte();
}
- else if (dataType == typeof(SByte))
+ else if (dataType == typeof(sbyte))
{
result = ScalarTypeInfo.SByte();
}
- else if (dataType == typeof(Int16))
+ else if (dataType == typeof(short))
{
result = ScalarTypeInfo.Int16();
}
- else if (dataType == typeof(UInt16))
+ else if (dataType == typeof(ushort))
{
result = ScalarTypeInfo.UInt16();
}
- else if (dataType == typeof(Int32))
+ else if (dataType == typeof(int))
{
result = ScalarTypeInfo.Int32();
}
- else if (dataType == typeof(UInt32))
+ else if (dataType == typeof(uint))
{
result = ScalarTypeInfo.UInt32();
}
- else if (dataType == typeof(Int64))
+ else if (dataType == typeof(long))
{
result = ScalarTypeInfo.Int64();
}
- else if (dataType == typeof(UInt64))
+ else if (dataType == typeof(ulong))
{
result = ScalarTypeInfo.UInt64();
}
- else if (dataType == typeof(Char))
+ else if (dataType == typeof(char))
{
result = ScalarTypeInfo.Char();
}
- else if (dataType == typeof(Double))
+ else if (dataType == typeof(double))
{
result = ScalarTypeInfo.Double();
}
- else if (dataType == typeof(Single))
+ else if (dataType == typeof(float))
{
result = ScalarTypeInfo.Single();
}
@@ -674,7 +674,7 @@ namespace System.Diagnostics.Tracing
{
result = new DateTimeTypeInfo();
}
- else if (dataType == typeof(Decimal))
+ else if (dataType == typeof(decimal))
{
result = new DecimalTypeInfo();
}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingDataCollector.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingDataCollector.cs
index 04a047fb3..f6d0a59aa 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingDataCollector.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingDataCollector.cs
@@ -85,6 +85,17 @@ namespace System.Diagnostics.Tracing
}
/// <summary>
+ /// Adds a null-terminated String value to the event payload.
+ /// </summary>
+ /// <param name="value">
+ /// Value to be added. A null value is treated as a zero-length string.
+ /// </param>
+ public void AddNullTerminatedString(string value)
+ {
+ DataCollector.ThreadInstance.AddNullTerminatedString(value);
+ }
+
+ /// <summary>
/// Adds a counted String value to the event payload.
/// </summary>
/// <param name="value">
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs
index 4348df7d6..0553f9899 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventSource.cs
@@ -47,6 +47,10 @@ namespace System.Diagnostics.Tracing
private byte[] providerMetadata;
#endif
+#if FEATURE_PERFTRACING
+ private readonly TraceLoggingEventHandleTable m_eventHandleTable = new TraceLoggingEventHandleTable();
+#endif
+
/// <summary>
/// Construct an EventSource with a given name for non-contract based events (e.g. those using the Write() API).
/// </summary>
@@ -431,15 +435,22 @@ namespace System.Diagnostics.Tracing
identity = nameInfo.identity;
EventDescriptor descriptor = new EventDescriptor(identity, level, opcode, (long)keywords);
+#if FEATURE_PERFTRACING
+ IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_eventPipeProvider, m_eventHandleTable, descriptor, eventTypes);
+ Debug.Assert(eventHandle != IntPtr.Zero);
+#else
+ IntPtr eventHandle = IntPtr.Zero;
+#endif
+
var pinCount = eventTypes.pinCount;
var scratch = stackalloc byte[eventTypes.scratchSize];
var descriptors = stackalloc EventData[eventTypes.dataCount + 3];
for(int i = 0; i < eventTypes.dataCount + 3; i++)
- descriptors[i] = default(EventData);
+ descriptors[i] = default;
var pins = stackalloc GCHandle[pinCount];
for (int i = 0; i < pinCount; i++)
- pins[i] = default(GCHandle);
+ pins[i] = default;
fixed (byte*
pMetadata0 = this.providerMetadata,
@@ -472,6 +483,7 @@ namespace System.Diagnostics.Tracing
this.WriteEventRaw(
eventName,
ref descriptor,
+ eventHandle,
activityID,
childActivityID,
(int)(DataCollector.ThreadInstance.Finish() - descriptors),
@@ -538,12 +550,19 @@ namespace System.Diagnostics.Tracing
return;
}
+#if FEATURE_PERFTRACING
+ IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_eventPipeProvider, m_eventHandleTable, descriptor, eventTypes);
+ Debug.Assert(eventHandle != IntPtr.Zero);
+#else
+ IntPtr eventHandle = IntPtr.Zero;
+#endif
+
// We make a descriptor for each EventData, and because we morph strings to counted strings
// we may have 2 for each arg, so we allocate enough for this.
var descriptorsLength = eventTypes.dataCount + eventTypes.typeInfos.Length * 2 + 3;
var descriptors = stackalloc EventData[descriptorsLength];
for(int i = 0; i < descriptorsLength; i++)
- descriptors[i] = default(EventData);
+ descriptors[i] = default;
fixed (byte*
pMetadata0 = this.providerMetadata,
@@ -557,35 +576,20 @@ namespace System.Diagnostics.Tracing
for (int i = 0; i < eventTypes.typeInfos.Length; i++)
{
- // Until M3, we need to morph strings to a counted representation
- // When TDH supports null terminated strings, we can remove this.
- if (eventTypes.typeInfos[i].DataType == typeof(string))
- {
- // Write out the size of the string
- descriptors[numDescrs].DataPointer = (IntPtr) (&descriptors[numDescrs + 1].m_Size);
- descriptors[numDescrs].m_Size = 2;
- numDescrs++;
-
- descriptors[numDescrs].m_Ptr = data[i].m_Ptr;
- descriptors[numDescrs].m_Size = data[i].m_Size - 2; // Remove the null terminator
- numDescrs++;
- }
- else
- {
- descriptors[numDescrs].m_Ptr = data[i].m_Ptr;
- descriptors[numDescrs].m_Size = data[i].m_Size;
+ descriptors[numDescrs].m_Ptr = data[i].m_Ptr;
+ descriptors[numDescrs].m_Size = data[i].m_Size;
- // old conventions for bool is 4 bytes, but meta-data assumes 1.
- if (data[i].m_Size == 4 && eventTypes.typeInfos[i].DataType == typeof(bool))
- descriptors[numDescrs].m_Size = 1;
+ // old conventions for bool is 4 bytes, but meta-data assumes 1.
+ if (data[i].m_Size == 4 && eventTypes.typeInfos[i].DataType == typeof(bool))
+ descriptors[numDescrs].m_Size = 1;
- numDescrs++;
- }
+ numDescrs++;
}
this.WriteEventRaw(
eventName,
ref descriptor,
+ eventHandle,
activityID,
childActivityID,
numDescrs,
@@ -615,16 +619,23 @@ namespace System.Diagnostics.Tracing
return;
}
+#if FEATURE_PERFTRACING
+ IntPtr eventHandle = nameInfo.GetOrCreateEventHandle(m_eventPipeProvider, m_eventHandleTable, descriptor, eventTypes);
+ Debug.Assert(eventHandle != IntPtr.Zero);
+#else
+ IntPtr eventHandle = IntPtr.Zero;
+#endif
+
#if FEATURE_MANAGED_ETW
var pinCount = eventTypes.pinCount;
var scratch = stackalloc byte[eventTypes.scratchSize];
var descriptors = stackalloc EventData[eventTypes.dataCount + 3];
for(int i=0; i<eventTypes.dataCount + 3; i++)
- descriptors[i] = default(EventData);
+ descriptors[i] = default;
var pins = stackalloc GCHandle[pinCount];
for (int i = 0; i < pinCount; i++)
- pins[i] = default(GCHandle);
+ pins[i] = default;
fixed (byte*
pMetadata0 = this.providerMetadata,
@@ -637,7 +648,7 @@ namespace System.Diagnostics.Tracing
#endif // FEATURE_MANAGED_ETW
#if (!ES_BUILD_PCL && !ES_BUILD_PN)
- System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions();
+ System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions();
#endif
EventOpcode opcode = (EventOpcode)descriptor.Opcode;
@@ -677,6 +688,7 @@ namespace System.Diagnostics.Tracing
this.WriteEventRaw(
eventName,
ref descriptor,
+ eventHandle,
pActivityId,
pRelatedActivityId,
(int)(DataCollector.ThreadInstance.Finish() - descriptors),
@@ -687,7 +699,7 @@ namespace System.Diagnostics.Tracing
if (m_Dispatchers != null)
{
var eventData = (EventPayload)(eventTypes.typeInfos[0].GetData(data));
- WriteToAllListeners(eventName, ref descriptor, nameInfo.tags, pActivityId, eventData);
+ WriteToAllListeners(eventName, ref descriptor, nameInfo.tags, pActivityId, pRelatedActivityId, eventData);
}
}
@@ -716,7 +728,7 @@ namespace System.Diagnostics.Tracing
}
}
- private unsafe void WriteToAllListeners(string eventName, ref EventDescriptor eventDescriptor, EventTags tags, Guid* pActivityId, EventPayload payload)
+ private unsafe void WriteToAllListeners(string eventName, ref EventDescriptor eventDescriptor, EventTags tags, Guid* pActivityId, Guid* pChildActivityId, EventPayload payload)
{
EventWrittenEventArgs eventCallbackArgs = new EventWrittenEventArgs(this);
eventCallbackArgs.EventName = eventName;
@@ -728,7 +740,9 @@ namespace System.Diagnostics.Tracing
// Self described events do not have an id attached. We mark it internally with -1.
eventCallbackArgs.EventId = -1;
if (pActivityId != null)
- eventCallbackArgs.RelatedActivityId = *pActivityId;
+ eventCallbackArgs.ActivityId = *pActivityId;
+ if (pChildActivityId != null)
+ eventCallbackArgs.RelatedActivityId = *pChildActivityId;
if (payload != null)
{
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventTypes.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventTypes.cs
index 3c775a3ce..8887714fd 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventTypes.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventTypes.cs
@@ -25,6 +25,9 @@ namespace System.Diagnostics.Tracing
public class TraceLoggingEventTypes
{
internal readonly TraceLoggingTypeInfo[] typeInfos;
+#if FEATURE_PERFTRACING
+ internal readonly string[] paramNames;
+#endif
internal readonly string name;
internal readonly EventTags tags;
internal readonly byte level;
@@ -98,6 +101,9 @@ namespace System.Diagnostics.Tracing
}
this.typeInfos = MakeArray(paramInfos);
+#if FEATURE_PERFTRACING
+ this.paramNames = MakeParamNameArray(paramInfos);
+#endif
this.name = name;
this.tags = tags;
this.level = Statics.DefaultLevel;
@@ -248,5 +254,19 @@ namespace System.Diagnostics.Tracing
return (TraceLoggingTypeInfo[])typeInfos.Clone(); ;
}
+
+#if FEATURE_PERFTRACING
+ private static string[] MakeParamNameArray(
+ System.Reflection.ParameterInfo[] paramInfos)
+ {
+ string[] paramNames = new string[paramInfos.Length];
+ for (int i = 0; i < paramNames.Length; i++)
+ {
+ paramNames[i] = paramInfos[i].Name;
+ }
+
+ return paramNames;
+ }
+#endif
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingMetadataCollector.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingMetadataCollector.cs
index 1db1a28c9..b5b199dbc 100644
--- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingMetadataCollector.cs
+++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/TraceLogging/TraceLoggingMetadataCollector.cs
@@ -192,22 +192,43 @@ namespace System.Diagnostics.Tracing
}
/// <summary>
+ /// Adds a null-terminated string field to an event.
+ /// Compatible with core types: Utf16String, MbcsString.
+ /// Compatible with dataCollector method: AddNullTerminatedString(string).
+ /// </summary>
+ /// <param name="name">
+ /// The name to use for the added field. This value must not be null.
+ /// </param>
+ /// <param name="type">
+ /// The type code for the added field. This must be a null-terminated string type.
+ /// </param>
+ public void AddNullTerminatedString(string name, TraceLoggingDataType type)
+ {
+ switch ((TraceLoggingDataType)((int)type & Statics.InTypeMask))
+ {
+ case TraceLoggingDataType.Utf16String:
+ break;
+ default:
+ throw new ArgumentOutOfRangeException(nameof(type));
+ }
+
+ this.impl.AddNonscalar();
+ this.AddField(new FieldMetadata(name, type, this.Tags, this.BeginningBufferedArray));
+ }
+
+ /// <summary>
/// Adds an array field to an event.
/// </summary>
/// <param name="name">
/// The name to use for the added field. This value must not be null.
/// </param>
/// <param name="type">
- /// The type code for the added field. This must be a fixed-size type
- /// or a string type. In the case of a string type, this adds an array
- /// of characters, not an array of strings.
+ /// The type code for the added field. This must be a fixed-size type.
/// </param>
public void AddArray(string name, TraceLoggingDataType type)
{
switch ((TraceLoggingDataType)((int)type & Statics.InTypeMask))
{
- case TraceLoggingDataType.Utf16String:
- case TraceLoggingDataType.MbcsString:
case TraceLoggingDataType.Int8:
case TraceLoggingDataType.UInt8:
case TraceLoggingDataType.Int16:
diff --git a/src/System.Private.CoreLib/shared/System/DivideByZeroException.cs b/src/System.Private.CoreLib/shared/System/DivideByZeroException.cs
index b309695ff..27f57414f 100644
--- a/src/System.Private.CoreLib/shared/System/DivideByZeroException.cs
+++ b/src/System.Private.CoreLib/shared/System/DivideByZeroException.cs
@@ -25,13 +25,13 @@ namespace System
HResult = HResults.COR_E_DIVIDEBYZERO;
}
- public DivideByZeroException(String message)
+ public DivideByZeroException(string message)
: base(message)
{
HResult = HResults.COR_E_DIVIDEBYZERO;
}
- public DivideByZeroException(String message, Exception innerException)
+ public DivideByZeroException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_DIVIDEBYZERO;
diff --git a/src/System.Private.CoreLib/shared/System/DllNotFoundException.cs b/src/System.Private.CoreLib/shared/System/DllNotFoundException.cs
index 14fb50d9c..bd29b8b13 100644
--- a/src/System.Private.CoreLib/shared/System/DllNotFoundException.cs
+++ b/src/System.Private.CoreLib/shared/System/DllNotFoundException.cs
@@ -26,13 +26,13 @@ namespace System
HResult = HResults.COR_E_DLLNOTFOUND;
}
- public DllNotFoundException(String message)
+ public DllNotFoundException(string message)
: base(message)
{
HResult = HResults.COR_E_DLLNOTFOUND;
}
- public DllNotFoundException(String message, Exception inner)
+ public DllNotFoundException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_DLLNOTFOUND;
diff --git a/src/System.Private.CoreLib/shared/System/Double.cs b/src/System.Private.CoreLib/shared/System/Double.cs
index 146ee4600..d85b4bca9 100644
--- a/src/System.Private.CoreLib/shared/System/Double.cs
+++ b/src/System.Private.CoreLib/shared/System/Double.cs
@@ -24,9 +24,9 @@ namespace System
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct Double : IComparable, IConvertible, IFormattable, IComparable<Double>, IEquatable<Double>, ISpanFormattable
+ public readonly struct Double : IComparable, IConvertible, IFormattable, IComparable<double>, IEquatable<double>, ISpanFormattable
{
- private double m_value; // Do not rename (binary serialization)
+ private readonly double m_value; // Do not rename (binary serialization)
//
// Public Constants
@@ -47,7 +47,7 @@ namespace System
/// <summary>Determines whether the specified value is finite (zero, subnormal, or normal).</summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe static bool IsFinite(double d)
+ public static unsafe bool IsFinite(double d)
{
var bits = BitConverter.DoubleToInt64Bits(d);
return (bits & 0x7FFFFFFFFFFFFFFF) < 0x7FF0000000000000;
@@ -56,7 +56,7 @@ namespace System
/// <summary>Determines whether the specified value is infinite.</summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe static bool IsInfinity(double d)
+ public static unsafe bool IsInfinity(double d)
{
var bits = BitConverter.DoubleToInt64Bits(d);
return (bits & 0x7FFFFFFFFFFFFFFF) == 0x7FF0000000000000;
@@ -65,7 +65,7 @@ namespace System
/// <summary>Determines whether the specified value is NaN.</summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe static bool IsNaN(double d)
+ public static unsafe bool IsNaN(double d)
{
var bits = BitConverter.DoubleToInt64Bits(d);
return (bits & 0x7FFFFFFFFFFFFFFF) > 0x7FF0000000000000;
@@ -74,10 +74,9 @@ namespace System
/// <summary>Determines whether the specified value is negative.</summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe static bool IsNegative(double d)
+ public static unsafe bool IsNegative(double d)
{
- var bits = unchecked((ulong)BitConverter.DoubleToInt64Bits(d));
- return (bits & 0x8000000000000000) == 0x8000000000000000;
+ return BitConverter.DoubleToInt64Bits(d) < 0;
}
/// <summary>Determines whether the specified value is negative infinity.</summary>
@@ -91,7 +90,7 @@ namespace System
/// <summary>Determines whether the specified value is normal.</summary>
[NonVersionable]
// This is probably not worth inlining, it has branches and should be rarely called
- public unsafe static bool IsNormal(double d)
+ public static unsafe bool IsNormal(double d)
{
var bits = BitConverter.DoubleToInt64Bits(d);
bits &= 0x7FFFFFFFFFFFFFFF;
@@ -109,7 +108,7 @@ namespace System
/// <summary>Determines whether the specified value is subnormal.</summary>
[NonVersionable]
// This is probably not worth inlining, it has branches and should be rarely called
- public unsafe static bool IsSubnormal(double d)
+ public static unsafe bool IsSubnormal(double d)
{
var bits = BitConverter.DoubleToInt64Bits(d);
bits &= 0x7FFFFFFFFFFFFFFF;
@@ -123,13 +122,13 @@ namespace System
//
// Returns a value less than zero if this object
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
- if (value is Double)
+ if (value is double)
{
double d = (double)value;
if (m_value < d) return -1;
@@ -145,7 +144,7 @@ namespace System
throw new ArgumentException(SR.Arg_MustBeDouble);
}
- public int CompareTo(Double value)
+ public int CompareTo(double value)
{
if (m_value < value) return -1;
if (m_value > value) return 1;
@@ -160,13 +159,13 @@ namespace System
// True if obj is another Double with the same value as the current instance. This is
// a method of object equality, that only returns true if obj is also a double.
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is Double))
+ if (!(obj is double))
{
return false;
}
- double temp = ((Double)obj).m_value;
+ double temp = ((double)obj).m_value;
// This code below is written this way for performance reasons i.e the != and == check is intentional.
if (temp == m_value)
{
@@ -176,42 +175,42 @@ namespace System
}
[NonVersionable]
- public static bool operator ==(Double left, Double right)
+ public static bool operator ==(double left, double right)
{
return left == right;
}
[NonVersionable]
- public static bool operator !=(Double left, Double right)
+ public static bool operator !=(double left, double right)
{
return left != right;
}
[NonVersionable]
- public static bool operator <(Double left, Double right)
+ public static bool operator <(double left, double right)
{
return left < right;
}
[NonVersionable]
- public static bool operator >(Double left, Double right)
+ public static bool operator >(double left, double right)
{
return left > right;
}
[NonVersionable]
- public static bool operator <=(Double left, Double right)
+ public static bool operator <=(double left, double right)
{
return left <= right;
}
[NonVersionable]
- public static bool operator >=(Double left, Double right)
+ public static bool operator >=(double left, double right)
{
return left >= right;
}
- public bool Equals(Double obj)
+ public bool Equals(double obj)
{
if (obj == m_value)
{
@@ -226,7 +225,7 @@ namespace System
[MethodImpl(MethodImplOptions.AggressiveInlining)] // 64-bit constants make the IL unusually large that makes the inliner to reject the method
public override int GetHashCode()
{
- var bits = Unsafe.As<double, long>(ref m_value);
+ var bits = Unsafe.As<double, long>(ref Unsafe.AsRef(in m_value));
// Optimized check for IsNan() || IsZero()
if (((bits - 1) & 0x7FFFFFFFFFFFFFFF) >= 0x7FF0000000000000)
@@ -238,22 +237,22 @@ namespace System
return unchecked((int)bits) ^ ((int)(bits >> 32));
}
- public override String ToString()
+ public override string ToString()
{
return Number.FormatDouble(m_value, null, NumberFormatInfo.CurrentInfo);
}
- public String ToString(String format)
+ public string ToString(string format)
{
return Number.FormatDouble(m_value, format, NumberFormatInfo.CurrentInfo);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return Number.FormatDouble(m_value, null, NumberFormatInfo.GetInstance(provider));
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
return Number.FormatDouble(m_value, format, NumberFormatInfo.GetInstance(provider));
}
@@ -263,26 +262,26 @@ namespace System
return Number.TryFormatDouble(m_value, format, NumberFormatInfo.GetInstance(provider), destination, out charsWritten);
}
- public static double Parse(String s)
+ public static double Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseDouble(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo);
}
- public static double Parse(String s, NumberStyles style)
+ public static double Parse(string s, NumberStyles style)
{
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseDouble(s, style, NumberFormatInfo.CurrentInfo);
}
- public static double Parse(String s, IFormatProvider provider)
+ public static double Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseDouble(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.GetInstance(provider));
}
- public static double Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static double Parse(string s, NumberStyles style, IFormatProvider provider)
{
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -297,7 +296,7 @@ namespace System
// PositiveInfinity or NegativeInfinity for a number that is too
// large or too small.
- public static double Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ public static double Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Float | NumberStyles.AllowThousands, IFormatProvider provider = null)
{
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
return Number.ParseDouble(s, style, NumberFormatInfo.GetInstance(provider));
@@ -305,7 +304,7 @@ namespace System
- public static bool TryParse(String s, out double result)
+ public static bool TryParse(string s, out double result)
{
if (s == null)
{
@@ -321,7 +320,7 @@ namespace System
return TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo, out result);
}
- public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out double result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out double result)
{
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
@@ -346,15 +345,15 @@ namespace System
if (!success)
{
ReadOnlySpan<char> sTrim = s.Trim();
- if (StringSpanHelpers.Equals(sTrim, info.PositiveInfinitySymbol))
+ if (sTrim.EqualsOrdinal(info.PositiveInfinitySymbol))
{
result = PositiveInfinity;
}
- else if (StringSpanHelpers.Equals(sTrim, info.NegativeInfinitySymbol))
+ else if (sTrim.EqualsOrdinal(info.NegativeInfinitySymbol))
{
result = NegativeInfinity;
}
- else if (StringSpanHelpers.Equals(sTrim, info.NaNSymbol))
+ else if (sTrim.EqualsOrdinal(info.NaNSymbol))
{
result = NaN;
}
@@ -435,7 +434,7 @@ namespace System
return m_value;
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -445,7 +444,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Double", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/DuplicateWaitObjectException.cs b/src/System.Private.CoreLib/shared/System/DuplicateWaitObjectException.cs
index 77303846a..f48e4be17 100644
--- a/src/System.Private.CoreLib/shared/System/DuplicateWaitObjectException.cs
+++ b/src/System.Private.CoreLib/shared/System/DuplicateWaitObjectException.cs
@@ -21,9 +21,9 @@ namespace System
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class DuplicateWaitObjectException : ArgumentException
{
- private static volatile String s_duplicateWaitObjectMessage = null;
+ private static volatile string s_duplicateWaitObjectMessage = null;
- private static String DuplicateWaitObjectMessage
+ private static string DuplicateWaitObjectMessage
{
get
{
@@ -41,19 +41,19 @@ namespace System
HResult = HResults.COR_E_DUPLICATEWAITOBJECT;
}
- public DuplicateWaitObjectException(String parameterName)
+ public DuplicateWaitObjectException(string parameterName)
: base(DuplicateWaitObjectMessage, parameterName)
{
HResult = HResults.COR_E_DUPLICATEWAITOBJECT;
}
- public DuplicateWaitObjectException(String parameterName, String message)
+ public DuplicateWaitObjectException(string parameterName, string message)
: base(message, parameterName)
{
HResult = HResults.COR_E_DUPLICATEWAITOBJECT;
}
- public DuplicateWaitObjectException(String message, Exception innerException)
+ public DuplicateWaitObjectException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_DUPLICATEWAITOBJECT;
diff --git a/src/System.Private.CoreLib/shared/System/EntryPointNotFoundException.cs b/src/System.Private.CoreLib/shared/System/EntryPointNotFoundException.cs
index dac1cdb97..606743aa1 100644
--- a/src/System.Private.CoreLib/shared/System/EntryPointNotFoundException.cs
+++ b/src/System.Private.CoreLib/shared/System/EntryPointNotFoundException.cs
@@ -26,13 +26,13 @@ namespace System
HResult = HResults.COR_E_ENTRYPOINTNOTFOUND;
}
- public EntryPointNotFoundException(String message)
+ public EntryPointNotFoundException(string message)
: base(message)
{
HResult = HResults.COR_E_ENTRYPOINTNOTFOUND;
}
- public EntryPointNotFoundException(String message, Exception inner)
+ public EntryPointNotFoundException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_ENTRYPOINTNOTFOUND;
diff --git a/src/System.Private.CoreLib/shared/System/EventHandler.cs b/src/System.Private.CoreLib/shared/System/EventHandler.cs
index 3d1cbfef2..c38e17ce6 100644
--- a/src/System.Private.CoreLib/shared/System/EventHandler.cs
+++ b/src/System.Private.CoreLib/shared/System/EventHandler.cs
@@ -6,7 +6,7 @@ using System;
namespace System
{
- public delegate void EventHandler(Object sender, EventArgs e);
+ public delegate void EventHandler(object sender, EventArgs e);
- public delegate void EventHandler<TEventArgs>(Object sender, TEventArgs e); // Removed TEventArgs constraint post-.NET 4
+ public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e); // Removed TEventArgs constraint post-.NET 4
}
diff --git a/src/System.Private.CoreLib/shared/System/ExecutionEngineException.cs b/src/System.Private.CoreLib/shared/System/ExecutionEngineException.cs
index 5edd5cf19..5649cc082 100644
--- a/src/System.Private.CoreLib/shared/System/ExecutionEngineException.cs
+++ b/src/System.Private.CoreLib/shared/System/ExecutionEngineException.cs
@@ -31,13 +31,13 @@ namespace System
HResult = HResults.COR_E_EXECUTIONENGINE;
}
- public ExecutionEngineException(String message)
+ public ExecutionEngineException(string message)
: base(message)
{
HResult = HResults.COR_E_EXECUTIONENGINE;
}
- public ExecutionEngineException(String message, Exception innerException)
+ public ExecutionEngineException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_EXECUTIONENGINE;
diff --git a/src/System.Private.CoreLib/shared/System/FieldAccessException.cs b/src/System.Private.CoreLib/shared/System/FieldAccessException.cs
index cb28264d6..b23984133 100644
--- a/src/System.Private.CoreLib/shared/System/FieldAccessException.cs
+++ b/src/System.Private.CoreLib/shared/System/FieldAccessException.cs
@@ -23,13 +23,13 @@ namespace System
HResult = HResults.COR_E_FIELDACCESS;
}
- public FieldAccessException(String message)
+ public FieldAccessException(string message)
: base(message)
{
HResult = HResults.COR_E_FIELDACCESS;
}
- public FieldAccessException(String message, Exception inner)
+ public FieldAccessException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_FIELDACCESS;
diff --git a/src/System.Private.CoreLib/shared/System/FormatException.cs b/src/System.Private.CoreLib/shared/System/FormatException.cs
index b0e273369..97d5001f3 100644
--- a/src/System.Private.CoreLib/shared/System/FormatException.cs
+++ b/src/System.Private.CoreLib/shared/System/FormatException.cs
@@ -25,13 +25,13 @@ namespace System
HResult = HResults.COR_E_FORMAT;
}
- public FormatException(String message)
+ public FormatException(string message)
: base(message)
{
HResult = HResults.COR_E_FORMAT;
}
- public FormatException(String message, Exception innerException)
+ public FormatException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_FORMAT;
diff --git a/src/System.Private.CoreLib/shared/System/FormattableString.cs b/src/System.Private.CoreLib/shared/System/FormattableString.cs
index 6369363b5..51863d6e7 100644
--- a/src/System.Private.CoreLib/shared/System/FormattableString.cs
+++ b/src/System.Private.CoreLib/shared/System/FormattableString.cs
@@ -73,6 +73,29 @@ namespace System
return formattable.ToString(Globalization.CultureInfo.InvariantCulture);
}
+ /// <summary>
+ /// Format the given object in the current culture. This static method may be
+ /// imported in C# by
+ /// <code>
+ /// using static System.FormattableString;
+ /// </code>.
+ /// Within the scope
+ /// of that import directive an interpolated string may be formatted in the
+ /// current culture by writing, for example,
+ /// <code>
+ /// CurrentCulture($"{{ lat = {latitude}; lon = {longitude} }}")
+ /// </code>
+ /// </summary>
+ public static string CurrentCulture(FormattableString formattable)
+ {
+ if (formattable == null)
+ {
+ throw new ArgumentNullException(nameof(formattable));
+ }
+
+ return formattable.ToString(Globalization.CultureInfo.CurrentCulture);
+ }
+
public override string ToString()
{
return ToString(Globalization.CultureInfo.CurrentCulture);
diff --git a/src/System.Private.CoreLib/shared/System/Gen2GcCallback.cs b/src/System.Private.CoreLib/shared/System/Gen2GcCallback.cs
new file mode 100644
index 000000000..225268122
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Gen2GcCallback.cs
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.InteropServices;
+
+namespace System
+{
+ /// <summary>
+ /// Schedules a callback roughly every gen 2 GC (you may see a Gen 0 an Gen 1 but only once)
+ /// (We can fix this by capturing the Gen 2 count at startup and testing, but I mostly don't care)
+ /// </summary>
+ internal sealed class Gen2GcCallback : CriticalFinalizerObject
+ {
+ private Gen2GcCallback()
+ : base()
+ {
+ }
+
+ /// <summary>
+ /// Schedule 'callback' to be called in the next GC. If the callback returns true it is
+ /// rescheduled for the next Gen 2 GC. Otherwise the callbacks stop.
+ ///
+ /// NOTE: This callback will be kept alive until either the callback function returns false,
+ /// or the target object dies.
+ /// </summary>
+ public static void Register(Func<object, bool> callback, object targetObj)
+ {
+ // Create a unreachable object that remembers the callback function and target object.
+ Gen2GcCallback gcCallback = new Gen2GcCallback();
+ gcCallback.Setup(callback, targetObj);
+ }
+
+ private Func<object, bool> _callback;
+ private GCHandle _weakTargetObj;
+
+ private void Setup(Func<object, bool> callback, object targetObj)
+ {
+ _callback = callback;
+ _weakTargetObj = GCHandle.Alloc(targetObj, GCHandleType.Weak);
+ }
+
+ ~Gen2GcCallback()
+ {
+ // Check to see if the target object is still alive.
+ object targetObj = _weakTargetObj.Target;
+ if (targetObj == null)
+ {
+ // The target object is dead, so this callback object is no longer needed.
+ _weakTargetObj.Free();
+ return;
+ }
+
+ // Execute the callback method.
+ try
+ {
+ if (!_callback(targetObj))
+ {
+ // If the callback returns false, this callback object is no longer needed.
+ return;
+ }
+ }
+ catch
+ {
+ // Ensure that we still get a chance to resurrect this object, even if the callback throws an exception.
+ }
+
+ // Resurrect ourselves by re-registering for finalization.
+ if (!Environment.HasShutdownStarted)
+ {
+ GC.ReRegisterForFinalize(this);
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/Calendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/Calendar.cs
index 49ad597ce..66a63694a 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/Calendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/Calendar.cs
@@ -206,7 +206,7 @@ namespace System.Globalization
if (ticks < minValue.Ticks || ticks > maxValue.Ticks)
{
throw new ArgumentException(
- String.Format(CultureInfo.InvariantCulture, SR.Format(SR.Argument_ResultCalendarRange,
+ string.Format(CultureInfo.InvariantCulture, SR.Format(SR.Argument_ResultCalendarRange,
minValue, maxValue)));
}
}
@@ -736,7 +736,7 @@ namespace System.Globalization
public abstract DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era);
- internal virtual Boolean TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result)
+ internal virtual bool TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result)
{
result = DateTime.MinValue;
try
@@ -818,7 +818,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(millisecond),
- String.Format(
+ string.Format(
CultureInfo.InvariantCulture,
SR.Format(SR.ArgumentOutOfRange_Range, 0, MillisPerSecond - 1)));
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Unix.cs b/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Unix.cs
index 17d6ed7a0..c94ac0ae5 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Unix.cs
@@ -32,7 +32,7 @@ namespace System.Globalization
internal partial class CalendarData
{
- private bool LoadCalendarDataFromSystem(String localeName, CalendarId calendarId)
+ private bool LoadCalendarDataFromSystem(string localeName, CalendarId calendarId)
{
bool result = true;
result &= GetCalendarInfo(localeName, calendarId, CalendarDataType.NativeName, out this.sNativeName);
@@ -134,16 +134,107 @@ namespace System.Globalization
{
List<string> datePatternsList = callbackContext.Results;
- datePatterns = new string[datePatternsList.Count];
for (int i = 0; i < datePatternsList.Count; i++)
{
- datePatterns[i] = NormalizeDatePattern(datePatternsList[i]);
+ datePatternsList[i] = NormalizeDatePattern(datePatternsList[i]);
}
+
+ if (dataType == CalendarDataType.ShortDates)
+ FixDefaultShortDatePattern(datePatternsList);
+
+ datePatterns = datePatternsList.ToArray();
}
return result;
}
+ // FixDefaultShortDatePattern will convert the default short date pattern from using 'yy' to using 'yyyy'
+ // And will ensure the original pattern still exist in the list.
+ // doing that will have the short date pattern format the year as 4-digit number and not just 2-digit number.
+ // Example: June 5, 2018 will be formatted to something like 6/5/2018 instead of 6/5/18 fro en-US culture.
+ private static void FixDefaultShortDatePattern(List<string> shortDatePatterns)
+ {
+ if (shortDatePatterns.Count == 0)
+ return;
+
+ string s = shortDatePatterns[0];
+
+ // We are not expecting any pattern have length more than 100.
+ // We have to do this check to prevent stack overflow as we allocate the buffer on the stack.
+ if (s.Length > 100)
+ return;
+
+ Span<char> modifiedPattern = stackalloc char[s.Length + 2];
+ int index = 0;
+
+ while (index < s.Length)
+ {
+ if (s[index] == '\'')
+ {
+ do
+ {
+ modifiedPattern[index] = s[index];
+ index++;
+ } while (index < s.Length && s[index] != '\'');
+
+ if (index >= s.Length)
+ return;
+ }
+ else if (s[index] == 'y')
+ {
+ modifiedPattern[index] = 'y';
+ break;
+ }
+
+ modifiedPattern[index] = s[index];
+ index++;
+ }
+
+ if (index >= s.Length - 1 || s[index + 1] != 'y')
+ {
+ // not a 'yy' pattern
+ return;
+ }
+
+ if (index + 2 < s.Length && s[index + 2] == 'y')
+ {
+ // we have 'yyy' then nothing to do
+ return;
+ }
+
+ // we are sure now we have 'yy' pattern
+
+ Debug.Assert(index + 3 < modifiedPattern.Length);
+
+ modifiedPattern[index + 1] = 'y'; // second y
+ modifiedPattern[index + 2] = 'y'; // third y
+ modifiedPattern[index + 3] = 'y'; // fourth y
+
+ index += 2;
+
+ // Now, copy the rest of the pattern to the destination buffer
+ while (index < s.Length)
+ {
+ modifiedPattern[index + 2] = s[index];
+ index++;
+ }
+
+ shortDatePatterns[0] = modifiedPattern.ToString();
+
+ for (int i = 1; i < shortDatePatterns.Count; i++)
+ {
+ if (shortDatePatterns[i] == shortDatePatterns[0])
+ {
+ // Found match in the list to the new constructed pattern, then replace it with the original modified pattern
+ shortDatePatterns[i] = s;
+ return;
+ }
+ }
+
+ // if we come here means the newly constructed pattern not found on the list, then add the original pattern
+ shortDatePatterns.Add(s);
+ }
+
/// <summary>
/// The ICU date format characters are not exactly the same as the .NET date format characters.
/// NormalizeDatePattern will take in an ICU date pattern and return the equivalent .NET date pattern.
@@ -220,7 +311,7 @@ namespace System.Globalization
break;
default:
const string unsupportedDateFieldSymbols = "YuUrQqwWDFg";
- Debug.Assert(unsupportedDateFieldSymbols.IndexOf(input[index]) == -1,
+ Debug.Assert(!unsupportedDateFieldSymbols.Contains(input[index]),
string.Format(CultureInfo.InvariantCulture,
"Encountered an unexpected date field symbol '{0}' from ICU which has no known corresponding .NET equivalent.",
input[index]));
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Windows.cs b/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Windows.cs
index 03f9088d6..de5037441 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.Windows.cs
@@ -13,7 +13,7 @@ namespace System.Globalization
{
internal partial class CalendarData
{
- private bool LoadCalendarDataFromSystem(String localeName, CalendarId calendarId)
+ private bool LoadCalendarDataFromSystem(string localeName, CalendarId calendarId)
{
Debug.Assert(!GlobalizationMode.Invariant);
@@ -127,7 +127,7 @@ namespace System.Globalization
}
// Call native side to figure out which calendars are allowed
- internal static int GetCalendars(String localeName, bool useUserOverride, CalendarId[] calendars)
+ internal static int GetCalendars(string localeName, bool useUserOverride, CalendarId[] calendars)
{
Debug.Assert(!GlobalizationMode.Invariant);
@@ -451,7 +451,7 @@ namespace System.Globalization
}
}
- private static unsafe String GetUserDefaultLocaleName()
+ private static unsafe string GetUserDefaultLocaleName()
{
Debug.Assert(!GlobalizationMode.Invariant);
@@ -463,7 +463,7 @@ namespace System.Globalization
char* localeName = stackalloc char[LOCALE_NAME_MAX_LENGTH];
result = CultureData.GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME, localeName, LOCALE_NAME_MAX_LENGTH);
- return result <= 0 ? "" : new String(localeName, 0, result - 1); // exclude the null termination
+ return result <= 0 ? "" : new string(localeName, 0, result - 1); // exclude the null termination
}
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.cs b/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.cs
index ea70a1ce9..56ddf7579 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CalendarData.cs
@@ -19,26 +19,26 @@ namespace System.Globalization
internal const int MAX_CALENDARS = 23;
// Identity
- internal String sNativeName; // Calendar Name for the locale
+ internal string sNativeName; // Calendar Name for the locale
// Formats
- internal String[] saShortDates; // Short Data format, default first
- internal String[] saYearMonths; // Year/Month Data format, default first
- internal String[] saLongDates; // Long Data format, default first
- internal String sMonthDay; // Month/Day format
+ internal string[] saShortDates; // Short Data format, default first
+ internal string[] saYearMonths; // Year/Month Data format, default first
+ internal string[] saLongDates; // Long Data format, default first
+ internal string sMonthDay; // Month/Day format
// Calendar Parts Names
- internal String[] saEraNames; // Names of Eras
- internal String[] saAbbrevEraNames; // Abbreviated Era Names
- internal String[] saAbbrevEnglishEraNames; // Abbreviated Era Names in English
- internal String[] saDayNames; // Day Names, null to use locale data, starts on Sunday
- internal String[] saAbbrevDayNames; // Abbrev Day Names, null to use locale data, starts on Sunday
- internal String[] saSuperShortDayNames; // Super short Day of week names
- internal String[] saMonthNames; // Month Names (13)
- internal String[] saAbbrevMonthNames; // Abbrev Month Names (13)
- internal String[] saMonthGenitiveNames; // Genitive Month Names (13)
- internal String[] saAbbrevMonthGenitiveNames; // Genitive Abbrev Month Names (13)
- internal String[] saLeapYearMonthNames; // Multiple strings for the month names in a leap year.
+ internal string[] saEraNames; // Names of Eras
+ internal string[] saAbbrevEraNames; // Abbreviated Era Names
+ internal string[] saAbbrevEnglishEraNames; // Abbreviated Era Names in English
+ internal string[] saDayNames; // Day Names, null to use locale data, starts on Sunday
+ internal string[] saAbbrevDayNames; // Abbrev Day Names, null to use locale data, starts on Sunday
+ internal string[] saSuperShortDayNames; // Super short Day of week names
+ internal string[] saMonthNames; // Month Names (13)
+ internal string[] saAbbrevMonthNames; // Abbrev Month Names (13)
+ internal string[] saMonthGenitiveNames; // Genitive Month Names (13)
+ internal string[] saAbbrevMonthGenitiveNames; // Genitive Abbrev Month Names (13)
+ internal string[] saLeapYearMonthNames; // Multiple strings for the month names in a leap year.
// Integers at end to make marshaller happier
internal int iTwoDigitYearMax = 2029; // Max 2 digit year (for Y2K bug data entry)
@@ -69,22 +69,22 @@ namespace System.Globalization
invariant.iCurrentEra = 1; // Current era #
// Formats
- invariant.saShortDates = new String[] { "MM/dd/yyyy", "yyyy-MM-dd" }; // short date format
- invariant.saLongDates = new String[] { "dddd, dd MMMM yyyy" }; // long date format
- invariant.saYearMonths = new String[] { "yyyy MMMM" }; // year month format
+ invariant.saShortDates = new string[] { "MM/dd/yyyy", "yyyy-MM-dd" }; // short date format
+ invariant.saLongDates = new string[] { "dddd, dd MMMM yyyy" }; // long date format
+ invariant.saYearMonths = new string[] { "yyyy MMMM" }; // year month format
invariant.sMonthDay = "MMMM dd"; // Month day pattern
// Calendar Parts Names
- invariant.saEraNames = new String[] { "A.D." }; // Era names
- invariant.saAbbrevEraNames = new String[] { "AD" }; // Abbreviated Era names
- invariant.saAbbrevEnglishEraNames = new String[] { "AD" }; // Abbreviated era names in English
- invariant.saDayNames = new String[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };// day names
- invariant.saAbbrevDayNames = new String[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; // abbreviated day names
- invariant.saSuperShortDayNames = new String[] { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" }; // The super short day names
- invariant.saMonthNames = new String[] { "January", "February", "March", "April", "May", "June",
- "July", "August", "September", "October", "November", "December", String.Empty}; // month names
- invariant.saAbbrevMonthNames = new String[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", String.Empty}; // abbreviated month names
+ invariant.saEraNames = new string[] { "A.D." }; // Era names
+ invariant.saAbbrevEraNames = new string[] { "AD" }; // Abbreviated Era names
+ invariant.saAbbrevEnglishEraNames = new string[] { "AD" }; // Abbreviated era names in English
+ invariant.saDayNames = new string[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };// day names
+ invariant.saAbbrevDayNames = new string[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; // abbreviated day names
+ invariant.saSuperShortDayNames = new string[] { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" }; // The super short day names
+ invariant.saMonthNames = new string[] { "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December", string.Empty}; // month names
+ invariant.saAbbrevMonthNames = new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", string.Empty}; // abbreviated month names
invariant.saMonthGenitiveNames = invariant.saMonthNames; // Genitive month names (same as month names for invariant)
invariant.saAbbrevMonthGenitiveNames = invariant.saAbbrevMonthNames; // Abbreviated genitive month names (same as abbrev month names for invariant)
invariant.saLeapYearMonthNames = invariant.saMonthNames; // leap year month names are unused in Gregorian English (invariant)
@@ -97,7 +97,7 @@ namespace System.Globalization
//
// Get a bunch of data for a calendar
//
- internal CalendarData(String localeName, CalendarId calendarId, bool bUseUserOverrides)
+ internal CalendarData(string localeName, CalendarId calendarId, bool bUseUserOverrides)
{
this.bUseUserOverrides = bUseUserOverrides;
@@ -109,7 +109,7 @@ namespace System.Globalization
// Something failed, try invariant for missing parts
// This is really not good, but we don't want the callers to crash.
- if (this.sNativeName == null) this.sNativeName = String.Empty; // Calendar Name for the locale.
+ if (this.sNativeName == null) this.sNativeName = string.Empty; // Calendar Name for the locale.
// Formats
if (this.saShortDates == null) this.saShortDates = Invariant.saShortDates; // Short Data format, default first
@@ -138,16 +138,16 @@ namespace System.Globalization
}
else
{
- this.sNativeName = String.Empty;
+ this.sNativeName = string.Empty;
}
}
// Check for null genitive names (in case unmanaged side skips it for non-gregorian calendars, etc)
- if (this.saMonthGenitiveNames == null || this.saMonthGenitiveNames.Length == 0 || String.IsNullOrEmpty(this.saMonthGenitiveNames[0]))
+ if (this.saMonthGenitiveNames == null || this.saMonthGenitiveNames.Length == 0 || string.IsNullOrEmpty(this.saMonthGenitiveNames[0]))
this.saMonthGenitiveNames = this.saMonthNames; // Genitive month names (same as month names for invariant)
- if (this.saAbbrevMonthGenitiveNames == null || this.saAbbrevMonthGenitiveNames.Length == 0 || String.IsNullOrEmpty(this.saAbbrevMonthGenitiveNames[0]))
+ if (this.saAbbrevMonthGenitiveNames == null || this.saAbbrevMonthGenitiveNames.Length == 0 || string.IsNullOrEmpty(this.saAbbrevMonthGenitiveNames[0]))
this.saAbbrevMonthGenitiveNames = this.saAbbrevMonthNames; // Abbreviated genitive month names (same as abbrev month names for invariant)
- if (this.saLeapYearMonthNames == null || this.saLeapYearMonthNames.Length == 0 || String.IsNullOrEmpty(this.saLeapYearMonthNames[0]))
+ if (this.saLeapYearMonthNames == null || this.saLeapYearMonthNames.Length == 0 || string.IsNullOrEmpty(this.saLeapYearMonthNames[0]))
this.saLeapYearMonthNames = this.saMonthNames;
InitializeEraNames(localeName, calendarId);
@@ -162,7 +162,7 @@ namespace System.Globalization
else
{
// For all others just use the an empty string (doesn't matter we'll never ask for it for other calendars)
- this.saAbbrevEnglishEraNames = new String[] { "" };
+ this.saAbbrevEnglishEraNames = new string[] { "" };
}
// Japanese is the only thing with > 1 era. Its current era # is how many ever
@@ -178,60 +178,60 @@ namespace System.Globalization
// For Localized Gregorian we really expect the data from the OS.
case CalendarId.GREGORIAN:
// Fallback for CoreCLR < Win7 or culture.dll missing
- if (this.saEraNames == null || this.saEraNames.Length == 0 || String.IsNullOrEmpty(this.saEraNames[0]))
+ if (this.saEraNames == null || this.saEraNames.Length == 0 || string.IsNullOrEmpty(this.saEraNames[0]))
{
- this.saEraNames = new String[] { "A.D." };
+ this.saEraNames = new string[] { "A.D." };
}
break;
// The rest of the calendars have constant data, so we'll just use that
case CalendarId.GREGORIAN_US:
case CalendarId.JULIAN:
- this.saEraNames = new String[] { "A.D." };
+ this.saEraNames = new string[] { "A.D." };
break;
case CalendarId.HEBREW:
- this.saEraNames = new String[] { "C.E." };
+ this.saEraNames = new string[] { "C.E." };
break;
case CalendarId.HIJRI:
case CalendarId.UMALQURA:
if (localeName == "dv-MV")
{
// Special case for Divehi
- this.saEraNames = new String[] { "\x0780\x07a8\x0796\x07b0\x0783\x07a9" };
+ this.saEraNames = new string[] { "\x0780\x07a8\x0796\x07b0\x0783\x07a9" };
}
else
{
- this.saEraNames = new String[] { "\x0628\x0639\x062F \x0627\x0644\x0647\x062C\x0631\x0629" };
+ this.saEraNames = new string[] { "\x0628\x0639\x062F \x0627\x0644\x0647\x062C\x0631\x0629" };
}
break;
case CalendarId.GREGORIAN_ARABIC:
case CalendarId.GREGORIAN_XLIT_ENGLISH:
case CalendarId.GREGORIAN_XLIT_FRENCH:
// These are all the same:
- this.saEraNames = new String[] { "\x0645" };
+ this.saEraNames = new string[] { "\x0645" };
break;
case CalendarId.GREGORIAN_ME_FRENCH:
- this.saEraNames = new String[] { "ap. J.-C." };
+ this.saEraNames = new string[] { "ap. J.-C." };
break;
case CalendarId.TAIWAN:
if (SystemSupportsTaiwaneseCalendar())
{
- this.saEraNames = new String[] { "\x4e2d\x83ef\x6c11\x570b" };
+ this.saEraNames = new string[] { "\x4e2d\x83ef\x6c11\x570b" };
}
else
{
- this.saEraNames = new String[] { String.Empty };
+ this.saEraNames = new string[] { string.Empty };
}
break;
case CalendarId.KOREA:
- this.saEraNames = new String[] { "\xb2e8\xae30" };
+ this.saEraNames = new string[] { "\xb2e8\xae30" };
break;
case CalendarId.THAI:
- this.saEraNames = new String[] { "\x0e1e\x002e\x0e28\x002e" };
+ this.saEraNames = new string[] { "\x0e1e\x002e\x0e28\x002e" };
break;
case CalendarId.JAPAN:
@@ -240,9 +240,9 @@ namespace System.Globalization
break;
case CalendarId.PERSIAN:
- if (this.saEraNames == null || this.saEraNames.Length == 0 || String.IsNullOrEmpty(this.saEraNames[0]))
+ if (this.saEraNames == null || this.saEraNames.Length == 0 || string.IsNullOrEmpty(this.saEraNames[0]))
{
- this.saEraNames = new String[] { "\x0647\x002e\x0634" };
+ this.saEraNames = new string[] { "\x0647\x002e\x0634" };
}
break;
@@ -261,16 +261,16 @@ namespace System.Globalization
// For Localized Gregorian we really expect the data from the OS.
case CalendarId.GREGORIAN:
// Fallback for CoreCLR < Win7 or culture.dll missing
- if (this.saAbbrevEraNames == null || this.saAbbrevEraNames.Length == 0 || String.IsNullOrEmpty(this.saAbbrevEraNames[0]))
+ if (this.saAbbrevEraNames == null || this.saAbbrevEraNames.Length == 0 || string.IsNullOrEmpty(this.saAbbrevEraNames[0]))
{
- this.saAbbrevEraNames = new String[] { "AD" };
+ this.saAbbrevEraNames = new string[] { "AD" };
}
break;
// The rest of the calendars have constant data, so we'll just use that
case CalendarId.GREGORIAN_US:
case CalendarId.JULIAN:
- this.saAbbrevEraNames = new String[] { "AD" };
+ this.saAbbrevEraNames = new string[] { "AD" };
break;
case CalendarId.JAPAN:
case CalendarId.JAPANESELUNISOLAR:
@@ -281,16 +281,16 @@ namespace System.Globalization
if (localeName == "dv-MV")
{
// Special case for Divehi
- this.saAbbrevEraNames = new String[] { "\x0780\x002e" };
+ this.saAbbrevEraNames = new string[] { "\x0780\x002e" };
}
else
{
- this.saAbbrevEraNames = new String[] { "\x0647\x0640" };
+ this.saAbbrevEraNames = new string[] { "\x0647\x0640" };
}
break;
case CalendarId.TAIWAN:
// Get era name and abbreviate it
- this.saAbbrevEraNames = new String[1];
+ this.saAbbrevEraNames = new string[1];
if (this.saEraNames[0].Length == 4)
{
this.saAbbrevEraNames[0] = this.saEraNames[0].Substring(2, 2);
@@ -302,7 +302,7 @@ namespace System.Globalization
break;
case CalendarId.PERSIAN:
- if (this.saAbbrevEraNames == null || this.saAbbrevEraNames.Length == 0 || String.IsNullOrEmpty(this.saAbbrevEraNames[0]))
+ if (this.saAbbrevEraNames == null || this.saAbbrevEraNames.Length == 0 || string.IsNullOrEmpty(this.saAbbrevEraNames[0]))
{
this.saAbbrevEraNames = this.saEraNames;
}
@@ -326,13 +326,13 @@ namespace System.Globalization
// Get a culture name
// TODO: Note that this doesn't handle the new calendars (lunisolar, etc)
- String culture = CalendarIdToCultureName(calendarId);
+ string culture = CalendarIdToCultureName(calendarId);
// Return our calendar
return CultureInfo.GetCultureInfo(culture)._cultureData.GetCalendar(calendarId);
}
- private static String CalendarIdToCultureName(CalendarId calendarId)
+ private static string CalendarIdToCultureName(CalendarId calendarId)
{
switch (calendarId)
{
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CharUnicodeInfo.cs b/src/System.Private.CoreLib/shared/System/Globalization/CharUnicodeInfo.cs
index 0cd8429bb..d8d621cb0 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CharUnicodeInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CharUnicodeInfo.cs
@@ -13,6 +13,7 @@
////////////////////////////////////////////////////////////////////////////
using System.Diagnostics;
+using System.Text;
namespace System.Globalization
{
@@ -29,6 +30,7 @@ namespace System.Globalization
internal const char HIGH_SURROGATE_END = '\udbff';
internal const char LOW_SURROGATE_START = '\udc00';
internal const char LOW_SURROGATE_END = '\udfff';
+ internal const int HIGH_SURROGATE_RANGE = 0x3FF;
internal const int UNICODE_CATEGORY_OFFSET = 0;
internal const int BIDI_CATEGORY_OFFSET = 1;
@@ -41,7 +43,7 @@ namespace System.Globalization
//
// Actions:
// Convert the BMP character or surrogate pointed by index to a UTF32 value.
- // This is similar to Char.ConvertToUTF32, but the difference is that
+ // This is similar to char.ConvertToUTF32, but the difference is that
// it does not throw exceptions when invalid surrogate characters are passed in.
//
// WARNING: since it doesn't throw an exception it CAN return a value
@@ -49,17 +51,17 @@ namespace System.Globalization
//
////////////////////////////////////////////////////////////////////////
- internal static int InternalConvertToUtf32(String s, int index)
+ internal static int InternalConvertToUtf32(string s, int index)
{
Debug.Assert(s != null, "s != null");
Debug.Assert(index >= 0 && index < s.Length, "index < s.Length");
if (index < s.Length - 1)
{
int temp1 = (int)s[index] - HIGH_SURROGATE_START;
- if (temp1 >= 0 && temp1 <= 0x3ff)
+ if (temp1 >= 0 && temp1 <= HIGH_SURROGATE_RANGE)
{
int temp2 = (int)s[index + 1] - LOW_SURROGATE_START;
- if (temp2 >= 0 && temp2 <= 0x3ff)
+ if (temp2 >= 0 && temp2 <= HIGH_SURROGATE_RANGE)
{
// Convert the surrogate to UTF32 and get the result.
return ((temp1 * 0x400) + temp2 + UNICODE_PLANE01_START);
@@ -68,6 +70,29 @@ namespace System.Globalization
}
return ((int)s[index]);
}
+
+ internal static int InternalConvertToUtf32(StringBuilder s, int index)
+ {
+ Debug.Assert(s != null, "s != null");
+ Debug.Assert(index >= 0 && index < s.Length, "index < s.Length");
+
+ int c = (int)s[index];
+ if (index < s.Length - 1)
+ {
+ int temp1 = c - HIGH_SURROGATE_START;
+ if (temp1 >= 0 && temp1 <= HIGH_SURROGATE_RANGE)
+ {
+ int temp2 = (int)s[index + 1] - LOW_SURROGATE_START;
+ if (temp2 >= 0 && temp2 <= HIGH_SURROGATE_RANGE)
+ {
+ // Convert the surrogate to UTF32 and get the result.
+ return ((temp1 * 0x400) + temp2 + UNICODE_PLANE01_START);
+ }
+ }
+ }
+ return c;
+ }
+
////////////////////////////////////////////////////////////////////////
//
// Convert a character or a surrogate pair starting at index of string s
@@ -90,7 +115,7 @@ namespace System.Globalization
//
////////////////////////////////////////////////////////////////////////
- internal static int InternalConvertToUtf32(String s, int index, out int charLength)
+ internal static int InternalConvertToUtf32(string s, int index, out int charLength)
{
Debug.Assert(s != null, "s != null");
Debug.Assert(s.Length > 0, "s.Length > 0");
@@ -99,10 +124,10 @@ namespace System.Globalization
if (index < s.Length - 1)
{
int temp1 = (int)s[index] - HIGH_SURROGATE_START;
- if (temp1 >= 0 && temp1 <= 0x3ff)
+ if (temp1 >= 0 && temp1 <= HIGH_SURROGATE_RANGE)
{
int temp2 = (int)s[index + 1] - LOW_SURROGATE_START;
- if (temp2 >= 0 && temp2 <= 0x3ff)
+ if (temp2 >= 0 && temp2 <= HIGH_SURROGATE_RANGE)
{
// Convert the surrogate to UTF32 and get the result.
charLength++;
@@ -121,7 +146,7 @@ namespace System.Globalization
//
////////////////////////////////////////////////////////////////////////
- internal static bool IsWhiteSpace(String s, int index)
+ internal static bool IsWhiteSpace(string s, int index)
{
Debug.Assert(s != null, "s!=null");
Debug.Assert(index >= 0 && index < s.Length, "index >= 0 && index < s.Length");
@@ -221,7 +246,7 @@ namespace System.Globalization
}
- public static double GetNumericValue(String s, int index)
+ public static double GetNumericValue(string s, int index)
{
if (s == null)
{
@@ -239,7 +264,7 @@ namespace System.Globalization
return (sbyte)(InternalGetDigitValues(ch) >> 8);
}
- public static int GetDecimalDigitValue(String s, int index)
+ public static int GetDecimalDigitValue(string s, int index)
{
if (s == null)
{
@@ -259,7 +284,7 @@ namespace System.Globalization
return (sbyte)(InternalGetDigitValues(ch) & 0x00FF);
}
- public static int GetDigitValue(String s, int index)
+ public static int GetDigitValue(string s, int index)
{
if (s == null)
{
@@ -279,7 +304,7 @@ namespace System.Globalization
return (GetUnicodeCategory((int)ch));
}
- public static UnicodeCategory GetUnicodeCategory(String s, int index)
+ public static UnicodeCategory GetUnicodeCategory(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -347,7 +372,7 @@ namespace System.Globalization
//
////////////////////////////////////////////////////////////////////////
- internal static UnicodeCategory InternalGetUnicodeCategory(String value, int index)
+ internal static UnicodeCategory InternalGetUnicodeCategory(string value, int index)
{
Debug.Assert(value != null, "value can not be null");
Debug.Assert(index < value.Length, "index < value.Length");
@@ -355,7 +380,7 @@ namespace System.Globalization
return (GetUnicodeCategory(InternalConvertToUtf32(value, index)));
}
- internal static BidiCategory GetBidiCategory(String s, int index)
+ internal static BidiCategory GetBidiCategory(string s, int index)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -368,6 +393,14 @@ namespace System.Globalization
return ((BidiCategory) InternalGetCategoryValue(InternalConvertToUtf32(s, index), BIDI_CATEGORY_OFFSET));
}
+ internal static BidiCategory GetBidiCategory(StringBuilder s, int index)
+ {
+ Debug.Assert(s != null, "s can not be null");
+ Debug.Assert(index >= 0 && index < s.Length, "invalid index"); ;
+
+ return ((BidiCategory) InternalGetCategoryValue(InternalConvertToUtf32(s, index), BIDI_CATEGORY_OFFSET));
+ }
+
////////////////////////////////////////////////////////////////////////
//
// Get the Unicode category of the character starting at index. If the character is in BMP, charLength will return 1.
@@ -375,7 +408,7 @@ namespace System.Globalization
//
////////////////////////////////////////////////////////////////////////
- internal static UnicodeCategory InternalGetUnicodeCategory(String str, int index, out int charLength)
+ internal static UnicodeCategory InternalGetUnicodeCategory(string str, int index, out int charLength)
{
Debug.Assert(str != null, "str can not be null");
Debug.Assert(str.Length > 0, "str.Length > 0"); ;
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/ChineseLunisolarCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/ChineseLunisolarCalendar.cs
index d2b52b97b..39448e183 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/ChineseLunisolarCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/ChineseLunisolarCalendar.cs
@@ -8,9 +8,9 @@ namespace System.Globalization
/*
** Calendar support range:
** Calendar Minimum Maximum
- ** ========== ========== ==========
+ ** ========== ========== ==========
** Gregorian 1901/02/19 2101/01/28
- ** ChineseLunisolar 1901/01/01 2100/12/29
+ ** ChineseLunisolar 1901/01/01 2100/12/29
*/
public class ChineseLunisolarCalendar : EastAsianLunisolarCalendar
@@ -43,7 +43,6 @@ namespace System.Globalization
}
}
-
public override DateTime MaxSupportedDateTime
{
get
@@ -56,218 +55,222 @@ namespace System.Globalization
{
get
{
- // 1900: 1-29 2-30 3-29 4-29 5-30 6-29 7-30 8-30 Leap8-29 9-30 10-30 11-29 12-30 from Calendrical Tabulations
+ // 1900: 1-29 2-30 3-29 4-29 5-30 6-29 7-30 8-30 Leap8-29 9-30 10-30 11-29 12-30 from Calendrical Tabulations [1]
+ // [1] Reingold, Edward M, and Nachum Dershowitz. Calendrical Tabulations, 1900 - 2200.Cambridge: Cambridge Univ. Press, 2002.Print.
return 384;
}
}
-
+ // Data for years 1901-1905 and 1907-2100 matches output of Calendrical Calculations [2] and published calendar tables [3].
+ // For 1906, month 4 of the Chinese year starts on 24 Apr 1906 and has 29 days. This is historially accurate
+ // but different to the values in [1] and output from [2]. This is due to a change in the astronomical methods used
+ // by the Chinese to calculate the calendar from 1913 onwards (see warnings in [1]).
+ // [2] Reingold, Edward M, and Nachum Dershowitz. Calendrical Calculations: The Ultimate Edition. Cambridge [etc.: Cambridge University Press, 2018. Print.
+ // [3] Wang, Jianmin. Xin Bian Wan Nian Li: (1840-2050) Chong Bian Ben. Beijing: Ke xue pu ji chu ban she, 1990. Print.
private static readonly int[,] s_yinfo =
{
- /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
- 1901 */
- { 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1902 */{ 0 , 2 , 8 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1903 */{ 5 , 1 , 29 , 21096 },/* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
-1904 */{ 0 , 2 , 16 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-1905 */{ 0 , 2 , 4 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
-1906 */{ 4 , 1 , 25 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1907 */{ 0 , 2 , 13 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1908 */{ 0 , 2 , 2 , 39632 },/* 30 29 29 30 30 29 30 29 30 30 29 30 0 355
-1909 */{ 2 , 1 , 22 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1910 */{ 0 , 2 , 10 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1911 */{ 6 , 1 , 30 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1912 */{ 0 , 2 , 18 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1913 */{ 0 , 2 , 6 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-1914 */{ 5 , 1 , 26 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
-1915 */{ 0 , 2 , 14 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
-1916 */{ 0 , 2 , 3 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355
-1917 */{ 2 , 1 , 23 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
-1918 */{ 0 , 2 , 11 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1919 */{ 7 , 2 , 1 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1920 */{ 0 , 2 , 20 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1921 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1922 */{ 5 , 1 , 28 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1923 */{ 0 , 2 , 16 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
-1924 */{ 0 , 2 , 5 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
-1925 */{ 4 , 1 , 24 , 44456 },/* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
-1926 */{ 0 , 2 , 13 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1927 */{ 0 , 2 , 2 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355
-1928 */{ 2 , 1 , 23 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
-1929 */{ 0 , 2 , 10 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1930 */{ 6 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
-1931 */{ 0 , 2 , 17 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1932 */{ 0 , 2 , 6 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
-1933 */{ 5 , 1 , 26 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
-1934 */{ 0 , 2 , 14 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
-1935 */{ 0 , 2 , 4 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1936 */{ 3 , 1 , 24 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
-1937 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1938 */{ 7 , 1 , 31 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-1939 */{ 0 , 2 , 19 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
-1940 */{ 0 , 2 , 8 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1941 */{ 6 , 1 , 27 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1942 */{ 0 , 2 , 15 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1943 */{ 0 , 2 , 5 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1944 */{ 4 , 1 , 25 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
-1945 */{ 0 , 2 , 13 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1946 */{ 0 , 2 , 2 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
-1947 */{ 2 , 1 , 22 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
-1948 */{ 0 , 2 , 10 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1949 */{ 7 , 1 , 29 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-1950 */{ 0 , 2 , 17 , 27808 },/* 29 30 30 29 30 30 29 29 30 29 30 29 0 354
-1951 */{ 0 , 2 , 6 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1952 */{ 5 , 1 , 27 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-1953 */{ 0 , 2 , 14 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
-1954 */{ 0 , 2 , 3 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
-1955 */{ 3 , 1 , 24 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1956 */{ 0 , 2 , 12 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1957 */{ 8 , 1 , 31 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
-1958 */{ 0 , 2 , 18 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
-1959 */{ 0 , 2 , 8 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1960 */{ 6 , 1 , 28 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1961 */{ 0 , 2 , 15 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1962 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-1963 */{ 4 , 1 , 25 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1964 */{ 0 , 2 , 13 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1965 */{ 0 , 2 , 2 , 21088 },/* 29 30 29 30 29 29 30 29 29 30 30 29 0 353
-1966 */{ 3 , 1 , 21 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-1967 */{ 0 , 2 , 9 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
-1968 */{ 7 , 1 , 30 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1969 */{ 0 , 2 , 17 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1970 */{ 0 , 2 , 6 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-1971 */{ 5 , 1 , 27 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1972 */{ 0 , 2 , 15 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
-1973 */{ 0 , 2 , 3 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1974 */{ 4 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1975 */{ 0 , 2 , 11 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-1976 */{ 8 , 1 , 31 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
-1977 */{ 0 , 2 , 18 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
-1978 */{ 0 , 2 , 7 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355
-1979 */{ 6 , 1 , 28 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
-1980 */{ 0 , 2 , 16 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1981 */{ 0 , 2 , 5 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1982 */{ 4 , 1 , 25 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-1983 */{ 0 , 2 , 13 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1984 */{ 10 , 2 , 2 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1985 */{ 0 , 2 , 20 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
-1986 */{ 0 , 2 , 9 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
-1987 */{ 6 , 1 , 29 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 29 384
-1988 */{ 0 , 2 , 17 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1989 */{ 0 , 2 , 6 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355
-1990 */{ 5 , 1 , 27 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
-1991 */{ 0 , 2 , 15 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1992 */{ 0 , 2 , 4 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1993 */{ 3 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1994 */{ 0 , 2 , 10 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
-1995 */{ 8 , 1 , 31 , 27432 },/* 29 30 30 29 30 29 30 30 29 29 30 29 30 384
-1996 */{ 0 , 2 , 19 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354
-1997 */{ 0 , 2 , 7 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1998 */{ 5 , 1 , 28 , 37736 },/* 30 29 29 30 29 29 30 30 29 30 30 29 30 384
-1999 */{ 0 , 2 , 16 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-2000 */{ 0 , 2 , 5 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-2001 */{ 4 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-2002 */{ 0 , 2 , 12 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-2003 */{ 0 , 2 , 1 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-2004 */{ 2 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-2005 */{ 0 , 2 , 9 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-2006 */{ 7 , 1 , 29 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
-2007 */{ 0 , 2 , 18 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-2008 */{ 0 , 2 , 7 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
-2009 */{ 5 , 1 , 26 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
-2010 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-2011 */{ 0 , 2 , 3 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-2012 */{ 4 , 1 , 23 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-2013 */{ 0 , 2 , 10 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-2014 */{ 9 , 1 , 31 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-2015 */{ 0 , 2 , 19 , 19360 },/* 29 30 29 29 30 29 30 30 30 29 30 29 0 354
-2016 */{ 0 , 2 , 8 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
-2017 */{ 6 , 1 , 28 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-2018 */{ 0 , 2 , 16 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-2019 */{ 0 , 2 , 5 , 43312 },/* 30 29 30 29 30 29 29 30 29 29 30 30 0 354
-2020 */{ 4 , 1 , 25 , 29864 },/* 29 30 30 30 29 30 29 29 30 29 30 29 30 384
-2021 */{ 0 , 2 , 12 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-2022 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-2023 */{ 2 , 1 , 22 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
-2024 */{ 0 , 2 , 10 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-2025 */{ 6 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-2026 */{ 0 , 2 , 17 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
-2027 */{ 0 , 2 , 6 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-2028 */{ 5 , 1 , 26 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-2029 */{ 0 , 2 , 13 , 54576 },/* 30 30 29 30 29 30 29 30 29 29 30 30 0 355
-2030 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-2031 */{ 3 , 1 , 23 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
-2032 */{ 0 , 2 , 11 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-2033 */{ 11 , 1 , 31 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-2034 */{ 0 , 2 , 19 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
-2035 */{ 0 , 2 , 8 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-2036 */{ 6 , 1 , 28 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
-2037 */{ 0 , 2 , 15 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-2038 */{ 0 , 2 , 4 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
-2039 */{ 5 , 1 , 24 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
-2040 */{ 0 , 2 , 12 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
-2041 */{ 0 , 2 , 1 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-2042 */{ 2 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
-2043 */{ 0 , 2 , 10 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-2044 */{ 7 , 1 , 30 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-2045 */{ 0 , 2 , 17 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-2046 */{ 0 , 2 , 6 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
-2047 */{ 5 , 1 , 26 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-2048 */{ 0 , 2 , 14 , 27936 },/* 29 30 30 29 30 30 29 30 29 29 30 29 0 354
-2049 */{ 0 , 2 , 2 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
-2050 */{ 3 , 1 , 23 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-2051 */{ 0 , 2 , 11 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
-2052 */{ 8 , 2 , 1 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
-2053 */{ 0 , 2 , 19 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-2054 */{ 0 , 2 , 8 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-2055 */{ 6 , 1 , 28 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-2056 */{ 0 , 2 , 15 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
-2057 */{ 0 , 2 , 4 , 27424 },/* 29 30 30 29 30 29 30 30 29 29 30 29 0 354
-2058 */{ 4 , 1 , 24 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
-2059 */{ 0 , 2 , 12 , 43744 },/* 30 29 30 29 30 29 30 29 30 30 30 29 0 355
-2060 */{ 0 , 2 , 2 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-2061 */{ 3 , 1 , 21 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
-2062 */{ 0 , 2 , 9 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-2063 */{ 7 , 1 , 29 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-2064 */{ 0 , 2 , 17 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-2065 */{ 0 , 2 , 5 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-2066 */{ 5 , 1 , 26 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-2067 */{ 0 , 2 , 14 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-2068 */{ 0 , 2 , 3 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
-2069 */{ 4 , 1 , 23 , 21224 },/* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
-2070 */{ 0 , 2 , 11 , 21200 },/* 29 30 29 30 29 29 30 29 30 30 29 30 0 354
-2071 */{ 8 , 1 , 31 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-2072 */{ 0 , 2 , 19 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-2073 */{ 0 , 2 , 7 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-2074 */{ 6 , 1 , 27 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-2075 */{ 0 , 2 , 15 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-2076 */{ 0 , 2 , 5 , 21920 },/* 29 30 29 30 29 30 29 30 30 29 30 29 0 354
-2077 */{ 4 , 1 , 24 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
-2078 */{ 0 , 2 , 12 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
-2079 */{ 0 , 2 , 2 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-2080 */{ 3 , 1 , 22 , 43320 },/* 30 29 30 29 30 29 29 30 29 29 30 30 30 384
-2081 */{ 0 , 2 , 9 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354
-2082 */{ 7 , 1 , 29 , 29336 },/* 29 30 30 30 29 29 30 29 30 29 29 30 30 384
-2083 */{ 0 , 2 , 17 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-2084 */{ 0 , 2 , 6 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-2085 */{ 5 , 1 , 26 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
-2086 */{ 0 , 2 , 14 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-2087 */{ 0 , 2 , 3 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-2088 */{ 4 , 1 , 24 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
-2089 */{ 0 , 2 , 10 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-2090 */{ 8 , 1 , 30 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-2091 */{ 0 , 2 , 18 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
-2092 */{ 0 , 2 , 7 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
-2093 */{ 6 , 1 , 27 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
-2094 */{ 0 , 2 , 15 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-2095 */{ 0 , 2 , 5 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-2096 */{ 4 , 1 , 25 , 42216 },/* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
-2097 */{ 0 , 2 , 12 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-2098 */{ 0 , 2 , 1 , 53584 },/* 30 30 29 30 29 29 29 30 29 30 29 30 0 354
-2099 */{ 2 , 1 , 21 , 55592 },/* 30 30 29 30 30 29 29 30 29 29 30 29 30 384
-2100 */{ 0 , 2 , 9 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
- */};
-
+/*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
+1901 */ { 00, 02, 19, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1902 */ { 00, 02, 08, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1903 */ { 05, 01, 29, 0b0101001001101000 }, /* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
+1904 */ { 00, 02, 16, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
+1905 */ { 00, 02, 04, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
+1906 */ { 04, 01, 25, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1907 */ { 00, 02, 13, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1908 */ { 00, 02, 02, 0b1001101011010000 }, /* 30 29 29 30 30 29 30 29 30 30 29 30 355
+1909 */ { 02, 01, 22, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1910 */ { 00, 02, 10, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1911 */ { 06, 01, 30, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1912 */ { 00, 02, 18, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1913 */ { 00, 02, 06, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+1914 */ { 05, 01, 26, 0b1101010100101000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1915 */ { 00, 02, 14, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
+1916 */ { 00, 02, 03, 0b1101011010100000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 355
+1917 */ { 02, 01, 23, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1918 */ { 00, 02, 11, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1919 */ { 07, 02, 01, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1920 */ { 00, 02, 20, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1921 */ { 00, 02, 08, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1922 */ { 05, 01, 28, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1923 */ { 00, 02, 16, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
+1924 */ { 00, 02, 05, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
+1925 */ { 04, 01, 24, 0b1010110110101000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
+1926 */ { 00, 02, 13, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1927 */ { 00, 02, 02, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 355
+1928 */ { 02, 01, 23, 0b0100100101111000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+1929 */ { 00, 02, 10, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1930 */ { 06, 01, 30, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1931 */ { 00, 02, 17, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1932 */ { 00, 02, 06, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
+1933 */ { 05, 01, 26, 0b0110110101001000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
+1934 */ { 00, 02, 14, 0b0101101011010000 }, /* 29 30 29 30 30 29 30 29 30 30 29 30 355
+1935 */ { 00, 02, 04, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1936 */ { 03, 01, 24, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1937 */ { 00, 02, 11, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1938 */ { 07, 01, 31, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1939 */ { 00, 02, 19, 0b1100100101010000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 354
+1940 */ { 00, 02, 08, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1941 */ { 06, 01, 27, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1942 */ { 00, 02, 15, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1943 */ { 00, 02, 05, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1944 */ { 04, 01, 25, 0b1010101011011000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+1945 */ { 00, 02, 13, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+1946 */ { 00, 02, 02, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
+1947 */ { 02, 01, 22, 0b1100100101011000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+1948 */ { 00, 02, 10, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1949 */ { 07, 01, 29, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+1950 */ { 00, 02, 17, 0b0110110010100000 }, /* 29 30 30 29 30 30 29 29 30 29 30 29 354
+1951 */ { 00, 02, 06, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1952 */ { 05, 01, 27, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+1953 */ { 00, 02, 14, 0b0100110110100000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 354
+1954 */ { 00, 02, 03, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
+1955 */ { 03, 01, 24, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1956 */ { 00, 02, 12, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1957 */ { 08, 01, 31, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
+1958 */ { 00, 02, 18, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 355
+1959 */ { 00, 02, 08, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1960 */ { 06, 01, 28, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1961 */ { 00, 02, 15, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1962 */ { 00, 02, 05, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+1963 */ { 04, 01, 25, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1964 */ { 00, 02, 13, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1965 */ { 00, 02, 02, 0b0101001001100000 }, /* 29 30 29 30 29 29 30 29 29 30 30 29 353
+1966 */ { 03, 01, 21, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1967 */ { 00, 02, 09, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
+1968 */ { 07, 01, 30, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1969 */ { 00, 02, 17, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1970 */ { 00, 02, 06, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+1971 */ { 05, 01, 27, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1972 */ { 00, 02, 15, 0b0100101011010000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 354
+1973 */ { 00, 02, 03, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1974 */ { 04, 01, 23, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1975 */ { 00, 02, 11, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+1976 */ { 08, 01, 31, 0b1101010100101000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1977 */ { 00, 02, 18, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
+1978 */ { 00, 02, 07, 0b1011011010100000 }, /* 30 29 30 30 29 30 30 29 30 29 30 29 355
+1979 */ { 06, 01, 28, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1980 */ { 00, 02, 16, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1981 */ { 00, 02, 05, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1982 */ { 04, 01, 25, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1983 */ { 00, 02, 13, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1984 */ { 10, 02, 02, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1985 */ { 00, 02, 20, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
+1986 */ { 00, 02, 09, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
+1987 */ { 06, 01, 29, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 29 384
+1988 */ { 00, 02, 17, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+1989 */ { 00, 02, 06, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 355
+1990 */ { 05, 01, 27, 0b0100100101111000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+1991 */ { 00, 02, 15, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1992 */ { 00, 02, 04, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1993 */ { 03, 01, 23, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1994 */ { 00, 02, 10, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
+1995 */ { 08, 01, 31, 0b0110101100101000 }, /* 29 30 30 29 30 29 30 30 29 29 30 29 30 384
+1996 */ { 00, 02, 19, 0b0101101011000000 }, /* 29 30 29 30 30 29 30 29 30 30 29 29 354
+1997 */ { 00, 02, 07, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+1998 */ { 05, 01, 28, 0b1001001101101000 }, /* 30 29 29 30 29 29 30 30 29 30 30 29 30 384
+1999 */ { 00, 02, 16, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+2000 */ { 00, 02, 05, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+2001 */ { 04, 01, 24, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+2002 */ { 00, 02, 12, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+2003 */ { 00, 02, 01, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
+2004 */ { 02, 01, 22, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+2005 */ { 00, 02, 09, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+2006 */ { 07, 01, 29, 0b1010101011011000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+2007 */ { 00, 02, 18, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+2008 */ { 00, 02, 07, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
+2009 */ { 05, 01, 26, 0b1100100101011000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+2010 */ { 00, 02, 14, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+2011 */ { 00, 02, 03, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+2012 */ { 04, 01, 23, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+2013 */ { 00, 02, 10, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+2014 */ { 09, 01, 31, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2015 */ { 00, 02, 19, 0b0100101110100000 }, /* 29 30 29 29 30 29 30 30 30 29 30 29 354
+2016 */ { 00, 02, 08, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
+2017 */ { 06, 01, 28, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+2018 */ { 00, 02, 16, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+2019 */ { 00, 02, 05, 0b1010100100110000 }, /* 30 29 30 29 30 29 29 30 29 29 30 30 354
+2020 */ { 04, 01, 25, 0b0111010010101000 }, /* 29 30 30 30 29 30 29 29 30 29 30 29 30 384
+2021 */ { 00, 02, 12, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+2022 */ { 00, 02, 01, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+2023 */ { 02, 01, 22, 0b0100110110101000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+2024 */ { 00, 02, 10, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+2025 */ { 06, 01, 29, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+2026 */ { 00, 02, 17, 0b1010010011100000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 354
+2027 */ { 00, 02, 06, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
+2028 */ { 05, 01, 26, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+2029 */ { 00, 02, 13, 0b1101010100110000 }, /* 30 30 29 30 29 30 29 30 29 29 30 30 355
+2030 */ { 00, 02, 03, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+2031 */ { 03, 01, 23, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+2032 */ { 00, 02, 11, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+2033 */ { 11, 01, 31, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+2034 */ { 00, 02, 19, 0b0100101011010000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 354
+2035 */ { 00, 02, 08, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+2036 */ { 06, 01, 28, 0b1101001001011000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
+2037 */ { 00, 02, 15, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+2038 */ { 00, 02, 04, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
+2039 */ { 05, 01, 24, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
+2040 */ { 00, 02, 12, 0b1011010110100000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 355
+2041 */ { 00, 02, 01, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+2042 */ { 02, 01, 22, 0b0100101011011000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+2043 */ { 00, 02, 10, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+2044 */ { 07, 01, 30, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+2045 */ { 00, 02, 17, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+2046 */ { 00, 02, 06, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
+2047 */ { 05, 01, 26, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+2048 */ { 00, 02, 14, 0b0110110100100000 }, /* 29 30 30 29 30 30 29 30 29 29 30 29 354
+2049 */ { 00, 02, 02, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
+2050 */ { 03, 01, 23, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+2051 */ { 00, 02, 11, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
+2052 */ { 08, 02, 01, 0b0100100101111000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+2053 */ { 00, 02, 19, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+2054 */ { 00, 02, 08, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+2055 */ { 06, 01, 28, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+2056 */ { 00, 02, 15, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
+2057 */ { 00, 02, 04, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+2058 */ { 04, 01, 24, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
+2059 */ { 00, 02, 12, 0b1010101011100000 }, /* 30 29 30 29 30 29 30 29 30 30 30 29 355
+2060 */ { 00, 02, 02, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+2061 */ { 03, 01, 21, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
+2062 */ { 00, 02, 09, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+2063 */ { 07, 01, 29, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+2064 */ { 00, 02, 17, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+2065 */ { 00, 02, 05, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
+2066 */ { 05, 01, 26, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+2067 */ { 00, 02, 14, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+2068 */ { 00, 02, 03, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 355
+2069 */ { 04, 01, 23, 0b0101001011101000 }, /* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
+2070 */ { 00, 02, 11, 0b0101001011010000 }, /* 29 30 29 30 29 29 30 29 30 30 29 30 354
+2071 */ { 08, 01, 31, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+2072 */ { 00, 02, 19, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+2073 */ { 00, 02, 07, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+2074 */ { 06, 01, 27, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+2075 */ { 00, 02, 15, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+2076 */ { 00, 02, 05, 0b0101010110100000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 354
+2077 */ { 04, 01, 24, 0b1010010111010000 }, /* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
+2078 */ { 00, 02, 12, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
+2079 */ { 00, 02, 02, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+2080 */ { 03, 01, 22, 0b1010100100111000 }, /* 30 29 30 29 30 29 29 30 29 29 30 30 30 384
+2081 */ { 00, 02, 09, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 354
+2082 */ { 07, 01, 29, 0b0111001010011000 }, /* 29 30 30 30 29 29 30 29 30 29 29 30 30 384
+2083 */ { 00, 02, 17, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+2084 */ { 00, 02, 06, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+2085 */ { 05, 01, 26, 0b0100110110101000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+2086 */ { 00, 02, 14, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+2087 */ { 00, 02, 03, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+2088 */ { 04, 01, 24, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
+2089 */ { 00, 02, 10, 0b1101000101100000 }, /* 30 30 29 30 29 29 29 30 29 30 30 29 354
+2090 */ { 08, 01, 30, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+2091 */ { 00, 02, 18, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
+2092 */ { 00, 02, 07, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 355
+2093 */ { 06, 01, 27, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+2094 */ { 00, 02, 15, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+2095 */ { 00, 02, 05, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+2096 */ { 04, 01, 25, 0b1010010011101000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
+2097 */ { 00, 02, 12, 0b1010001011010000 }, /* 30 29 30 29 29 29 30 29 30 30 29 30 354
+2098 */ { 00, 02, 01, 0b1101000101010000 }, /* 30 30 29 30 29 29 29 30 29 30 29 30 354
+2099 */ { 02, 01, 21, 0b1101100100101000 }, /* 30 30 29 30 30 29 29 30 29 29 30 29 30 384
+2100 */ { 00, 02, 09, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
+ */ };
internal override int MinCalendarYear
{
@@ -315,7 +318,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"year",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range, MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR));
}
@@ -339,7 +342,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range, MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR));
}
@@ -374,7 +377,6 @@ namespace System.Globalization
}
}
-
public override int[] Eras
{
get
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Invariant.cs b/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Invariant.cs
index 29e4f5321..16201b8d1 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Invariant.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Invariant.cs
@@ -18,7 +18,7 @@ namespace System.Globalization
fixed (char* pSource = source) fixed (char* pValue = value)
{
char* pSrc = &pSource[startIndex];
- int index = InvariantFindString(pSrc, count, pValue, value.Length, ignoreCase, start : true);
+ int index = InvariantFindString(pSrc, count, pValue, value.Length, ignoreCase, fromBeginning : true);
if (index >= 0)
{
return index + startIndex;
@@ -27,7 +27,7 @@ namespace System.Globalization
}
}
- internal static unsafe int InvariantIndexOf(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase)
+ internal static unsafe int InvariantIndexOf(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase, bool fromBeginning = true)
{
Debug.Assert(source.Length != 0);
Debug.Assert(value.Length != 0);
@@ -35,7 +35,7 @@ namespace System.Globalization
fixed (char* pSource = &MemoryMarshal.GetReference(source))
fixed (char* pValue = &MemoryMarshal.GetReference(value))
{
- return InvariantFindString(pSource, source.Length, pValue, value.Length, ignoreCase, start: true);
+ return InvariantFindString(pSource, source.Length, pValue, value.Length, ignoreCase, fromBeginning);
}
}
@@ -48,7 +48,7 @@ namespace System.Globalization
fixed (char* pSource = source) fixed (char* pValue = value)
{
char* pSrc = &pSource[startIndex - count + 1];
- int index = InvariantFindString(pSrc, count, pValue, value.Length, ignoreCase, start : false);
+ int index = InvariantFindString(pSrc, count, pValue, value.Length, ignoreCase, fromBeginning : false);
if (index >= 0)
{
return index + startIndex - count + 1;
@@ -57,7 +57,7 @@ namespace System.Globalization
}
}
- private static unsafe int InvariantFindString(char* source, int sourceCount, char* value, int valueCount, bool ignoreCase, bool start)
+ private static unsafe int InvariantFindString(char* source, int sourceCount, char* value, int valueCount, bool ignoreCase, bool fromBeginning)
{
int ctrSource = 0; // index value into source
int ctrValue = 0; // index value into value
@@ -72,7 +72,7 @@ namespace System.Globalization
if (valueCount == 0)
{
- return start ? 0 : sourceCount - 1;
+ return fromBeginning ? 0 : sourceCount - 1;
}
if (sourceCount < valueCount)
@@ -80,7 +80,7 @@ namespace System.Globalization
return -1;
}
- if (start)
+ if (fromBeginning)
{
lastSourceStart = sourceCount - valueCount;
if (ignoreCase)
diff --git a/src/System.Private.CoreLib/src/System/Globalization/CompareInfo.Unix.cs b/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Unix.cs
index 40f0ab008..f51754009 100644
--- a/src/System.Private.CoreLib/src/System/Globalization/CompareInfo.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Unix.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Buffers;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -87,7 +88,7 @@ namespace System.Globalization
return -1;
}
- internal static unsafe int IndexOfOrdinalCore(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase)
+ internal static unsafe int IndexOfOrdinalCore(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase, bool fromBeginning)
{
Debug.Assert(!GlobalizationMode.Invariant);
@@ -104,13 +105,29 @@ namespace System.Globalization
fixed (char* pSource = &MemoryMarshal.GetReference(source))
fixed (char* pValue = &MemoryMarshal.GetReference(value))
{
- int index = Interop.Globalization.IndexOfOrdinalIgnoreCase(pValue, value.Length, pSource, source.Length, findLast: false);
- return index;
+ return Interop.Globalization.IndexOfOrdinalIgnoreCase(pValue, value.Length, pSource, source.Length, findLast: !fromBeginning);
}
}
- int endIndex = source.Length - value.Length;
- for (int i = 0; i <= endIndex; i++)
+ int startIndex, endIndex, jump;
+ if (fromBeginning)
+ {
+ // Left to right, from zero to last possible index in the source string.
+ // Incrementing by one after each iteration. Stop condition is last possible index plus 1.
+ startIndex = 0;
+ endIndex = source.Length - value.Length + 1;
+ jump = 1;
+ }
+ else
+ {
+ // Right to left, from first possible index in the source string to zero.
+ // Decrementing by one after each iteration. Stop condition is last possible index minus 1.
+ startIndex = source.Length - value.Length;
+ endIndex = -1;
+ jump = -1;
+ }
+
+ for (int i = startIndex; i != endIndex; i += jump)
{
int valueIndex, sourceIndex;
@@ -177,11 +194,15 @@ namespace System.Globalization
return -1;
}
- private static unsafe int CompareStringOrdinalIgnoreCase(char* string1, int count1, char* string2, int count2)
+ private static unsafe int CompareStringOrdinalIgnoreCase(ref char string1, int count1, ref char string2, int count2)
{
Debug.Assert(!GlobalizationMode.Invariant);
- return Interop.Globalization.CompareStringOrdinalIgnoreCase(string1, count1, string2, count2);
+ fixed (char* char1 = &string1)
+ fixed (char* char2 = &string2)
+ {
+ return Interop.Globalization.CompareStringOrdinalIgnoreCase(char1, count1, char2, count2);
+ }
}
// TODO https://github.com/dotnet/coreclr/issues/13827:
@@ -224,7 +245,7 @@ namespace System.Globalization
if (target.Length == 0)
{
- if(matchLengthPtr != null)
+ if (matchLengthPtr != null)
*matchLengthPtr = 0;
return startIndex;
}
@@ -232,35 +253,38 @@ namespace System.Globalization
if (options == CompareOptions.Ordinal)
{
index = IndexOfOrdinal(source, target, startIndex, count, ignoreCase: false);
- if(index != -1)
+ if (index != -1)
{
- if(matchLengthPtr != null)
+ if (matchLengthPtr != null)
*matchLengthPtr = target.Length;
}
return index;
}
+
#if CORECLR
if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options) && source.IsFastSort() && target.IsFastSort())
{
index = IndexOf(source, target, startIndex, count, GetOrdinalCompareOptions(options));
- if(index != -1)
+ if (index != -1)
{
- if(matchLengthPtr != null)
+ if (matchLengthPtr != null)
*matchLengthPtr = target.Length;
}
return index;
}
#endif
+
fixed (char* pSource = source)
+ fixed (char* pTarget = target)
{
- index = Interop.Globalization.IndexOf(_sortHandle, target, target.Length, pSource + startIndex, count, options, matchLengthPtr);
+ index = Interop.Globalization.IndexOf(_sortHandle, pTarget, target.Length, pSource + startIndex, count, options, matchLengthPtr);
return index != -1 ? index + startIndex : -1;
}
}
// For now, this method is only called from Span APIs with either options == CompareOptions.None or CompareOptions.IgnoreCase
- internal unsafe int IndexOfCore(ReadOnlySpan<char> source, ReadOnlySpan<char> target, CompareOptions options, int* matchLengthPtr)
+ internal unsafe int IndexOfCore(ReadOnlySpan<char> source, ReadOnlySpan<char> target, CompareOptions options, int* matchLengthPtr, bool fromBeginning)
{
Debug.Assert(!_invariantMode);
Debug.Assert(source.Length != 0);
@@ -269,25 +293,29 @@ namespace System.Globalization
if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options))
{
if ((options & CompareOptions.IgnoreCase) == CompareOptions.IgnoreCase)
- {
- return IndexOfOrdinalIgnoreCaseHelper(source, target, options, matchLengthPtr);
- }
+ return IndexOfOrdinalIgnoreCaseHelper(source, target, options, matchLengthPtr, fromBeginning);
else
- {
- return IndexOfOrdinalHelper(source, target, options, matchLengthPtr);
- }
+ return IndexOfOrdinalHelper(source, target, options, matchLengthPtr, fromBeginning);
}
else
{
fixed (char* pSource = &MemoryMarshal.GetReference(source))
fixed (char* pTarget = &MemoryMarshal.GetReference(target))
{
- return Interop.Globalization.IndexOf(_sortHandle, pTarget, target.Length, pSource, source.Length, options, matchLengthPtr);
+ if (fromBeginning)
+ return Interop.Globalization.IndexOf(_sortHandle, pTarget, target.Length, pSource, source.Length, options, matchLengthPtr);
+ else
+ return Interop.Globalization.LastIndexOf(_sortHandle, pTarget, target.Length, pSource, source.Length, options);
}
}
}
- private unsafe int IndexOfOrdinalIgnoreCaseHelper(ReadOnlySpan<char> source, ReadOnlySpan<char> target, CompareOptions options, int* matchLengthPtr)
+ /// <summary>
+ /// Duplicate of IndexOfOrdinalHelper that also handles ignore case. Can't converge both methods
+ /// as the JIT wouldn't be able to optimize the ignoreCase path away.
+ /// </summary>
+ /// <returns></returns>
+ private unsafe int IndexOfOrdinalIgnoreCaseHelper(ReadOnlySpan<char> source, ReadOnlySpan<char> target, CompareOptions options, int* matchLengthPtr, bool fromBeginning)
{
Debug.Assert(!_invariantMode);
@@ -300,9 +328,8 @@ namespace System.Globalization
{
char* a = ap;
char* b = bp;
- int endIndex = source.Length - target.Length;
- if (endIndex < 0)
+ if (target.Length > source.Length)
goto InteropCall;
for (int j = 0; j < target.Length; j++)
@@ -312,20 +339,36 @@ namespace System.Globalization
goto InteropCall;
}
- int i = 0;
- for (; i <= endIndex; i++)
+ int startIndex, endIndex, jump;
+ if (fromBeginning)
+ {
+ // Left to right, from zero to last possible index in the source string.
+ // Incrementing by one after each iteration. Stop condition is last possible index plus 1.
+ startIndex = 0;
+ endIndex = source.Length - target.Length + 1;
+ jump = 1;
+ }
+ else
+ {
+ // Right to left, from first possible index in the source string to zero.
+ // Decrementing by one after each iteration. Stop condition is last possible index minus 1.
+ startIndex = source.Length - target.Length;
+ endIndex = -1;
+ jump = -1;
+ }
+
+ for (int i = startIndex; i != endIndex; i += jump)
{
int targetIndex = 0;
int sourceIndex = i;
- for (; targetIndex < target.Length; targetIndex++)
+ for (; targetIndex < target.Length; targetIndex++, sourceIndex++)
{
char valueChar = *(a + sourceIndex);
char targetChar = *(b + targetIndex);
if (valueChar == targetChar && valueChar < 0x80 && !s_highCharTable[valueChar])
{
- sourceIndex++;
continue;
}
@@ -339,7 +382,6 @@ namespace System.Globalization
goto InteropCall;
else if (valueChar != targetChar)
break;
- sourceIndex++;
}
if (targetIndex == target.Length)
@@ -349,14 +391,17 @@ namespace System.Globalization
return i;
}
}
- if (i > endIndex)
- return -1;
- InteropCall:
- return Interop.Globalization.IndexOf(_sortHandle, b, target.Length, a, source.Length, options, matchLengthPtr);
+
+ return -1;
+ InteropCall:
+ if (fromBeginning)
+ return Interop.Globalization.IndexOf(_sortHandle, b, target.Length, a, source.Length, options, matchLengthPtr);
+ else
+ return Interop.Globalization.LastIndexOf(_sortHandle, b, target.Length, a, source.Length, options);
}
}
- private unsafe int IndexOfOrdinalHelper(ReadOnlySpan<char> source, ReadOnlySpan<char> target, CompareOptions options, int* matchLengthPtr)
+ private unsafe int IndexOfOrdinalHelper(ReadOnlySpan<char> source, ReadOnlySpan<char> target, CompareOptions options, int* matchLengthPtr, bool fromBeginning)
{
Debug.Assert(!_invariantMode);
@@ -369,9 +414,8 @@ namespace System.Globalization
{
char* a = ap;
char* b = bp;
- int endIndex = source.Length - target.Length;
- if (endIndex < 0)
+ if (target.Length > source.Length)
goto InteropCall;
for (int j = 0; j < target.Length; j++)
@@ -381,21 +425,38 @@ namespace System.Globalization
goto InteropCall;
}
- int i = 0;
- for (; i <= endIndex; i++)
+ int startIndex, endIndex, jump;
+ if (fromBeginning)
+ {
+ // Left to right, from zero to last possible index in the source string.
+ // Incrementing by one after each iteration. Stop condition is last possible index plus 1.
+ startIndex = 0;
+ endIndex = source.Length - target.Length + 1;
+ jump = 1;
+ }
+ else
+ {
+ // Right to left, from first possible index in the source string to zero.
+ // Decrementing by one after each iteration. Stop condition is last possible index minus 1.
+ startIndex = source.Length - target.Length;
+ endIndex = -1;
+ jump = -1;
+ }
+
+ for (int i = startIndex; i != endIndex; i += jump)
{
int targetIndex = 0;
int sourceIndex = i;
- for (; targetIndex < target.Length; targetIndex++)
+ for (; targetIndex < target.Length; targetIndex++, sourceIndex++)
{
char valueChar = *(a + sourceIndex);
char targetChar = *(b + targetIndex);
+
if (valueChar >= 0x80 || s_highCharTable[valueChar])
goto InteropCall;
else if (valueChar != targetChar)
break;
- sourceIndex++;
}
if (targetIndex == target.Length)
@@ -405,10 +466,13 @@ namespace System.Globalization
return i;
}
}
- if (i > endIndex)
- return -1;
+
+ return -1;
InteropCall:
- return Interop.Globalization.IndexOf(_sortHandle, b, target.Length, a, source.Length, options, matchLengthPtr);
+ if (fromBeginning)
+ return Interop.Globalization.IndexOf(_sortHandle, b, target.Length, a, source.Length, options, matchLengthPtr);
+ else
+ return Interop.Globalization.LastIndexOf(_sortHandle, b, target.Length, a, source.Length, options);
}
}
@@ -442,8 +506,9 @@ namespace System.Globalization
int leftStartIndex = (startIndex - count + 1);
fixed (char* pSource = source)
+ fixed (char* pTarget = target)
{
- int lastIndex = Interop.Globalization.LastIndexOf(_sortHandle, target, target.Length, pSource + (startIndex - count + 1), count, options);
+ int lastIndex = Interop.Globalization.LastIndexOf(_sortHandle, pTarget, target.Length, pSource + (startIndex - count + 1), count, options);
return lastIndex != -1 ? lastIndex + leftStartIndex : -1;
}
@@ -599,7 +664,7 @@ namespace System.Globalization
return Interop.Globalization.EndsWith(_sortHandle, suffix, suffix.Length, source, source.Length, options);
}
-
+
private unsafe bool EndsWith(ReadOnlySpan<char> source, ReadOnlySpan<char> suffix, CompareOptions options)
{
Debug.Assert(!_invariantMode);
@@ -715,7 +780,7 @@ namespace System.Globalization
}
}
- private unsafe SortKey CreateSortKey(String source, CompareOptions options)
+ private unsafe SortKey CreateSortKey(string source, CompareOptions options)
{
Debug.Assert(!_invariantMode);
@@ -738,14 +803,17 @@ namespace System.Globalization
fixed (byte* pSortKey = keyData)
{
- Interop.Globalization.GetSortKey(_sortHandle, source, source.Length, pSortKey, sortKeyLength, options);
+ if (Interop.Globalization.GetSortKey(_sortHandle, source, source.Length, pSortKey, sortKeyLength, options) != sortKeyLength)
+ {
+ throw new ArgumentException(SR.Arg_ExternalException);
+ }
}
}
return new SortKey(Name, source, options, keyData);
}
- private unsafe static bool IsSortable(char *text, int length)
+ private static unsafe bool IsSortable(char *text, int length)
{
Debug.Assert(!GlobalizationMode.Invariant);
@@ -754,12 +822,12 @@ namespace System.Globalization
while (index < length)
{
- if (Char.IsHighSurrogate(text[index]))
+ if (char.IsHighSurrogate(text[index]))
{
- if (index == length - 1 || !Char.IsLowSurrogate(text[index+1]))
+ if (index == length - 1 || !char.IsLowSurrogate(text[index+1]))
return false; // unpaired surrogate
- uc = CharUnicodeInfo.GetUnicodeCategory(Char.ConvertToUtf32(text[index], text[index+1]));
+ uc = CharUnicodeInfo.GetUnicodeCategory(char.ConvertToUtf32(text[index], text[index+1]));
if (uc == UnicodeCategory.PrivateUse || uc == UnicodeCategory.OtherNotAssigned)
return false;
@@ -767,7 +835,7 @@ namespace System.Globalization
continue;
}
- if (Char.IsLowSurrogate(text[index]))
+ if (char.IsLowSurrogate(text[index]))
{
return false; // unpaired surrogate
}
@@ -802,45 +870,28 @@ namespace System.Globalization
int sortKeyLength = Interop.Globalization.GetSortKey(_sortHandle, source, source.Length, null, 0, options);
- // As an optimization, for small sort keys we allocate the buffer on the stack.
- if (sortKeyLength <= 256)
- {
- byte* pSortKey = stackalloc byte[sortKeyLength];
- Interop.Globalization.GetSortKey(_sortHandle, source, source.Length, pSortKey, sortKeyLength, options);
- return InternalHashSortKey(pSortKey, sortKeyLength);
- }
-
- byte[] sortKey = new byte[sortKeyLength];
+ byte[] borrowedArr = null;
+ Span<byte> span = sortKeyLength <= 512 ?
+ stackalloc byte[512] :
+ (borrowedArr = ArrayPool<byte>.Shared.Rent(sortKeyLength));
- fixed (byte* pSortKey = &sortKey[0])
+ fixed (byte* pSortKey = &MemoryMarshal.GetReference(span))
{
- Interop.Globalization.GetSortKey(_sortHandle, source, source.Length, pSortKey, sortKeyLength, options);
- return InternalHashSortKey(pSortKey, sortKeyLength);
+ if (Interop.Globalization.GetSortKey(_sortHandle, source, source.Length, pSortKey, sortKeyLength, options) != sortKeyLength)
+ {
+ throw new ArgumentException(SR.Arg_ExternalException);
+ }
}
- }
- private static unsafe int InternalHashSortKey(byte* sortKey, int sortKeyLength)
- {
- // TODO: Random hashing is yet to be done
- // Active Issue: https://github.com/dotnet/corert/issues/2588
+ int hash = Marvin.ComputeHash32(span.Slice(0, sortKeyLength), Marvin.DefaultSeed);
- int hash1 = 5381;
- int hash2 = hash1;
- if (sortKeyLength == 0)
- {
- return 0;
- }
- if (sortKeyLength == 1)
+ // Return the borrowed array if necessary.
+ if (borrowedArr != null)
{
- return (((hash1 << 5) + hash1) ^ sortKey[0]) + (hash2 * 1566083941);
+ ArrayPool<byte>.Shared.Return(borrowedArr);
}
- for (int i = 0; i < (sortKeyLength & ~1); i += 2)
- {
- hash1 = ((hash1 << 5) + hash1) ^ sortKey[i];
- hash2 = ((hash2 << 5) + hash2) ^ sortKey[i+1];
- }
- return hash1 + (hash2 * 1566083941);
+ return hash;
}
private static CompareOptions GetOrdinalCompareOptions(CompareOptions options)
diff --git a/src/System.Private.CoreLib/src/System/Globalization/CompareInfo.Windows.cs b/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Windows.cs
index c0befb263..d1b12c664 100644
--- a/src/System.Private.CoreLib/src/System/Globalization/CompareInfo.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.Windows.cs
@@ -2,7 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Buffers;
using System.Diagnostics;
+using System.Security;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace System.Globalization
@@ -37,6 +40,8 @@ namespace System.Globalization
bool bIgnoreCase)
{
Debug.Assert(!GlobalizationMode.Invariant);
+ Debug.Assert(stringSource != null);
+ Debug.Assert(value != null);
fixed (char* pSource = stringSource)
fixed (char* pValue = value)
@@ -51,7 +56,7 @@ namespace System.Globalization
return ret < 0 ? ret : ret + offset;
}
}
-
+
private static unsafe int FindStringOrdinal(
uint dwFindStringOrdinalFlags,
ReadOnlySpan<char> source,
@@ -59,6 +64,8 @@ namespace System.Globalization
bool bIgnoreCase)
{
Debug.Assert(!GlobalizationMode.Invariant);
+ Debug.Assert(!source.IsEmpty);
+ Debug.Assert(!value.IsEmpty);
fixed (char* pSource = &MemoryMarshal.GetReference(source))
fixed (char* pValue = &MemoryMarshal.GetReference(value))
@@ -84,14 +91,15 @@ namespace System.Globalization
return FindStringOrdinal(FIND_FROMSTART, source, startIndex, count, value, value.Length, ignoreCase);
}
- internal static int IndexOfOrdinalCore(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase)
+ internal static int IndexOfOrdinalCore(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase, bool fromBeginning)
{
Debug.Assert(!GlobalizationMode.Invariant);
Debug.Assert(source.Length != 0);
Debug.Assert(value.Length != 0);
- return FindStringOrdinal(FIND_FROMSTART, source, value, ignoreCase);
+ uint positionFlag = fromBeginning ? (uint)FIND_FROMSTART : FIND_FROMEND;
+ return FindStringOrdinal(positionFlag, source, value, ignoreCase);
}
internal static int LastIndexOfOrdinalCore(string source, string value, int startIndex, int count, bool ignoreCase)
@@ -116,29 +124,59 @@ namespace System.Globalization
return 0;
}
- int tmpHash = 0;
+ uint flags = LCMAP_SORTKEY | (uint)GetNativeCompareFlags(options);
fixed (char* pSource = source)
{
- if (Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
- LCMAP_HASH | (uint)GetNativeCompareFlags(options),
+ int sortKeyLength = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
+ flags,
pSource, source.Length,
- &tmpHash, sizeof(int),
- null, null, _sortHandle) == 0)
+ null, 0,
+ null, null, _sortHandle);
+ if (sortKeyLength == 0)
{
- Environment.FailFast("LCMapStringEx failed!");
+ throw new ArgumentException(SR.Arg_ExternalException);
}
- }
- return tmpHash;
+ byte[] borrowedArr = null;
+ Span<byte> span = sortKeyLength <= 512 ?
+ stackalloc byte[512] :
+ (borrowedArr = ArrayPool<byte>.Shared.Rent(sortKeyLength));
+
+ fixed (byte* pSortKey = &MemoryMarshal.GetReference(span))
+ {
+ if (Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
+ flags,
+ pSource, source.Length,
+ pSortKey, sortKeyLength,
+ null, null, _sortHandle) != sortKeyLength)
+ {
+ throw new ArgumentException(SR.Arg_ExternalException);
+ }
+ }
+
+ int hash = Marvin.ComputeHash32(span.Slice(0, sortKeyLength), Marvin.DefaultSeed);
+
+ // Return the borrowed array if necessary.
+ if (borrowedArr != null)
+ {
+ ArrayPool<byte>.Shared.Return(borrowedArr);
+ }
+
+ return hash;
+ }
}
- private static unsafe int CompareStringOrdinalIgnoreCase(char* string1, int count1, char* string2, int count2)
+ private static unsafe int CompareStringOrdinalIgnoreCase(ref char string1, int count1, ref char string2, int count2)
{
Debug.Assert(!GlobalizationMode.Invariant);
- // Use the OS to compare and then convert the result to expected value by subtracting 2
- return Interop.Kernel32.CompareStringOrdinal(string1, count1, string2, count2, true) - 2;
+ fixed (char* char1 = &string1)
+ fixed (char* char2 = &string2)
+ {
+ // Use the OS to compare and then convert the result to expected value by subtracting 2
+ return Interop.Kernel32.CompareStringOrdinal(char1, count1, char2, count2, true) - 2;
+ }
}
// TODO https://github.com/dotnet/coreclr/issues/13827:
@@ -156,6 +194,7 @@ namespace System.Globalization
fixed (char* pString1 = &MemoryMarshal.GetReference(string1))
fixed (char* pString2 = &string2.GetRawStringData())
{
+ Debug.Assert(pString1 != null);
int result = Interop.Kernel32.CompareStringEx(
pLocaleName,
(uint)GetNativeCompareFlags(options),
@@ -169,7 +208,7 @@ namespace System.Globalization
if (result == 0)
{
- Environment.FailFast("CompareStringEx failed");
+ throw new ArgumentException(SR.Arg_ExternalException);
}
// Map CompareStringEx return value to -1, 0, 1.
@@ -188,6 +227,8 @@ namespace System.Globalization
fixed (char* pString1 = &MemoryMarshal.GetReference(string1))
fixed (char* pString2 = &MemoryMarshal.GetReference(string2))
{
+ Debug.Assert(pString1 != null);
+ Debug.Assert(pString2 != null);
int result = Interop.Kernel32.CompareStringEx(
pLocaleName,
(uint)GetNativeCompareFlags(options),
@@ -201,7 +242,7 @@ namespace System.Globalization
if (result == 0)
{
- Environment.FailFast("CompareStringEx failed");
+ throw new ArgumentException(SR.Arg_ExternalException);
}
// Map CompareStringEx return value to -1, 0, 1.
@@ -210,12 +251,14 @@ namespace System.Globalization
}
private unsafe int FindString(
- uint dwFindNLSStringFlags,
- ReadOnlySpan<char> lpStringSource,
- ReadOnlySpan<char> lpStringValue,
- int* pcchFound)
+ uint dwFindNLSStringFlags,
+ ReadOnlySpan<char> lpStringSource,
+ ReadOnlySpan<char> lpStringValue,
+ int* pcchFound)
{
Debug.Assert(!_invariantMode);
+ Debug.Assert(!lpStringSource.IsEmpty);
+ Debug.Assert(!lpStringValue.IsEmpty);
string localeName = _sortHandle != IntPtr.Zero ? null : _sortName;
@@ -236,18 +279,20 @@ namespace System.Globalization
_sortHandle);
}
}
-
+
private unsafe int FindString(
- uint dwFindNLSStringFlags,
- string lpStringSource,
- int startSource,
- int cchSource,
- string lpStringValue,
- int startValue,
- int cchValue,
- int* pcchFound)
+ uint dwFindNLSStringFlags,
+ string lpStringSource,
+ int startSource,
+ int cchSource,
+ string lpStringValue,
+ int startValue,
+ int cchValue,
+ int* pcchFound)
{
Debug.Assert(!_invariantMode);
+ Debug.Assert(lpStringSource != null);
+ Debug.Assert(lpStringValue != null);
string localeName = _sortHandle != IntPtr.Zero ? null : _sortName;
@@ -274,39 +319,38 @@ namespace System.Globalization
internal unsafe int IndexOfCore(string source, string target, int startIndex, int count, CompareOptions options, int* matchLengthPtr)
{
- Debug.Assert(!string.IsNullOrEmpty(source));
+ Debug.Assert(!_invariantMode);
+
+ Debug.Assert(source != null);
Debug.Assert(target != null);
Debug.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0);
- int index;
-
- // TODO: Consider moving this up to the relevent APIs we need to ensure this behavior for
- // and add a precondition that target is not empty.
if (target.Length == 0)
{
- if(matchLengthPtr != null)
+ if (matchLengthPtr != null)
*matchLengthPtr = 0;
- return startIndex; // keep Whidbey compatibility
+ return startIndex;
}
- if ((options & CompareOptions.Ordinal) != 0)
+ if (source.Length == 0)
{
- index = FastIndexOfString(source, target, startIndex, count, target.Length, findLastIndex: false);
- if(index != -1 && matchLengthPtr != null)
- *matchLengthPtr = target.Length;
+ return -1;
+ }
- return index;
+ if ((options & CompareOptions.Ordinal) != 0)
+ {
+ int retValue = FastIndexOfString(source, target, startIndex, count, target.Length, findLastIndex: false);
+ if (retValue >= 0)
+ {
+ if (matchLengthPtr != null)
+ *matchLengthPtr = target.Length;
+ }
+ return retValue;
}
else
{
- int retValue = FindString(FIND_FROMSTART | (uint)GetNativeCompareFlags(options),
- source,
- startIndex,
- count,
- target,
- 0,
- target.Length,
- matchLengthPtr);
+ int retValue = FindString(FIND_FROMSTART | (uint)GetNativeCompareFlags(options), source, startIndex, count,
+ target, 0, target.Length, matchLengthPtr);
if (retValue >= 0)
{
return retValue + startIndex;
@@ -316,7 +360,7 @@ namespace System.Globalization
return -1;
}
- internal unsafe int IndexOfCore(ReadOnlySpan<char> source, ReadOnlySpan<char> target, CompareOptions options, int* matchLengthPtr)
+ internal unsafe int IndexOfCore(ReadOnlySpan<char> source, ReadOnlySpan<char> target, CompareOptions options, int* matchLengthPtr, bool fromBeginning)
{
Debug.Assert(!_invariantMode);
@@ -324,8 +368,8 @@ namespace System.Globalization
Debug.Assert(target.Length != 0);
Debug.Assert((options == CompareOptions.None || options == CompareOptions.IgnoreCase));
- int retValue = FindString(FIND_FROMSTART | (uint)GetNativeCompareFlags(options), source, target, matchLengthPtr);
- return retValue;
+ uint positionFlag = fromBeginning ? (uint)FIND_FROMSTART : FIND_FROMEND;
+ return FindString(positionFlag | (uint)GetNativeCompareFlags(options), source, target, matchLengthPtr);
}
private unsafe int LastIndexOfCore(string source, string target, int startIndex, int count, CompareOptions options)
@@ -336,10 +380,8 @@ namespace System.Globalization
Debug.Assert(target != null);
Debug.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0);
- // TODO: Consider moving this up to the relevent APIs we need to ensure this behavior for
- // and add a precondition that target is not empty.
if (target.Length == 0)
- return startIndex; // keep Whidbey compatibility
+ return startIndex;
if ((options & CompareOptions.Ordinal) != 0)
{
@@ -347,14 +389,8 @@ namespace System.Globalization
}
else
{
- int retValue = FindString(FIND_FROMEND | (uint)GetNativeCompareFlags(options),
- source,
- startIndex - count + 1,
- count,
- target,
- 0,
- target.Length,
- null);
+ int retValue = FindString(FIND_FROMEND | (uint)GetNativeCompareFlags(options), source, startIndex - count + 1,
+ count, target, 0, target.Length, null);
if (retValue >= 0)
{
@@ -373,14 +409,8 @@ namespace System.Globalization
Debug.Assert(!string.IsNullOrEmpty(prefix));
Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
- return FindString(FIND_STARTSWITH | (uint)GetNativeCompareFlags(options),
- source,
- 0,
- source.Length,
- prefix,
- 0,
- prefix.Length,
- null) >= 0;
+ return FindString(FIND_STARTSWITH | (uint)GetNativeCompareFlags(options), source, 0, source.Length,
+ prefix, 0, prefix.Length, null) >= 0;
}
private unsafe bool StartsWith(ReadOnlySpan<char> source, ReadOnlySpan<char> prefix, CompareOptions options)
@@ -402,14 +432,8 @@ namespace System.Globalization
Debug.Assert(!string.IsNullOrEmpty(suffix));
Debug.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
- return FindString(FIND_ENDSWITH | (uint)GetNativeCompareFlags(options),
- source,
- 0,
- source.Length,
- suffix,
- 0,
- suffix.Length,
- null) >= 0;
+ return FindString(FIND_ENDSWITH | (uint)GetNativeCompareFlags(options), source, 0, source.Length,
+ suffix, 0, suffix.Length, null) >= 0;
}
private unsafe bool EndsWith(ReadOnlySpan<char> source, ReadOnlySpan<char> suffix, CompareOptions options)
@@ -428,7 +452,7 @@ namespace System.Globalization
private IntPtr _sortHandle;
private const uint LCMAP_SORTKEY = 0x00000400;
- private const uint LCMAP_HASH = 0x00040000;
+ private const uint LCMAP_HASH = 0x00040000;
private const int FIND_STARTSWITH = 0x00100000;
private const int FIND_ENDSWITH = 0x00200000;
@@ -510,7 +534,7 @@ namespace System.Globalization
return retValue;
}
- private unsafe SortKey CreateSortKey(String source, CompareOptions options)
+ private unsafe SortKey CreateSortKey(string source, CompareOptions options)
{
Debug.Assert(!_invariantMode);
@@ -528,27 +552,32 @@ namespace System.Globalization
}
else
{
+ uint flags = LCMAP_SORTKEY | (uint)GetNativeCompareFlags(options);
+
fixed (char *pSource = source)
{
- int result = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
- LCMAP_SORTKEY | (uint) GetNativeCompareFlags(options),
+ int sortKeyLength = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
+ flags,
pSource, source.Length,
null, 0,
null, null, _sortHandle);
- if (result == 0)
+ if (sortKeyLength == 0)
{
- throw new ArgumentException(SR.Argument_InvalidFlag, "source");
+ throw new ArgumentException(SR.Arg_ExternalException);
}
- keyData = new byte[result];
+ keyData = new byte[sortKeyLength];
fixed (byte* pBytes = keyData)
{
- result = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
- LCMAP_SORTKEY | (uint) GetNativeCompareFlags(options),
+ if (Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
+ flags,
pSource, source.Length,
pBytes, keyData.Length,
- null, null, _sortHandle);
+ null, null, _sortHandle) != sortKeyLength)
+ {
+ throw new ArgumentException(SR.Arg_ExternalException);
+ }
}
}
}
@@ -559,6 +588,7 @@ namespace System.Globalization
private static unsafe bool IsSortable(char* text, int length)
{
Debug.Assert(!GlobalizationMode.Invariant);
+ Debug.Assert(text != null);
return Interop.Kernel32.IsNLSDefinedString(Interop.Kernel32.COMPARE_STRING, 0, IntPtr.Zero, text, length);
}
@@ -606,6 +636,7 @@ namespace System.Globalization
Debug.Assert(!_invariantMode);
Interop.Kernel32.NlsVersionInfoEx nlsVersion = new Interop.Kernel32.NlsVersionInfoEx();
+ nlsVersion.dwNLSVersionInfoSize = sizeof(Interop.Kernel32.NlsVersionInfoEx);
Interop.Kernel32.GetNLSVersionEx(Interop.Kernel32.COMPARE_STRING, _sortName, &nlsVersion);
return new SortVersion(
nlsVersion.dwNLSVersion,
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.cs b/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.cs
index c369c816b..92742c7b9 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CompareInfo.cs
@@ -16,6 +16,8 @@ using System.Reflection;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
+using System.Buffers;
+using Internal.Runtime.CompilerServices;
namespace System.Globalization
{
@@ -105,7 +107,7 @@ namespace System.Globalization
{
throw new ArgumentNullException(nameof(assembly));
}
- if (assembly != typeof(Object).Module.Assembly)
+ if (assembly != typeof(object).Module.Assembly)
{
throw new ArgumentException(SR.Argument_OnlyMscorlib);
}
@@ -132,7 +134,7 @@ namespace System.Globalization
throw new ArgumentNullException(name == null ? nameof(name) : nameof(assembly));
}
- if (assembly != typeof(Object).Module.Assembly)
+ if (assembly != typeof(object).Module.Assembly)
{
throw new ArgumentException(SR.Argument_OnlyMscorlib);
}
@@ -302,7 +304,7 @@ namespace System.Globalization
{
if (options == CompareOptions.OrdinalIgnoreCase)
{
- return String.Compare(string1, string2, StringComparison.OrdinalIgnoreCase);
+ return string.Compare(string1, string2, StringComparison.OrdinalIgnoreCase);
}
// Verify the options before we do any real comparison.
@@ -313,7 +315,7 @@ namespace System.Globalization
throw new ArgumentException(SR.Argument_CompareOptionOrdinal, nameof(options));
}
- return String.CompareOrdinal(string1, string2);
+ return string.CompareOrdinal(string1, string2);
}
if ((options & ValidCompareMaskOffFlags) != 0)
@@ -339,9 +341,9 @@ namespace System.Globalization
if (_invariantMode)
{
if ((options & CompareOptions.IgnoreCase) != 0)
- return CompareOrdinalIgnoreCase(string1, 0, string1.Length, string2, 0, string2.Length);
+ return CompareOrdinalIgnoreCase(string1, string2);
- return String.CompareOrdinal(string1, string2);
+ return string.CompareOrdinal(string1, string2);
}
return CompareString(string1.AsSpan(), string2.AsSpan(), options);
@@ -389,38 +391,26 @@ namespace System.Globalization
return CompareString(string1, string2, options);
}
- // TODO https://github.com/dotnet/corefx/issues/21395: Expose this publicly?
- internal virtual int Compare(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2, CompareOptions options)
+ internal int CompareOptionNone(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2)
{
- if (options == CompareOptions.OrdinalIgnoreCase)
- {
- return CompareOrdinalIgnoreCase(string1, string2);
- }
+ // Check for empty span or span from a null string
+ if (string1.Length == 0 || string2.Length == 0)
+ return string1.Length - string2.Length;
- // Verify the options before we do any real comparison.
- if ((options & CompareOptions.Ordinal) != 0)
- {
- if (options != CompareOptions.Ordinal)
- {
- throw new ArgumentException(SR.Argument_CompareOptionOrdinal, nameof(options));
- }
-
- return string.CompareOrdinal(string1, string2);
- }
-
- if ((options & ValidCompareMaskOffFlags) != 0)
- {
- throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
- }
+ return _invariantMode ?
+ string.CompareOrdinal(string1, string2) :
+ CompareString(string1, string2, CompareOptions.None);
+ }
- if (_invariantMode)
- {
- return (options & CompareOptions.IgnoreCase) != 0 ?
- CompareOrdinalIgnoreCase(string1, string2) :
- string.CompareOrdinal(string1, string2);
- }
+ internal int CompareOptionIgnoreCase(ReadOnlySpan<char> string1, ReadOnlySpan<char> string2)
+ {
+ // Check for empty span or span from a null string
+ if (string1.Length == 0 || string2.Length == 0)
+ return string1.Length - string2.Length;
- return CompareString(string1, string2, options);
+ return _invariantMode ?
+ CompareOrdinalIgnoreCase(string1, string2) :
+ CompareString(string1, string2, CompareOptions.IgnoreCase);
}
////////////////////////////////////////////////////////////////////////
@@ -459,7 +449,7 @@ namespace System.Globalization
{
if (options == CompareOptions.OrdinalIgnoreCase)
{
- int result = String.Compare(string1, offset1, string2, offset2, length1 < length2 ? length1 : length2, StringComparison.OrdinalIgnoreCase);
+ int result = string.Compare(string1, offset1, string2, offset2, length1 < length2 ? length1 : length2, StringComparison.OrdinalIgnoreCase);
if ((length1 != length2) && result == 0)
return (length1 > length2 ? 1 : -1);
return (result);
@@ -511,35 +501,23 @@ namespace System.Globalization
return (1);
}
+ ReadOnlySpan<char> span1 = string1.AsSpan(offset1, length1);
+ ReadOnlySpan<char> span2 = string2.AsSpan(offset2, length2);
+
if (options == CompareOptions.Ordinal)
{
- return CompareOrdinal(string1, offset1, length1,
- string2, offset2, length2);
+ return string.CompareOrdinal(span1, span2);
}
if (_invariantMode)
{
if ((options & CompareOptions.IgnoreCase) != 0)
- return CompareOrdinalIgnoreCase(string1, offset1, length1, string2, offset2, length2);
+ return CompareOrdinalIgnoreCase(span1, span2);
- return CompareOrdinal(string1, offset1, length1, string2, offset2, length2);
+ return string.CompareOrdinal(span1, span2);
}
- return CompareString(
- string1.AsSpan().Slice(offset1, length1),
- string2.AsSpan().Slice(offset2, length2),
- options);
- }
-
- private static int CompareOrdinal(string string1, int offset1, int length1, string string2, int offset2, int length2)
- {
- int result = String.CompareOrdinal(string1, offset1, string2, offset2,
- (length1 < length2 ? length1 : length2));
- if ((length1 != length2) && result == 0)
- {
- return (length1 > length2 ? 1 : -1);
- }
- return (result);
+ return CompareString(span1, span2, options);
}
//
@@ -551,57 +529,103 @@ namespace System.Globalization
{
Debug.Assert(indexA + lengthA <= strA.Length);
Debug.Assert(indexB + lengthB <= strB.Length);
- return CompareOrdinalIgnoreCase(strA.AsSpan().Slice(indexA, lengthA), strB.AsSpan().Slice(indexB, lengthB));
+ return CompareOrdinalIgnoreCase(
+ ref Unsafe.Add(ref strA.GetRawStringData(), indexA),
+ lengthA,
+ ref Unsafe.Add(ref strB.GetRawStringData(), indexB),
+ lengthB);
}
- internal static unsafe int CompareOrdinalIgnoreCase(ReadOnlySpan<char> strA, ReadOnlySpan<char> strB)
+ internal static int CompareOrdinalIgnoreCase(ReadOnlySpan<char> strA, ReadOnlySpan<char> strB)
{
- int length = Math.Min(strA.Length, strB.Length);
+ return CompareOrdinalIgnoreCase(ref MemoryMarshal.GetReference(strA), strA.Length, ref MemoryMarshal.GetReference(strB), strB.Length);
+ }
+
+ internal static int CompareOrdinalIgnoreCase(string strA, string strB)
+ {
+ return CompareOrdinalIgnoreCase(ref strA.GetRawStringData(), strA.Length, ref strB.GetRawStringData(), strB.Length);
+ }
+
+ internal static int CompareOrdinalIgnoreCase(ref char strA, int lengthA, ref char strB, int lengthB)
+ {
+ int length = Math.Min(lengthA, lengthB);
int range = length;
- fixed (char* ap = &MemoryMarshal.GetReference(strA))
- fixed (char* bp = &MemoryMarshal.GetReference(strB))
- {
- char* a = ap;
- char* b = bp;
+ ref char charA = ref strA;
+ ref char charB = ref strB;
- // in InvariantMode we support all range and not only the ascii characters.
- char maxChar = (char) (GlobalizationMode.Invariant ? 0xFFFF : 0x7F);
+ // in InvariantMode we support all range and not only the ascii characters.
+ char maxChar = (GlobalizationMode.Invariant ? (char)0xFFFF : (char)0x7F);
- while (length != 0 && (*a <= maxChar) && (*b <= maxChar))
+ while (length != 0 && charA <= maxChar && charB <= maxChar)
+ {
+ // Ordinal equals or lowercase equals if the result ends up in the a-z range
+ if (charA == charB ||
+ ((charA | 0x20) == (charB | 0x20) &&
+ (uint)((charA | 0x20) - 'a') <= (uint)('z' - 'a')))
{
- int charA = *a;
- int charB = *b;
-
- if (charA == charB)
- {
- a++; b++;
- length--;
- continue;
- }
+ length--;
+ charA = ref Unsafe.Add(ref charA, 1);
+ charB = ref Unsafe.Add(ref charB, 1);
+ }
+ else
+ {
+ int currentA = charA;
+ int currentB = charB;
- // uppercase both chars - notice that we need just one compare per char
- if ((uint)(charA - 'a') <= 'z' - 'a') charA -= 0x20;
- if ((uint)(charB - 'a') <= 'z' - 'a') charB -= 0x20;
+ // Uppercase both chars if needed
+ if ((uint)(charA - 'a') <= 'z' - 'a')
+ currentA -= 0x20;
+ if ((uint)(charB - 'a') <= 'z' - 'a')
+ currentB -= 0x20;
// Return the (case-insensitive) difference between them.
- if (charA != charB)
- return charA - charB;
-
- // Next char
- a++; b++;
- length--;
+ return currentA - currentB;
}
+ }
+
+ if (length == 0)
+ return lengthA - lengthB;
+
+ Debug.Assert(!GlobalizationMode.Invariant);
- if (length == 0)
- return strA.Length - strB.Length;
+ range -= length;
- Debug.Assert(!GlobalizationMode.Invariant);
+ return CompareStringOrdinalIgnoreCase(ref charA, lengthA - range, ref charB, lengthB - range);
+ }
+
+
+ internal static bool EqualsOrdinalIgnoreCase(ref char strA, ref char strB, int length)
+ {
+ ref char charA = ref strA;
+ ref char charB = ref strB;
- range -= length;
+ // in InvariantMode we support all range and not only the ascii characters.
+ char maxChar = (GlobalizationMode.Invariant ? (char)0xFFFF : (char)0x7F);
- return CompareStringOrdinalIgnoreCase(a, strA.Length - range, b, strB.Length - range);
+ while (length != 0 && charA <= maxChar && charB <= maxChar)
+ {
+ // Ordinal equals or lowercase equals if the result ends up in the a-z range
+ if (charA == charB ||
+ ((charA | 0x20) == (charB | 0x20) &&
+ (uint)((charA | 0x20) - 'a') <= (uint)('z' - 'a')))
+ {
+ length--;
+ charA = ref Unsafe.Add(ref charA, 1);
+ charB = ref Unsafe.Add(ref charB, 1);
+ }
+ else
+ {
+ return false;
+ }
}
+
+ if (length == 0)
+ return true;
+
+ Debug.Assert(!GlobalizationMode.Invariant);
+
+ return CompareStringOrdinalIgnoreCase(ref charA, length, ref charB, length) == 0;
}
////////////////////////////////////////////////////////////////////////
@@ -609,7 +633,7 @@ namespace System.Globalization
// IsPrefix
//
// Determines whether prefix is a prefix of string. If prefix equals
- // String.Empty, true is returned.
+ // string.Empty, true is returned.
//
////////////////////////////////////////////////////////////////////////
public virtual bool IsPrefix(string source, string prefix, CompareOptions options)
@@ -674,7 +698,7 @@ namespace System.Globalization
// IsSuffix
//
// Determines whether suffix is a suffix of string. If suffix equals
- // String.Empty, true is returned.
+ // string.Empty, true is returned.
//
////////////////////////////////////////////////////////////////////////
public virtual bool IsSuffix(string source, string suffix, CompareOptions options)
@@ -741,7 +765,7 @@ namespace System.Globalization
//
// Returns the first index where value is found in string. The
// search starts from startIndex and ends at endIndex. Returns -1 if
- // the specified value is not found. If value equals String.Empty,
+ // the specified value is not found. If value equals string.Empty,
// startIndex is returned. Throws IndexOutOfRange if startIndex or
// endIndex is less than zero or greater than the length of string.
// Throws ArgumentException if value is null.
@@ -910,16 +934,36 @@ namespace System.Globalization
return IndexOfCore(source, value, startIndex, count, options, null);
}
- internal virtual int IndexOfOrdinal(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase)
+ internal int IndexOfOrdinal(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase)
+ {
+ Debug.Assert(!_invariantMode);
+ Debug.Assert(!source.IsEmpty);
+ Debug.Assert(!value.IsEmpty);
+ return IndexOfOrdinalCore(source, value, ignoreCase, fromBeginning: true);
+ }
+
+ internal int LastIndexOfOrdinal(ReadOnlySpan<char> source, ReadOnlySpan<char> value, bool ignoreCase)
+ {
+ Debug.Assert(!_invariantMode);
+ Debug.Assert(!source.IsEmpty);
+ Debug.Assert(!value.IsEmpty);
+ return IndexOfOrdinalCore(source, value, ignoreCase, fromBeginning: false);
+ }
+
+ internal unsafe int IndexOf(ReadOnlySpan<char> source, ReadOnlySpan<char> value, CompareOptions options)
{
Debug.Assert(!_invariantMode);
- return IndexOfOrdinalCore(source, value, ignoreCase);
+ Debug.Assert(!source.IsEmpty);
+ Debug.Assert(!value.IsEmpty);
+ return IndexOfCore(source, value, options, null, fromBeginning: true);
}
- internal unsafe virtual int IndexOf(ReadOnlySpan<char> source, ReadOnlySpan<char> value, CompareOptions options)
+ internal unsafe int LastIndexOf(ReadOnlySpan<char> source, ReadOnlySpan<char> value, CompareOptions options)
{
Debug.Assert(!_invariantMode);
- return IndexOfCore(source, value, options, null);
+ Debug.Assert(!source.IsEmpty);
+ Debug.Assert(!value.IsEmpty);
+ return IndexOfCore(source, value, options, null, fromBeginning: false);
}
// The following IndexOf overload is mainly used by String.Replace. This overload assumes the parameters are already validated
@@ -985,7 +1029,7 @@ namespace System.Globalization
//
// Returns the last index where value is found in string. The
// search starts from startIndex and ends at endIndex. Returns -1 if
- // the specified value is not found. If value equals String.Empty,
+ // the specified value is not found. If value equals string.Empty,
// endIndex is returned. Throws IndexOutOfRange if startIndex or
// endIndex is less than zero or greater than the length of string.
// Throws ArgumentException if value is null.
@@ -993,7 +1037,7 @@ namespace System.Globalization
////////////////////////////////////////////////////////////////////////
- public virtual int LastIndexOf(String source, char value)
+ public virtual int LastIndexOf(string source, char value)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
@@ -1208,7 +1252,7 @@ namespace System.Globalization
////////////////////////////////////////////////////////////////////////
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
CompareInfo that = value as CompareInfo;
@@ -1237,6 +1281,34 @@ namespace System.Globalization
return (this.Name.GetHashCode());
}
+ internal static unsafe int GetIgnoreCaseHash(string source)
+ {
+ Debug.Assert(source != null, "source must not be null");
+
+ // Do not allocate on the stack if string is empty
+ if (source.Length == 0)
+ {
+ return source.GetHashCode();
+ }
+
+ char[] borrowedArr = null;
+ Span<char> span = source.Length <= 255 ?
+ stackalloc char[255] :
+ (borrowedArr = ArrayPool<char>.Shared.Rent(source.Length));
+
+ int charsWritten = source.AsSpan().ToUpperInvariant(span);
+
+ // Slice the array to the size returned by ToUpperInvariant.
+ int hash = Marvin.ComputeHash32(MemoryMarshal.AsBytes(span.Slice(0, charsWritten)), Marvin.DefaultSeed);
+
+ // Return the borrowed array if necessary.
+ if (borrowedArr != null)
+ {
+ ArrayPool<char>.Shared.Return(borrowedArr);
+ }
+
+ return hash;
+ }
////////////////////////////////////////////////////////////////////////
//
@@ -1277,6 +1349,11 @@ namespace System.Globalization
throw new ArgumentException(SR.Argument_InvalidFlag, nameof(options));
}
+ if (_invariantMode)
+ {
+ return ((options & CompareOptions.IgnoreCase) != 0) ? GetIgnoreCaseHash(source) : source.GetHashCode();
+ }
+
return GetHashCodeOfStringCore(source, options);
}
@@ -1294,7 +1371,7 @@ namespace System.Globalization
if (options == CompareOptions.OrdinalIgnoreCase)
{
- return TextInfo.GetHashCodeOrdinalIgnoreCase(source);
+ return GetIgnoreCaseHash(source);
}
//
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CultureData.Unix.cs b/src/System.Private.CoreLib/shared/System/Globalization/CultureData.Unix.cs
index 3fce52792..4b21f2e7d 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CultureData.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CultureData.Unix.cs
@@ -149,7 +149,7 @@ namespace System.Globalization
// Failed, just use empty string
StringBuilderCache.Release(sb);
Debug.Fail("[CultureData.GetLocaleInfo(LocaleStringData)] Failed");
- return String.Empty;
+ return string.Empty;
}
return StringBuilderCache.GetStringAndRelease(sb);
}
@@ -216,7 +216,7 @@ namespace System.Globalization
// Failed, just use empty string
StringBuilderCache.Release(sb);
Debug.Fail("[CultureData.GetTimeFormatString(bool shortFormat)] Failed");
- return String.Empty;
+ return string.Empty;
}
return ConvertIcuTimeFormatString(StringBuilderCache.GetStringAndRelease(sb));
@@ -227,19 +227,19 @@ namespace System.Globalization
return this.GetLocaleInfo(LocaleNumberData.FirstDayOfWeek);
}
- private String[] GetTimeFormats()
+ private string[] GetTimeFormats()
{
string format = GetTimeFormatString(false);
return new string[] { format };
}
- private String[] GetShortTimeFormats()
+ private string[] GetShortTimeFormats()
{
string format = GetTimeFormatString(true);
return new string[] { format };
}
- private static CultureData GetCultureDataFromRegionName(String regionName)
+ private static CultureData GetCultureDataFromRegionName(string regionName)
{
// no support to lookup by region name, other than the hard-coded list in CultureData
return null;
@@ -371,7 +371,7 @@ namespace System.Globalization
return Array.Empty<CultureInfo>();
}
- Char [] chars = new Char[bufferLength];
+ char [] chars = new char[bufferLength];
bufferLength = Interop.Globalization.GetLocales(chars, bufferLength);
if (bufferLength <= 0)
@@ -394,7 +394,7 @@ namespace System.Globalization
int length = (int) chars[index++];
if (index + length <= bufferLength)
{
- CultureInfo ci = CultureInfo.GetCultureInfo(new String(chars, index, length));
+ CultureInfo ci = CultureInfo.GetCultureInfo(new string(chars, index, length));
if ((enumNeutrals && ci.IsNeutralCulture) || (enumSpecificss && !ci.IsNeutralCulture))
{
list.Add(ci);
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CultureData.Windows.cs b/src/System.Private.CoreLib/shared/System/Globalization/CultureData.Windows.cs
index 393f983bb..75f78620d 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CultureData.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CultureData.Windows.cs
@@ -517,7 +517,7 @@ namespace System.Globalization
// Context for EnumCalendarInfoExEx callback.
- private class EnumLocaleData
+ private struct EnumLocaleData
{
public string regionName;
public string cultureName;
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CultureData.cs b/src/System.Private.CoreLib/shared/System/Globalization/CultureData.cs
index fda239c51..5eb9f44f8 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CultureData.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CultureData.cs
@@ -2268,7 +2268,7 @@ namespace System.Globalization
for (int i = startIndex; i < format.Length; ++i)
{
// See if we have a time Part
- if (!inQuote && timeParts.IndexOf(format[i]) != -1)
+ if (!inQuote && timeParts.Contains(format[i]))
{
return i;
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/CultureNotFoundException.cs b/src/System.Private.CoreLib/shared/System/Globalization/CultureNotFoundException.cs
index 10e8b1f83..007aff7b9 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/CultureNotFoundException.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/CultureNotFoundException.cs
@@ -18,28 +18,28 @@ namespace System.Globalization
{
}
- public CultureNotFoundException(String message)
+ public CultureNotFoundException(string message)
: base(message)
{
}
- public CultureNotFoundException(String paramName, String message)
+ public CultureNotFoundException(string paramName, string message)
: base(message, paramName)
{
}
- public CultureNotFoundException(String message, Exception innerException)
+ public CultureNotFoundException(string message, Exception innerException)
: base(message, innerException)
{
}
- public CultureNotFoundException(String paramName, string invalidCultureName, String message)
+ public CultureNotFoundException(string paramName, string invalidCultureName, string message)
: base(message, paramName)
{
_invalidCultureName = invalidCultureName;
}
- public CultureNotFoundException(String message, string invalidCultureName, Exception innerException)
+ public CultureNotFoundException(string message, string invalidCultureName, Exception innerException)
: base(message, innerException)
{
_invalidCultureName = invalidCultureName;
@@ -81,7 +81,7 @@ namespace System.Globalization
get { return _invalidCultureName; }
}
- private static String DefaultMessage
+ private static string DefaultMessage
{
get
{
@@ -89,24 +89,24 @@ namespace System.Globalization
}
}
- private String FormatedInvalidCultureId
+ private string FormatedInvalidCultureId
{
get
{
return InvalidCultureId != null ?
- String.Format(CultureInfo.InvariantCulture, "{0} (0x{0:x4})", (int)InvalidCultureId) :
+ string.Format(CultureInfo.InvariantCulture, "{0} (0x{0:x4})", (int)InvalidCultureId) :
InvalidCultureName;
}
}
- public override String Message
+ public override string Message
{
get
{
- String s = base.Message;
+ string s = base.Message;
if (_invalidCultureId != null || _invalidCultureName != null)
{
- String valueMessage = SR.Format(SR.Argument_CultureInvalidIdentifier, FormatedInvalidCultureId);
+ string valueMessage = SR.Format(SR.Argument_CultureInvalidIdentifier, FormatedInvalidCultureId);
if (s == null)
{
return valueMessage;
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormat.cs b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormat.cs
index 595fb5631..73fb0e9b3 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormat.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormat.cs
@@ -7,6 +7,7 @@ using System.Diagnostics;
using System.Globalization;
using System.Text;
using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
namespace System
{
@@ -133,8 +134,8 @@ namespace System
's', 't', 'T', 'u', 'U', 'y', 'Y',
};
- internal const String RoundtripFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK";
- internal const String RoundtripDateTimeUnfixed = "yyyy'-'MM'-'ddTHH':'mm':'ss zzz";
+ internal const string RoundtripFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK";
+ internal const string RoundtripDateTimeUnfixed = "yyyy'-'MM'-'ddTHH':'mm':'ss zzz";
private const int DEFAULT_ALL_DATETIMES_SIZE = 132;
@@ -143,7 +144,7 @@ namespace System
internal static readonly string[] InvariantAbbreviatedDayNames = InvariantFormatInfo.AbbreviatedDayNames;
internal const string Gmt = "GMT";
- internal static String[] fixedNumberFormats = new String[] {
+ internal static string[] fixedNumberFormats = new string[] {
"0",
"00",
"000",
@@ -164,7 +165,7 @@ namespace System
// If the digits of the value is greater than len, no leading zero is added.
//
// Notes:
- // The function can format to Int32.MaxValue.
+ // The function can format to int.MaxValue.
//
////////////////////////////////////////////////////////////////////////////
internal static void FormatDigits(StringBuilder outputBuffer, int value, int len)
@@ -173,7 +174,7 @@ namespace System
FormatDigits(outputBuffer, value, len, false);
}
- internal unsafe static void FormatDigits(StringBuilder outputBuffer, int value, int len, bool overrideLengthLimit)
+ internal static unsafe void FormatDigits(StringBuilder outputBuffer, int value, int len, bool overrideLengthLimit)
{
Debug.Assert(value >= 0, "DateTimeFormat.FormatDigits(): value >= 0");
@@ -222,7 +223,7 @@ namespace System
return (index - pos);
}
- private static String FormatDayOfWeek(int dayOfWeek, int repeat, DateTimeFormatInfo dtfi)
+ private static string FormatDayOfWeek(int dayOfWeek, int repeat, DateTimeFormatInfo dtfi)
{
Debug.Assert(dayOfWeek >= 0 && dayOfWeek <= 6, "dayOfWeek >= 0 && dayOfWeek <= 6");
if (repeat == 3)
@@ -234,7 +235,7 @@ namespace System
return (dtfi.GetDayName((DayOfWeek)dayOfWeek));
}
- private static String FormatMonth(int month, int repeatCount, DateTimeFormatInfo dtfi)
+ private static string FormatMonth(int month, int repeatCount, DateTimeFormatInfo dtfi)
{
Debug.Assert(month >= 1 && month <= 12, "month >=1 && month <= 12");
if (repeatCount == 3)
@@ -275,7 +276,7 @@ namespace System
Therefore, if we are in a regular year, we have to increment the month name if moth is greater or eqaul to 7.
*/
- private static String FormatHebrewMonthName(DateTime time, int month, int repeatCount, DateTimeFormatInfo dtfi)
+ private static string FormatHebrewMonthName(DateTime time, int month, int repeatCount, DateTimeFormatInfo dtfi)
{
Debug.Assert(repeatCount != 3 || repeatCount != 4, "repeateCount should be 3 or 4");
if (dtfi.Calendar.IsLeapYear(dtfi.Calendar.GetYear(time)))
@@ -346,7 +347,7 @@ namespace System
{
// Here we can't find the matching quote.
throw new FormatException(
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.Format_BadQuote, quoteChar));
}
@@ -668,7 +669,7 @@ namespace System
}
else
{
- String fmtPattern = "D" + tokenLen.ToString();
+ string fmtPattern = "D" + tokenLen.ToString();
result.Append(year.ToString(fmtPattern, CultureInfo.InvariantCulture));
}
}
@@ -764,10 +765,10 @@ namespace System
// output the 'z' famliy of formats, which output a the offset from UTC, e.g. "-07:30"
- private static void FormatCustomizedTimeZone(DateTime dateTime, TimeSpan offset, ReadOnlySpan<char> format, Int32 tokenLen, Boolean timeOnly, StringBuilder result)
+ private static void FormatCustomizedTimeZone(DateTime dateTime, TimeSpan offset, ReadOnlySpan<char> format, int tokenLen, bool timeOnly, StringBuilder result)
{
// See if the instance already has an offset
- Boolean dateTimeFormat = (offset == NullOffset);
+ bool dateTimeFormat = (offset == NullOffset);
if (dateTimeFormat)
{
// No offset. The instance is a DateTime and the output should be the local time zone
@@ -852,14 +853,20 @@ namespace System
offset = offset.Negate();
}
- AppendNumber(result, offset.Hours, 2);
+ Append2DigitNumber(result, offset.Hours);
result.Append(':');
- AppendNumber(result, offset.Minutes, 2);
+ Append2DigitNumber(result, offset.Minutes);
}
- internal static String GetRealFormat(ReadOnlySpan<char> format, DateTimeFormatInfo dtfi)
+ private static void Append2DigitNumber(StringBuilder result, int val)
{
- String realFormat = null;
+ result.Append((char)('0' + (val / 10)));
+ result.Append((char)('0' + (val % 10)));
+ }
+
+ internal static string GetRealFormat(ReadOnlySpan<char> format, DateTimeFormatInfo dtfi)
+ {
+ string realFormat = null;
switch (format[0])
{
@@ -924,7 +931,7 @@ namespace System
// This method also convert the dateTime if necessary (e.g. when the format is in Universal time),
// and change dtfi if necessary (e.g. when the format should use invariant culture).
//
- private static String ExpandPredefinedFormat(ReadOnlySpan<char> format, ref DateTime dateTime, ref DateTimeFormatInfo dtfi, ref TimeSpan offset)
+ private static string ExpandPredefinedFormat(ReadOnlySpan<char> format, ref DateTime dateTime, ref DateTimeFormatInfo dtfi, ref TimeSpan offset)
{
switch (format[0])
{
@@ -981,19 +988,65 @@ namespace System
return GetRealFormat(format, dtfi);
}
- internal static String Format(DateTime dateTime, String format, DateTimeFormatInfo dtfi)
+ internal static string Format(DateTime dateTime, string format, IFormatProvider provider)
{
- return Format(dateTime, format, dtfi, NullOffset);
+ return Format(dateTime, format, provider, NullOffset);
}
- internal static string Format(DateTime dateTime, String format, DateTimeFormatInfo dtfi, TimeSpan offset) =>
- StringBuilderCache.GetStringAndRelease(FormatStringBuilder(dateTime, format, dtfi, offset));
+ internal static string Format(DateTime dateTime, string format, IFormatProvider provider, TimeSpan offset)
+ {
+ if (format != null && format.Length == 1)
+ {
+ // Optimize for these standard formats that are not affected by culture.
+ switch (format[0])
+ {
+ // Round trip format
+ case 'o':
+ case 'O':
+ const int MinFormatOLength = 27, MaxFormatOLength = 33;
+ Span<char> span = stackalloc char[MaxFormatOLength];
+ TryFormatO(dateTime, offset, span, out int ochars);
+ Debug.Assert(ochars >= MinFormatOLength && ochars <= MaxFormatOLength);
+ return span.Slice(0, ochars).ToString();
+
+ // RFC1123
+ case 'r':
+ case 'R':
+ const int FormatRLength = 29;
+ string str = string.FastAllocateString(FormatRLength);
+ TryFormatR(dateTime, offset, new Span<char>(ref str.GetRawStringData(), str.Length), out int rchars);
+ Debug.Assert(rchars == str.Length);
+ return str;
+ }
+ }
+
+ DateTimeFormatInfo dtfi = DateTimeFormatInfo.GetInstance(provider);
+ return StringBuilderCache.GetStringAndRelease(FormatStringBuilder(dateTime, format, dtfi, offset));
+ }
- internal static bool TryFormat(DateTime dateTime, Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi) =>
- TryFormat(dateTime, destination, out charsWritten, format, dtfi, NullOffset);
+ internal static bool TryFormat(DateTime dateTime, Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider provider) =>
+ TryFormat(dateTime, destination, out charsWritten, format, provider, NullOffset);
- internal static bool TryFormat(DateTime dateTime, Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, TimeSpan offset)
+ internal static bool TryFormat(DateTime dateTime, Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider provider, TimeSpan offset)
{
+ if (format.Length == 1)
+ {
+ // Optimize for these standard formats that are not affected by culture.
+ switch (format[0])
+ {
+ // Round trip format
+ case 'o':
+ case 'O':
+ return TryFormatO(dateTime, offset, destination, out charsWritten);
+
+ // RFC1123
+ case 'r':
+ case 'R':
+ return TryFormatR(dateTime, offset, destination, out charsWritten);
+ }
+ }
+
+ DateTimeFormatInfo dtfi = DateTimeFormatInfo.GetInstance(provider);
StringBuilder sb = FormatStringBuilder(dateTime, format, dtfi, offset);
bool success = sb.Length <= destination.Length;
@@ -1011,12 +1064,12 @@ namespace System
return success;
}
- internal static StringBuilder FormatStringBuilder(DateTime dateTime, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, TimeSpan offset)
+ private static StringBuilder FormatStringBuilder(DateTime dateTime, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, TimeSpan offset)
{
Debug.Assert(dtfi != null);
if (format.Length == 0)
{
- Boolean timeOnlySpecialCase = false;
+ bool timeOnlySpecialCase = false;
if (dateTime.Ticks < Calendar.TicksPerDay)
{
// If the time is less than 1 day, consider it as time of day.
@@ -1060,108 +1113,211 @@ namespace System
if (format.Length == 1)
{
- switch (format[0])
+ format = ExpandPredefinedFormat(format, ref dateTime, ref dtfi, ref offset);
+ }
+
+ return FormatCustomized(dateTime, format, dtfi, offset, result: null);
+ }
+
+ // Roundtrippable format. One of
+ // 012345678901234567890123456789012
+ // ---------------------------------
+ // 2017-06-12T05:30:45.7680000-07:00
+ // 2017-06-12T05:30:45.7680000Z (Z is short for "+00:00" but also distinguishes DateTimeKind.Utc from DateTimeKind.Local)
+ // 2017-06-12T05:30:45.7680000 (interpreted as local time wrt to current time zone)
+ private static bool TryFormatO(DateTime dateTime, TimeSpan offset, Span<char> destination, out int charsWritten)
+ {
+ const int MinimumBytesNeeded = 27;
+
+ int charsRequired = MinimumBytesNeeded;
+ DateTimeKind kind = DateTimeKind.Local;
+
+ if (offset == NullOffset)
+ {
+ kind = dateTime.Kind;
+ if (kind == DateTimeKind.Local)
{
- case 'O':
- case 'o':
- return FastFormatRoundtrip(dateTime, offset);
- case 'R':
- case 'r':
- return FastFormatRfc1123(dateTime, offset, dtfi);
+ offset = TimeZoneInfo.Local.GetUtcOffset(dateTime);
+ charsRequired += 6;
+ }
+ else if (kind == DateTimeKind.Utc)
+ {
+ charsRequired += 1;
}
+ }
+ else
+ {
+ charsRequired += 6;
+ }
- format = ExpandPredefinedFormat(format, ref dateTime, ref dtfi, ref offset);
+ if (destination.Length < charsRequired)
+ {
+ charsWritten = 0;
+ return false;
}
+ charsWritten = charsRequired;
+
+ // Hoist most of the bounds checks on destination.
+ { var unused = destination[MinimumBytesNeeded - 1]; }
+
+ WriteFourDecimalDigits((uint)dateTime.Year, destination, 0);
+ destination[4] = '-';
+ WriteTwoDecimalDigits((uint)dateTime.Month, destination, 5);
+ destination[7] = '-';
+ WriteTwoDecimalDigits((uint)dateTime.Day, destination, 8);
+ destination[10] = 'T';
+ WriteTwoDecimalDigits((uint)dateTime.Hour, destination, 11);
+ destination[13] = ':';
+ WriteTwoDecimalDigits((uint)dateTime.Minute, destination, 14);
+ destination[16] = ':';
+ WriteTwoDecimalDigits((uint)dateTime.Second, destination, 17);
+ destination[19] = '.';
+ WriteDigits((uint)((ulong)dateTime.Ticks % (ulong)TimeSpan.TicksPerSecond), destination.Slice(20, 7));
+
+ if (kind == DateTimeKind.Local)
+ {
+ char sign;
+ if (offset < default(TimeSpan) /* a "const" version of TimeSpan.Zero */)
+ {
+ sign = '-';
+ offset = TimeSpan.FromTicks(-offset.Ticks);
+ }
+ else
+ {
+ sign = '+';
+ }
- return FormatCustomized(dateTime, format, dtfi, offset, result: null);
+ // Writing the value backward allows the JIT to optimize by
+ // performing a single bounds check against buffer.
+ WriteTwoDecimalDigits((uint)offset.Minutes, destination, 31);
+ destination[30] = ':';
+ WriteTwoDecimalDigits((uint)offset.Hours, destination, 28);
+ destination[27] = sign;
+ }
+ else if (kind == DateTimeKind.Utc)
+ {
+ destination[27] = 'Z';
+ }
+
+ return true;
}
- internal static StringBuilder FastFormatRfc1123(DateTime dateTime, TimeSpan offset, DateTimeFormatInfo dtfi)
+ // Rfc1123
+ // 01234567890123456789012345678
+ // -----------------------------
+ // Tue, 03 Jan 2017 08:08:05 GMT
+ private static bool TryFormatR(DateTime dateTime, TimeSpan offset, Span<char> destination, out int charsWritten)
{
- // ddd, dd MMM yyyy HH:mm:ss GMT
- const int Rfc1123FormatLength = 29;
- StringBuilder result = StringBuilderCache.Acquire(Rfc1123FormatLength);
+ // Writing the check in this fashion elides all bounds checks on 'destination'
+ // for the remainder of the method.
+ if (28 >= (uint)destination.Length)
+ {
+ charsWritten = 0;
+ return false;
+ }
if (offset != NullOffset)
{
- // Convert to UTC invariants
+ // Convert to UTC invariants.
dateTime = dateTime - offset;
}
dateTime.GetDatePart(out int year, out int month, out int day);
- result.Append(InvariantAbbreviatedDayNames[(int)dateTime.DayOfWeek]);
- result.Append(',');
- result.Append(' ');
- AppendNumber(result, day, 2);
- result.Append(' ');
- result.Append(InvariantAbbreviatedMonthNames[month - 1]);
- result.Append(' ');
- AppendNumber(result, year, 4);
- result.Append(' ');
- AppendHHmmssTimeOfDay(result, dateTime);
- result.Append(' ');
- result.Append(Gmt);
- return result;
+ string dayAbbrev = InvariantAbbreviatedDayNames[(int)dateTime.DayOfWeek];
+ Debug.Assert(dayAbbrev.Length == 3);
+
+ string monthAbbrev = InvariantAbbreviatedMonthNames[month - 1];
+ Debug.Assert(monthAbbrev.Length == 3);
+
+ destination[0] = dayAbbrev[0];
+ destination[1] = dayAbbrev[1];
+ destination[2] = dayAbbrev[2];
+ destination[3] = ',';
+ destination[4] = ' ';
+ WriteTwoDecimalDigits((uint)day, destination, 5);
+ destination[7] = ' ';
+ destination[8] = monthAbbrev[0];
+ destination[9] = monthAbbrev[1];
+ destination[10] = monthAbbrev[2];
+ destination[11] = ' ';
+ WriteFourDecimalDigits((uint)year, destination, 12);
+ destination[16] = ' ';
+ WriteTwoDecimalDigits((uint)dateTime.Hour, destination, 17);
+ destination[19] = ':';
+ WriteTwoDecimalDigits((uint)dateTime.Minute, destination, 20);
+ destination[22] = ':';
+ WriteTwoDecimalDigits((uint)dateTime.Second, destination, 23);
+ destination[25] = ' ';
+ destination[26] = 'G';
+ destination[27] = 'M';
+ destination[28] = 'T';
+
+ charsWritten = 29;
+ return true;
}
- internal static StringBuilder FastFormatRoundtrip(DateTime dateTime, TimeSpan offset)
+ /// <summary>
+ /// Writes a value [ 00 .. 99 ] to the buffer starting at the specified offset.
+ /// This method performs best when the starting index is a constant literal.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void WriteTwoDecimalDigits(uint value, Span<char> destination, int offset)
{
- // yyyy-MM-ddTHH:mm:ss.fffffffK
- const int roundTripFormatLength = 28;
- StringBuilder result = StringBuilderCache.Acquire(roundTripFormatLength);
+ Debug.Assert(0 <= value && value <= 99);
- dateTime.GetDatePart(out int year, out int month, out int day);
- AppendNumber(result, year, 4);
- result.Append('-');
- AppendNumber(result, month, 2);
- result.Append('-');
- AppendNumber(result, day, 2);
- result.Append('T');
- AppendHHmmssTimeOfDay(result, dateTime);
- result.Append('.');
+ uint temp = '0' + value;
+ value /= 10;
+ destination[offset + 1] = (char)(temp - (value * 10));
+ destination[offset] = (char)('0' + value);
+ }
- long fraction = dateTime.Ticks % TimeSpan.TicksPerSecond;
- AppendNumber(result, fraction, 7);
+ /// <summary>
+ /// Writes a value [ 0000 .. 9999 ] to the buffer starting at the specified offset.
+ /// This method performs best when the starting index is a constant literal.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void WriteFourDecimalDigits(uint value, Span<char> buffer, int startingIndex = 0)
+ {
+ Debug.Assert(0 <= value && value <= 9999);
- FormatCustomizedRoundripTimeZone(dateTime, offset, result);
+ uint temp = '0' + value;
+ value /= 10;
+ buffer[startingIndex + 3] = (char)(temp - (value * 10));
- return result;
- }
+ temp = '0' + value;
+ value /= 10;
+ buffer[startingIndex + 2] = (char)(temp - (value * 10));
- private static void AppendHHmmssTimeOfDay(StringBuilder result, DateTime dateTime)
- {
- // HH:mm:ss
- AppendNumber(result, dateTime.Hour, 2);
- result.Append(':');
- AppendNumber(result, dateTime.Minute, 2);
- result.Append(':');
- AppendNumber(result, dateTime.Second, 2);
+ temp = '0' + value;
+ value /= 10;
+ buffer[startingIndex + 1] = (char)(temp - (value * 10));
+
+ buffer[startingIndex] = (char)('0' + value);
}
- internal static void AppendNumber(StringBuilder builder, long val, int digits)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void WriteDigits(ulong value, Span<char> buffer)
{
- for (int i = 0; i < digits; i++)
- {
- builder.Append('0');
- }
+ // We can mutate the 'value' parameter since it's a copy-by-value local.
+ // It'll be used to represent the value left over after each division by 10.
- int index = 1;
- while (val > 0 && index <= digits)
+ for (int i = buffer.Length - 1; i >= 1; i--)
{
- builder[builder.Length - index] = (char)('0' + (val % 10));
- val = val / 10;
- index++;
+ ulong temp = '0' + value;
+ value /= 10;
+ buffer[i] = (char)(temp - (value * 10));
}
- Debug.Assert(val == 0, "DateTimeFormat.AppendNumber(): digits less than size of val");
+ Debug.Assert(value < 10);
+ buffer[0] = (char)('0' + value);
}
- internal static String[] GetAllDateTimes(DateTime dateTime, char format, DateTimeFormatInfo dtfi)
+ internal static string[] GetAllDateTimes(DateTime dateTime, char format, DateTimeFormatInfo dtfi)
{
Debug.Assert(dtfi != null);
- String[] allFormats = null;
- String[] results = null;
+ string[] allFormats = null;
+ string[] results = null;
switch (format)
{
@@ -1178,7 +1334,7 @@ namespace System
case 'y':
case 'Y':
allFormats = dtfi.GetAllDateTimePatterns(format);
- results = new String[allFormats.Length];
+ results = new string[allFormats.Length];
for (int i = 0; i < allFormats.Length; i++)
{
results[i] = Format(dateTime, allFormats[i], dtfi);
@@ -1187,7 +1343,7 @@ namespace System
case 'U':
DateTime universalTime = dateTime.ToUniversalTime();
allFormats = dtfi.GetAllDateTimePatterns(format);
- results = new String[allFormats.Length];
+ results = new string[allFormats.Length];
for (int i = 0; i < allFormats.Length; i++)
{
results[i] = Format(universalTime, allFormats[i], dtfi);
@@ -1203,7 +1359,7 @@ namespace System
case 'O':
case 's':
case 'u':
- results = new String[] { Format(dateTime, new String(format, 1), dtfi) };
+ results = new string[] { Format(dateTime, new string(format, 1), dtfi) };
break;
default:
throw new FormatException(SR.Format_InvalidString);
@@ -1211,19 +1367,19 @@ namespace System
return (results);
}
- internal static String[] GetAllDateTimes(DateTime dateTime, DateTimeFormatInfo dtfi)
+ internal static string[] GetAllDateTimes(DateTime dateTime, DateTimeFormatInfo dtfi)
{
- List<String> results = new List<String>(DEFAULT_ALL_DATETIMES_SIZE);
+ List<string> results = new List<string>(DEFAULT_ALL_DATETIMES_SIZE);
for (int i = 0; i < allStandardFormats.Length; i++)
{
- String[] strings = GetAllDateTimes(dateTime, allStandardFormats[i], dtfi);
+ string[] strings = GetAllDateTimes(dateTime, allStandardFormats[i], dtfi);
for (int j = 0; j < strings.Length; j++)
{
results.Add(strings[j]);
}
}
- String[] value = new String[results.Count];
+ string[] value = new string[results.Count];
results.CopyTo(0, value, 0, results.Count);
return (value);
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfo.cs b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfo.cs
index faa0deac3..8fc6f7beb 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfo.cs
@@ -58,10 +58,10 @@ namespace System.Globalization
private CultureData _cultureData;
// The culture name used to create this DTFI.
- private String _name = null;
+ private string _name = null;
// The language name of the culture used to create this DTFI.
- private String _langName = null;
+ private string _langName = null;
// CompareInfo usually used by the parser.
private CompareInfo _compareInfo = null;
@@ -73,28 +73,28 @@ namespace System.Globalization
// Caches for various properties.
//
- private String amDesignator = null;
- private String pmDesignator = null;
+ private string amDesignator = null;
+ private string pmDesignator = null;
- private String dateSeparator = null; // derived from short date (whidbey expects, arrowhead doesn't)
+ private string dateSeparator = null; // derived from short date (whidbey expects, arrowhead doesn't)
- private String generalShortTimePattern = null; // short date + short time (whidbey expects, arrowhead doesn't)
+ private string generalShortTimePattern = null; // short date + short time (whidbey expects, arrowhead doesn't)
- private String generalLongTimePattern = null; // short date + long time (whidbey expects, arrowhead doesn't)
+ private string generalLongTimePattern = null; // short date + long time (whidbey expects, arrowhead doesn't)
- private String timeSeparator = null; // derived from long time (whidbey expects, arrowhead doesn't)
- private String monthDayPattern = null;
+ private string timeSeparator = null; // derived from long time (whidbey expects, arrowhead doesn't)
+ private string monthDayPattern = null;
// added in .NET Framework Release {2.0SP1/3.0SP1/3.5RTM}
- private String dateTimeOffsetPattern = null;
+ private string dateTimeOffsetPattern = null;
//
// The following are constant values.
//
- private const String rfc1123Pattern = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'";
+ private const string rfc1123Pattern = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'";
// The sortable pattern is based on ISO 8601.
- private const String sortableDateTimePattern = "yyyy'-'MM'-'dd'T'HH':'mm':'ss";
- private const String universalSortableDateTimePattern = "yyyy'-'MM'-'dd HH':'mm':'ss'Z'";
+ private const string sortableDateTimePattern = "yyyy'-'MM'-'dd'T'HH':'mm':'ss";
+ private const string universalSortableDateTimePattern = "yyyy'-'MM'-'dd HH':'mm':'ss'Z'";
//
// The following are affected by calendar settings.
@@ -105,27 +105,27 @@ namespace System.Globalization
private int calendarWeekRule = -1;
- private String fullDateTimePattern = null; // long date + long time (whidbey expects, arrowhead doesn't)
+ private string fullDateTimePattern = null; // long date + long time (whidbey expects, arrowhead doesn't)
- private String[] abbreviatedDayNames = null;
+ private string[] abbreviatedDayNames = null;
- private String[] m_superShortDayNames = null;
+ private string[] m_superShortDayNames = null;
- private String[] dayNames = null;
- private String[] abbreviatedMonthNames = null;
- private String[] monthNames = null;
+ private string[] dayNames = null;
+ private string[] abbreviatedMonthNames = null;
+ private string[] monthNames = null;
// Cache the genitive month names that we retrieve from the data table.
- private String[] genitiveMonthNames = null;
+ private string[] genitiveMonthNames = null;
// Cache the abbreviated genitive month names that we retrieve from the data table.
- private String[] m_genitiveAbbreviatedMonthNames = null;
+ private string[] m_genitiveAbbreviatedMonthNames = null;
// Cache the month names of a leap year that we retrieve from the data table.
- private String[] leapYearMonthNames = null;
+ private string[] leapYearMonthNames = null;
// For our "patterns" arrays we have 2 variables, a string and a string[]
//
@@ -134,23 +134,23 @@ namespace System.Globalization
// When we initially construct our string[], we set the string to string[0]
// The "default" Date/time patterns
- private String longDatePattern = null;
- private String shortDatePattern = null;
- private String yearMonthPattern = null;
- private String longTimePattern = null;
- private String shortTimePattern = null;
+ private string longDatePattern = null;
+ private string shortDatePattern = null;
+ private string yearMonthPattern = null;
+ private string longTimePattern = null;
+ private string shortTimePattern = null;
- private String[] allYearMonthPatterns = null;
+ private string[] allYearMonthPatterns = null;
- private String[] allShortDatePatterns = null;
- private String[] allLongDatePatterns = null;
- private String[] allShortTimePatterns = null;
- private String[] allLongTimePatterns = null;
+ private string[] allShortDatePatterns = null;
+ private string[] allLongDatePatterns = null;
+ private string[] allShortTimePatterns = null;
+ private string[] allLongTimePatterns = null;
// Cache the era names for this DateTimeFormatInfo instance.
- private String[] m_eraNames = null;
- private String[] m_abbrevEraNames = null;
- private String[] m_abbrevEnglishEraNames = null;
+ private string[] m_eraNames = null;
+ private string[] m_abbrevEraNames = null;
+ private string[] m_abbrevEnglishEraNames = null;
private CalendarId[] optionalCalendars = null;
@@ -164,7 +164,7 @@ namespace System.Globalization
private DateTimeFormatFlags formatFlags = DateTimeFormatFlags.NotInitialized;
- private String CultureName
+ private string CultureName
{
get
{
@@ -189,7 +189,7 @@ namespace System.Globalization
}
// TODO: This ignores other cultures that might want to do something similar
- private String LanguageName
+ private string LanguageName
{
get
{
@@ -261,9 +261,9 @@ namespace System.Globalization
//
////////////////////////////////////////////////////////////////////////////
- private String[] internalGetAbbreviatedMonthNames() => this.abbreviatedMonthNames ?? internalGetAbbreviatedMonthNamesCore();
+ private string[] internalGetAbbreviatedMonthNames() => this.abbreviatedMonthNames ?? internalGetAbbreviatedMonthNamesCore();
[MethodImpl(MethodImplOptions.NoInlining)]
- private String[] internalGetAbbreviatedMonthNamesCore()
+ private string[] internalGetAbbreviatedMonthNamesCore()
{
// Get the month names for our current calendar
this.abbreviatedMonthNames = _cultureData.AbbreviatedMonthNames(Calendar.ID);
@@ -386,13 +386,13 @@ namespace System.Globalization
provider.GetFormat(typeof(DateTimeFormatInfo)) is DateTimeFormatInfo info2 ? info2 :
CurrentInfo; // Couldn't get anything, just use currentInfo as fallback
- public Object GetFormat(Type formatType)
+ public object GetFormat(Type formatType)
{
return (formatType == typeof(DateTimeFormatInfo) ? this : null);
}
- public Object Clone()
+ public object Clone()
{
DateTimeFormatInfo n = (DateTimeFormatInfo)MemberwiseClone();
// We can use the data member calendar in the setter, instead of the property Calendar,
@@ -403,7 +403,7 @@ namespace System.Globalization
}
- public String AMDesignator
+ public string AMDesignator
{
get
{
@@ -546,7 +546,7 @@ namespace System.Globalization
============================================================================*/
- public int GetEra(String eraName)
+ public int GetEra(string eraName)
{
if (eraName == null)
{
@@ -602,7 +602,7 @@ namespace System.Globalization
}
- internal String[] EraNames
+ internal string[] EraNames
{
get
{
@@ -624,7 +624,7 @@ namespace System.Globalization
============================================================================*/
// Era names are 1 indexed
- public String GetEraName(int era)
+ public string GetEraName(int era)
{
if (era == Calendar.CurrentEra)
{
@@ -641,7 +641,7 @@ namespace System.Globalization
throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue);
}
- internal String[] AbbreviatedEraNames
+ internal string[] AbbreviatedEraNames
{
get
{
@@ -654,7 +654,7 @@ namespace System.Globalization
}
// Era names are 1 indexed
- public String GetAbbreviatedEraName(int era)
+ public string GetAbbreviatedEraName(int era)
{
if (AbbreviatedEraNames.Length == 0)
{
@@ -673,7 +673,7 @@ namespace System.Globalization
throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue);
}
- internal String[] AbbreviatedEnglishEraNames
+ internal string[] AbbreviatedEnglishEraNames
{
get
{
@@ -772,7 +772,7 @@ namespace System.Globalization
}
}
- public String FullDateTimePattern
+ public string FullDateTimePattern
{
get
{
@@ -802,7 +802,7 @@ namespace System.Globalization
// The string[] contains the list of patterns, EXCEPT the default may not be included.
// The string contains the default pattern.
// When we initially construct our string[], we set the string to string[0]
- public String LongDatePattern
+ public string LongDatePattern
{
get
{
@@ -842,7 +842,7 @@ namespace System.Globalization
// The string[] contains the list of patterns, EXCEPT the default may not be included.
// The string contains the default pattern.
// When we initially construct our string[], we set the string to string[0]
- public String LongTimePattern
+ public string LongTimePattern
{
get
{
@@ -881,7 +881,7 @@ namespace System.Globalization
// Note: just to be confusing there's only 1 month day pattern, not a whole list
- public String MonthDayPattern
+ public string MonthDayPattern
{
get
{
@@ -909,7 +909,7 @@ namespace System.Globalization
}
- public String PMDesignator
+ public string PMDesignator
{
get
{
@@ -937,7 +937,7 @@ namespace System.Globalization
}
- public String RFC1123Pattern
+ public string RFC1123Pattern
{
get
{
@@ -950,7 +950,7 @@ namespace System.Globalization
// The string[] contains the list of patterns, EXCEPT the default may not be included.
// The string contains the default pattern.
// When we initially construct our string[], we set the string to string[0]
- public String ShortDatePattern
+ public string ShortDatePattern
{
get
{
@@ -991,7 +991,7 @@ namespace System.Globalization
// The string[] contains the list of patterns, EXCEPT the default may not be included.
// The string contains the default pattern.
// When we initially construct our string[], we set the string to string[0]
- public String ShortTimePattern
+ public string ShortTimePattern
{
get
{
@@ -1026,7 +1026,7 @@ namespace System.Globalization
}
- public String SortableDateTimePattern
+ public string SortableDateTimePattern
{
get
{
@@ -1041,7 +1041,7 @@ namespace System.Globalization
** concatation every time somebody asks for the general format.
==============================================================================*/
- internal String GeneralShortTimePattern
+ internal string GeneralShortTimePattern
{
get
{
@@ -1060,7 +1060,7 @@ namespace System.Globalization
** concatation every time somebody asks for the general format.
==============================================================================*/
- internal String GeneralLongTimePattern
+ internal string GeneralLongTimePattern
{
get
{
@@ -1079,7 +1079,7 @@ namespace System.Globalization
** concatation every time somebody uses this form
==============================================================================*/
- internal String DateTimeOffsetPattern
+ internal string DateTimeOffsetPattern
{
get
{
@@ -1168,7 +1168,7 @@ namespace System.Globalization
}
}
- public String UniversalSortableDateTimePattern
+ public string UniversalSortableDateTimePattern
{
get
{
@@ -1181,7 +1181,7 @@ namespace System.Globalization
// The string[] contains the list of patterns, EXCEPT the default may not be included.
// The string contains the default pattern.
// When we initially construct our string[], we set the string to string[0]
- public String YearMonthPattern
+ public string YearMonthPattern
{
get
{
@@ -1215,7 +1215,7 @@ namespace System.Globalization
//
// Check if a string array contains a null value, and throw ArgumentNullException with parameter name "value"
//
- private static void CheckNullValue(String[] values, int length)
+ private static void CheckNullValue(string[] values, int length)
{
Debug.Assert(values != null, "value != null");
Debug.Assert(values.Length >= length);
@@ -1230,11 +1230,11 @@ namespace System.Globalization
}
- public String[] AbbreviatedDayNames
+ public string[] AbbreviatedDayNames
{
get
{
- return ((String[])internalGetAbbreviatedDayOfWeekNames().Clone());
+ return ((string[])internalGetAbbreviatedDayOfWeekNames().Clone());
}
set
@@ -1258,11 +1258,11 @@ namespace System.Globalization
}
// Returns the string array of the one-letter day of week names.
- public String[] ShortestDayNames
+ public string[] ShortestDayNames
{
get
{
- return ((String[])internalGetSuperShortDayNames().Clone());
+ return ((string[])internalGetSuperShortDayNames().Clone());
}
set
@@ -1284,11 +1284,11 @@ namespace System.Globalization
}
- public String[] DayNames
+ public string[] DayNames
{
get
{
- return ((String[])internalGetDayOfWeekNames().Clone());
+ return ((string[])internalGetDayOfWeekNames().Clone());
}
set
@@ -1312,11 +1312,11 @@ namespace System.Globalization
}
- public String[] AbbreviatedMonthNames
+ public string[] AbbreviatedMonthNames
{
get
{
- return ((String[])internalGetAbbreviatedMonthNames().Clone());
+ return ((string[])internalGetAbbreviatedMonthNames().Clone());
}
set
@@ -1339,11 +1339,11 @@ namespace System.Globalization
}
- public String[] MonthNames
+ public string[] MonthNames
{
get
{
- return ((String[])internalGetMonthNames().Clone());
+ return ((string[])internalGetMonthNames().Clone());
}
set
@@ -1398,13 +1398,13 @@ namespace System.Globalization
// Exceptions:
// ArgumentOutOfRangeException When month name is invalid.
//
- internal String internalGetMonthName(int month, MonthNameStyles style, bool abbreviated)
+ internal string internalGetMonthName(int month, MonthNameStyles style, bool abbreviated)
{
//
// Right now, style is mutual exclusive, but I make the style to be flag so that
// maybe we can combine flag if there is such a need.
//
- String[] monthNamesArray = null;
+ string[] monthNamesArray = null;
switch (style)
{
case MonthNameStyles.Genitive:
@@ -1436,7 +1436,7 @@ namespace System.Globalization
// Arguments:
// abbreviated When true, return abbreviated form. Otherwise, return a full form.
//
- private String[] internalGetGenitiveMonthNames(bool abbreviated)
+ private string[] internalGetGenitiveMonthNames(bool abbreviated)
{
if (abbreviated)
{
@@ -1465,7 +1465,7 @@ namespace System.Globalization
// If this culture does not have different month names in a leap year, the normal month name is returned.
// Arguments: None. (can use abbreviated later if needed)
//
- internal String[] internalGetLeapYearMonthNames(/*bool abbreviated*/)
+ internal string[] internalGetLeapYearMonthNames(/*bool abbreviated*/)
{
if (this.leapYearMonthNames == null)
{
@@ -1478,7 +1478,7 @@ namespace System.Globalization
}
- public String GetAbbreviatedDayName(DayOfWeek dayofweek)
+ public string GetAbbreviatedDayName(DayOfWeek dayofweek)
{
if ((int)dayofweek < 0 || (int)dayofweek > 6)
{
@@ -1510,13 +1510,13 @@ namespace System.Globalization
}
// Get all possible combination of inputs
- private static String[] GetCombinedPatterns(String[] patterns1, String[] patterns2, String connectString)
+ private static string[] GetCombinedPatterns(string[] patterns1, string[] patterns2, string connectString)
{
Debug.Assert(patterns1 != null);
Debug.Assert(patterns2 != null);
// Get array size
- String[] result = new String[patterns1.Length * patterns2.Length];
+ string[] result = new string[patterns1.Length * patterns2.Length];
// Counter of actual results
int k = 0;
@@ -1535,11 +1535,11 @@ namespace System.Globalization
public string[] GetAllDateTimePatterns()
{
- List<String> results = new List<String>(DEFAULT_ALL_DATETIMES_SIZE);
+ List<string> results = new List<string>(DEFAULT_ALL_DATETIMES_SIZE);
for (int i = 0; i < DateTimeFormat.allStandardFormats.Length; i++)
{
- String[] strings = GetAllDateTimePatterns(DateTimeFormat.allStandardFormats[i]);
+ string[] strings = GetAllDateTimePatterns(DateTimeFormat.allStandardFormats[i]);
for (int j = 0; j < strings.Length; j++)
{
results.Add(strings[j]);
@@ -1550,7 +1550,7 @@ namespace System.Globalization
public string[] GetAllDateTimePatterns(char format)
{
- String[] result = null;
+ string[] result = null;
switch (format)
{
@@ -1575,18 +1575,18 @@ namespace System.Globalization
break;
case 'm':
case 'M':
- result = new String[] { MonthDayPattern };
+ result = new string[] { MonthDayPattern };
break;
case 'o':
case 'O':
- result = new String[] { RoundtripFormat };
+ result = new string[] { RoundtripFormat };
break;
case 'r':
case 'R':
- result = new String[] { rfc1123Pattern };
+ result = new string[] { rfc1123Pattern };
break;
case 's':
- result = new String[] { sortableDateTimePattern };
+ result = new string[] { sortableDateTimePattern };
break;
case 't':
result = this.AllShortTimePatterns;
@@ -1595,20 +1595,20 @@ namespace System.Globalization
result = this.AllLongTimePatterns;
break;
case 'u':
- result = new String[] { UniversalSortableDateTimePattern };
+ result = new string[] { UniversalSortableDateTimePattern };
break;
case 'y':
case 'Y':
result = this.AllYearMonthPatterns;
break;
default:
- throw new ArgumentException(SR.Format_BadFormatSpecifier, nameof(format));
+ throw new ArgumentException(SR.Format(SR.Format_BadFormatSpecifier, format), nameof(format));
}
return (result);
}
- public String GetDayName(DayOfWeek dayofweek)
+ public string GetDayName(DayOfWeek dayofweek)
{
if ((int)dayofweek < 0 || (int)dayofweek > 6)
{
@@ -1621,7 +1621,7 @@ namespace System.Globalization
return (internalGetDayOfWeekNames()[(int)dayofweek]);
}
- public String GetAbbreviatedMonthName(int month)
+ public string GetAbbreviatedMonthName(int month)
{
if (month < 1 || month > 13)
{
@@ -1633,7 +1633,7 @@ namespace System.Globalization
return (internalGetAbbreviatedMonthNames()[month - 1]);
}
- public String GetMonthName(int month)
+ public string GetMonthName(int month)
{
if (month < 1 || month > 13)
{
@@ -1690,7 +1690,7 @@ namespace System.Globalization
else
{
// Not found, make room for it
- newPatterns = new String[patterns.Length + 1];
+ newPatterns = new string[patterns.Length + 1];
// Copy existing array
Array.Copy(patterns, 0, newPatterns, 1, patterns.Length);
@@ -1704,12 +1704,12 @@ namespace System.Globalization
}
// Needed by DateTimeFormatInfo and DateTimeFormat
- internal const String RoundtripFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK";
- internal const String RoundtripDateTimeUnfixed = "yyyy'-'MM'-'ddTHH':'mm':'ss zzz";
+ internal const string RoundtripFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK";
+ internal const string RoundtripDateTimeUnfixed = "yyyy'-'MM'-'ddTHH':'mm':'ss zzz";
// Default string isn't necessarily in our string array, so get the
// merged patterns of both
- private String[] AllYearMonthPatterns
+ private string[] AllYearMonthPatterns
{
get
{
@@ -1717,7 +1717,7 @@ namespace System.Globalization
}
}
- private String[] AllShortDatePatterns
+ private string[] AllShortDatePatterns
{
get
{
@@ -1725,7 +1725,7 @@ namespace System.Globalization
}
}
- private String[] AllShortTimePatterns
+ private string[] AllShortTimePatterns
{
get
{
@@ -1733,7 +1733,7 @@ namespace System.Globalization
}
}
- private String[] AllLongDatePatterns
+ private string[] AllLongDatePatterns
{
get
{
@@ -1741,7 +1741,7 @@ namespace System.Globalization
}
}
- private String[] AllLongTimePatterns
+ private string[] AllLongTimePatterns
{
get
{
@@ -1751,7 +1751,7 @@ namespace System.Globalization
// NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy.
// This won't include default, call AllYearMonthPatterns
- private String[] UnclonedYearMonthPatterns
+ private string[] UnclonedYearMonthPatterns
{
get
{
@@ -1770,7 +1770,7 @@ namespace System.Globalization
// NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy.
// This won't include default, call AllShortDatePatterns
- private String[] UnclonedShortDatePatterns
+ private string[] UnclonedShortDatePatterns
{
get
{
@@ -1788,7 +1788,7 @@ namespace System.Globalization
// NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy.
// This won't include default, call AllLongDatePatterns
- private String[] UnclonedLongDatePatterns
+ private string[] UnclonedLongDatePatterns
{
get
{
@@ -1806,7 +1806,7 @@ namespace System.Globalization
// NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy.
// This won't include default, call AllShortTimePatterns
- private String[] UnclonedShortTimePatterns
+ private string[] UnclonedShortTimePatterns
{
get
{
@@ -1823,7 +1823,7 @@ namespace System.Globalization
// NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy.
// This won't include default, call AllLongTimePatterns
- private String[] UnclonedLongTimePatterns
+ private string[] UnclonedLongTimePatterns
{
get
{
@@ -1896,7 +1896,7 @@ namespace System.Globalization
//
// WARNING: If more validation is ever done in one place, it should be done in the other.
//
- public void SetAllDateTimePatterns(String[] patterns, char format)
+ public void SetAllDateTimePatterns(string[] patterns, char format)
{
if (IsReadOnly)
throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
@@ -1950,18 +1950,18 @@ namespace System.Globalization
break;
default:
- throw new ArgumentException(SR.Format_BadFormatSpecifier, nameof(format));
+ throw new ArgumentException(SR.Format(SR.Format_BadFormatSpecifier, format), nameof(format));
}
// Clear the token hash table, note that even short dates could require this
ClearTokenHashTable();
}
- public String[] AbbreviatedMonthGenitiveNames
+ public string[] AbbreviatedMonthGenitiveNames
{
get
{
- return ((String[])internalGetGenitiveMonthNames(true).Clone());
+ return ((string[])internalGetGenitiveMonthNames(true).Clone());
}
set
@@ -1983,11 +1983,11 @@ namespace System.Globalization
}
}
- public String[] MonthGenitiveNames
+ public string[] MonthGenitiveNames
{
get
{
- return ((String[])internalGetGenitiveMonthNames(false).Clone());
+ return ((string[])internalGetGenitiveMonthNames(false).Clone());
}
set
@@ -2010,23 +2010,35 @@ namespace System.Globalization
}
//
+ // Decimal separator used by positive TimeSpan pattern
+ //
+ private string _decimalSeparator;
+ internal string DecimalSeparator
+ {
+ get
+ {
+ if (_decimalSeparator == null)
+ {
+ CultureData cultureDataWithoutUserOverrides = _cultureData.UseUserOverride ?
+ CultureData.GetCultureData(_cultureData.CultureName, false) :
+ _cultureData;
+ _decimalSeparator = new NumberFormatInfo(cultureDataWithoutUserOverrides).NumberDecimalSeparator;
+ }
+ return _decimalSeparator;
+ }
+ }
+
+ //
// Positive TimeSpan Pattern
//
private string _fullTimeSpanPositivePattern;
- internal String FullTimeSpanPositivePattern
+ internal string FullTimeSpanPositivePattern
{
get
{
if (_fullTimeSpanPositivePattern == null)
{
- CultureData cultureDataWithoutUserOverrides;
- if (_cultureData.UseUserOverride)
- cultureDataWithoutUserOverrides = CultureData.GetCultureData(_cultureData.CultureName, false);
- else
- cultureDataWithoutUserOverrides = _cultureData;
- String decimalSeparator = new NumberFormatInfo(cultureDataWithoutUserOverrides).NumberDecimalSeparator;
-
- _fullTimeSpanPositivePattern = "d':'h':'mm':'ss'" + decimalSeparator + "'FFFFFFF";
+ _fullTimeSpanPositivePattern = "d':'h':'mm':'ss'" + DecimalSeparator + "'FFFFFFF";
}
return _fullTimeSpanPositivePattern;
}
@@ -2036,7 +2048,7 @@ namespace System.Globalization
// Negative TimeSpan Pattern
//
private string _fullTimeSpanNegativePattern;
- internal String FullTimeSpanNegativePattern
+ internal string FullTimeSpanNegativePattern
{
get
{
@@ -2070,7 +2082,7 @@ namespace System.Globalization
| DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeLocal
| DateTimeStyles.AssumeUniversal | DateTimeStyles.RoundtripKind);
- internal static void ValidateStyles(DateTimeStyles style, String parameterName)
+ internal static void ValidateStyles(DateTimeStyles style, string parameterName)
{
if ((style & InvalidDateTimeStyles) != 0)
{
@@ -2106,7 +2118,7 @@ namespace System.Globalization
return formatFlags;
}
- internal Boolean HasForceTwoDigitYears
+ internal bool HasForceTwoDigitYears
{
get
{
@@ -2129,7 +2141,7 @@ namespace System.Globalization
}
// Returns whether the YearMonthAdjustment function has any fix-up work to do for this culture/calendar.
- internal Boolean HasYearMonthAdjustment
+ internal bool HasYearMonthAdjustment
{
get
{
@@ -2142,7 +2154,7 @@ namespace System.Globalization
// the Hebrew calendar, but this could be extended to other cultures.
//
// The return value is whether the year and month are actually valid for this calendar.
- internal Boolean YearMonthAdjustment(ref int year, ref int month, Boolean parsedMonthName)
+ internal bool YearMonthAdjustment(ref int year, ref int month, bool parsedMonthName)
{
if ((FormatFlags & DateTimeFormatFlags.UseHebrewRule) != 0)
{
@@ -2189,45 +2201,45 @@ namespace System.Globalization
private const int TOKEN_HASH_SIZE = 199;
private const int SECOND_PRIME = 197;
- private const String dateSeparatorOrTimeZoneOffset = "-";
- private const String invariantDateSeparator = "/";
- private const String invariantTimeSeparator = ":";
+ private const string dateSeparatorOrTimeZoneOffset = "-";
+ private const string invariantDateSeparator = "/";
+ private const string invariantTimeSeparator = ":";
//
// Common Ignorable Symbols
//
- internal const String IgnorablePeriod = ".";
- internal const String IgnorableComma = ",";
+ internal const string IgnorablePeriod = ".";
+ internal const string IgnorableComma = ",";
//
// Year/Month/Day suffixes
//
- internal const String CJKYearSuff = "\u5e74";
- internal const String CJKMonthSuff = "\u6708";
- internal const String CJKDaySuff = "\u65e5";
+ internal const string CJKYearSuff = "\u5e74";
+ internal const string CJKMonthSuff = "\u6708";
+ internal const string CJKDaySuff = "\u65e5";
- internal const String KoreanYearSuff = "\ub144";
- internal const String KoreanMonthSuff = "\uc6d4";
- internal const String KoreanDaySuff = "\uc77c";
+ internal const string KoreanYearSuff = "\ub144";
+ internal const string KoreanMonthSuff = "\uc6d4";
+ internal const string KoreanDaySuff = "\uc77c";
- internal const String KoreanHourSuff = "\uc2dc";
- internal const String KoreanMinuteSuff = "\ubd84";
- internal const String KoreanSecondSuff = "\ucd08";
+ internal const string KoreanHourSuff = "\uc2dc";
+ internal const string KoreanMinuteSuff = "\ubd84";
+ internal const string KoreanSecondSuff = "\ucd08";
- internal const String CJKHourSuff = "\u6642";
- internal const String ChineseHourSuff = "\u65f6";
+ internal const string CJKHourSuff = "\u6642";
+ internal const string ChineseHourSuff = "\u65f6";
- internal const String CJKMinuteSuff = "\u5206";
- internal const String CJKSecondSuff = "\u79d2";
+ internal const string CJKMinuteSuff = "\u5206";
+ internal const string CJKSecondSuff = "\u79d2";
- internal const String LocalTimeMark = "T";
+ internal const string LocalTimeMark = "T";
- internal const String GMTName = "GMT";
- internal const String ZuluName = "Z";
+ internal const string GMTName = "GMT";
+ internal const string ZuluName = "Z";
- internal const String KoreanLangName = "ko";
- internal const String JapaneseLangName = "ja";
- internal const String EnglishLangName = "en";
+ internal const string KoreanLangName = "ko";
+ internal const string JapaneseLangName = "ja";
+ internal const string EnglishLangName = "en";
private static volatile DateTimeFormatInfo s_jajpDTFI;
private static volatile DateTimeFormatInfo s_zhtwDTFI;
@@ -2341,7 +2353,7 @@ namespace System.Globalization
InsertHash(temp, dateSeparatorOrTimeZoneOffset, TokenType.SEP_DateOrOffset, 0);
}
- String[] dateWords = null;
+ string[] dateWords = null;
DateTimeFormatInfoScanner scanner = null;
// We need to rescan the date words since we're always synthetic
@@ -2355,7 +2367,7 @@ namespace System.Globalization
// This is determined in DateTimeFormatInfoScanner. Use this flag to determine if we should treat date separator as ignorable symbol.
bool useDateSepAsIgnorableSymbol = false;
- String monthPostfix = null;
+ string monthPostfix = null;
if (dateWords != null)
{
// There are DateWords. It could be a real date word (such as "de"), or a monthPostfix.
@@ -2372,7 +2384,7 @@ namespace System.Globalization
AddMonthNames(temp, monthPostfix);
break;
case DateTimeFormatInfoScanner.IgnorableSymbolChar:
- String symbol = dateWords[i].Substring(1);
+ string symbol = dateWords[i].Substring(1);
InsertHash(temp, symbol, TokenType.IgnorableSymbol, 0);
if (this.DateSeparator.Trim(null).Equals(symbol))
{
@@ -2412,7 +2424,7 @@ namespace System.Globalization
{
for (int i = 1; i <= 13; i++)
{
- String str;
+ string str;
str = internalGetMonthName(i, MonthNameStyles.Genitive, false);
InsertHash(temp, str, TokenType.MonthToken, i);
}
@@ -2422,7 +2434,7 @@ namespace System.Globalization
{
for (int i = 1; i <= 13; i++)
{
- String str;
+ string str;
str = internalGetMonthName(i, MonthNameStyles.LeapYear, false);
InsertHash(temp, str, TokenType.MonthToken, i);
}
@@ -2432,7 +2444,7 @@ namespace System.Globalization
{
//String str = GetDayOfWeekNames()[i];
// We have to call public methods here to work with inherited DTFI.
- String str = GetDayName((DayOfWeek)i);
+ string str = GetDayName((DayOfWeek)i);
InsertHash(temp, str, TokenType.DayOfWeekToken, i);
str = GetAbbreviatedDayName((DayOfWeek)i);
@@ -2452,7 +2464,7 @@ namespace System.Globalization
// Japanese allows day of week forms like: "(Tue)"
for (int i = 0; i < 7; i++)
{
- String specialDayOfWeek = "(" + GetAbbreviatedDayName((DayOfWeek)i) + ")";
+ string specialDayOfWeek = "(" + GetAbbreviatedDayName((DayOfWeek)i) + ")";
InsertHash(temp, specialDayOfWeek, TokenType.DayOfWeekToken, i);
}
if (this.Calendar.GetType() != typeof(JapaneseCalendar))
@@ -2488,7 +2500,7 @@ namespace System.Globalization
// Add invariant month names and day names.
for (int i = 1; i <= 12; i++)
{
- String str;
+ string str;
// We have to call public methods here to work with inherited DTFI.
// Insert the month name first, so that they are at the front of abbreviated
// month names.
@@ -2501,7 +2513,7 @@ namespace System.Globalization
for (int i = 0; i < 7; i++)
{
// We have to call public methods here to work with inherited DTFI.
- String str = InvariantInfo.GetDayName((DayOfWeek)i);
+ string str = InvariantInfo.GetDayName((DayOfWeek)i);
InsertHash(temp, str, TokenType.DayOfWeekToken, i);
str = InvariantInfo.GetAbbreviatedDayName((DayOfWeek)i);
@@ -2526,11 +2538,11 @@ namespace System.Globalization
return (temp);
}
- private void AddMonthNames(TokenHashValue[] temp, String monthPostfix)
+ private void AddMonthNames(TokenHashValue[] temp, string monthPostfix)
{
for (int i = 1; i <= 13; i++)
{
- String str;
+ string str;
//str = internalGetMonthName(i, MonthNameStyles.Regular, false);
// We have to call public methods here to work with inherited DTFI.
// Insert the month name first, so that they are at the front of abbreviated
@@ -2568,7 +2580,7 @@ namespace System.Globalization
private static bool TryParseHebrewNumber(
ref __DTString str,
- out Boolean badFormat,
+ out bool badFormat,
out int number)
{
number = -1;
@@ -2631,7 +2643,7 @@ namespace System.Globalization
Debug.Assert(str.Index < str.Value.Length, "DateTimeFormatInfo.Tokenize(): start < value.Length");
char ch = str.m_current;
- bool isLetter = Char.IsLetter(ch);
+ bool isLetter = char.IsLetter(ch);
if (isLetter)
{
ch = this.Culture.TextInfo.ToLower(ch);
@@ -2689,7 +2701,7 @@ namespace System.Globalization
{
// Check word boundary. The next character should NOT be a letter.
char nextCh = str.Value[nextCharIndex];
- compareStrings = !(Char.IsLetter(nextCh));
+ compareStrings = !(char.IsLetter(nextCh));
}
}
@@ -2724,7 +2736,7 @@ namespace System.Globalization
return (false);
}
- private void InsertAtCurrentHashNode(TokenHashValue[] hashTable, String str, char ch, TokenType tokenType, int tokenValue, int pos, int hashcode, int hashProbe)
+ private void InsertAtCurrentHashNode(TokenHashValue[] hashTable, string str, char ch, TokenType tokenType, int tokenValue, int pos, int hashcode, int hashProbe)
{
// Remember the current slot.
TokenHashValue previousNode = hashTable[hashcode];
@@ -2757,7 +2769,7 @@ namespace System.Globalization
Debug.Fail("The hashtable is full. This should not happen.");
}
- private void InsertHash(TokenHashValue[] hashTable, String str, TokenType tokenType, int tokenValue)
+ private void InsertHash(TokenHashValue[] hashTable, string str, TokenType tokenType, int tokenValue)
{
// The month of the 13th month is allowed to be null, so make sure that we ignore null value here.
if (str == null || str.Length == 0)
@@ -2768,7 +2780,7 @@ namespace System.Globalization
int i = 0;
// If there is whitespace characters in the beginning and end of the string, trim them since whitespaces are skipped by
// DateTime.Parse().
- if (Char.IsWhiteSpace(str[0]) || Char.IsWhiteSpace(str[str.Length - 1]))
+ if (char.IsWhiteSpace(str[0]) || char.IsWhiteSpace(str[str.Length - 1]))
{
str = str.Trim(null); // Trim white space characters.
// Could have space for separators
@@ -2860,11 +2872,11 @@ namespace System.Globalization
internal class TokenHashValue
{
- internal String tokenString;
+ internal string tokenString;
internal TokenType tokenType;
internal int tokenValue;
- internal TokenHashValue(String tokenString, TokenType tokenType, int tokenValue)
+ internal TokenHashValue(string tokenString, TokenType tokenType, int tokenValue)
{
this.tokenString = tokenString;
this.tokenType = tokenType;
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfoScanner.cs b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfoScanner.cs
index d3c3aac84..de43c2da3 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfoScanner.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeFormatInfoScanner.cs
@@ -94,23 +94,23 @@ namespace System.Globalization
internal const char IgnorableSymbolChar = '\xe001';
// Known CJK suffix
- internal const String CJKYearSuff = "\u5e74";
- internal const String CJKMonthSuff = "\u6708";
- internal const String CJKDaySuff = "\u65e5";
+ internal const string CJKYearSuff = "\u5e74";
+ internal const string CJKMonthSuff = "\u6708";
+ internal const string CJKDaySuff = "\u65e5";
- internal const String KoreanYearSuff = "\ub144";
- internal const String KoreanMonthSuff = "\uc6d4";
- internal const String KoreanDaySuff = "\uc77c";
+ internal const string KoreanYearSuff = "\ub144";
+ internal const string KoreanMonthSuff = "\uc6d4";
+ internal const string KoreanDaySuff = "\uc77c";
- internal const String KoreanHourSuff = "\uc2dc";
- internal const String KoreanMinuteSuff = "\ubd84";
- internal const String KoreanSecondSuff = "\ucd08";
+ internal const string KoreanHourSuff = "\uc2dc";
+ internal const string KoreanMinuteSuff = "\ubd84";
+ internal const string KoreanSecondSuff = "\ucd08";
- internal const String CJKHourSuff = "\u6642";
- internal const String ChineseHourSuff = "\u65f6";
+ internal const string CJKHourSuff = "\u6642";
+ internal const string ChineseHourSuff = "\u65f6";
- internal const String CJKMinuteSuff = "\u5206";
- internal const String CJKSecondSuff = "\u79d2";
+ internal const string CJKMinuteSuff = "\u5206";
+ internal const string CJKSecondSuff = "\u79d2";
// The collection fo date words & postfix.
internal List<string> m_dateWords = new List<string>();
@@ -127,23 +127,23 @@ namespace System.Globalization
// Add known words into the hash table.
// Skip these special symbols.
- temp.Add("/", String.Empty);
- temp.Add("-", String.Empty);
- temp.Add(".", String.Empty);
+ temp.Add("/", string.Empty);
+ temp.Add("-", string.Empty);
+ temp.Add(".", string.Empty);
// Skip known CJK suffixes.
- temp.Add(CJKYearSuff, String.Empty);
- temp.Add(CJKMonthSuff, String.Empty);
- temp.Add(CJKDaySuff, String.Empty);
- temp.Add(KoreanYearSuff, String.Empty);
- temp.Add(KoreanMonthSuff, String.Empty);
- temp.Add(KoreanDaySuff, String.Empty);
- temp.Add(KoreanHourSuff, String.Empty);
- temp.Add(KoreanMinuteSuff, String.Empty);
- temp.Add(KoreanSecondSuff, String.Empty);
- temp.Add(CJKHourSuff, String.Empty);
- temp.Add(ChineseHourSuff, String.Empty);
- temp.Add(CJKMinuteSuff, String.Empty);
- temp.Add(CJKSecondSuff, String.Empty);
+ temp.Add(CJKYearSuff, string.Empty);
+ temp.Add(CJKMonthSuff, string.Empty);
+ temp.Add(CJKDaySuff, string.Empty);
+ temp.Add(KoreanYearSuff, string.Empty);
+ temp.Add(KoreanMonthSuff, string.Empty);
+ temp.Add(KoreanDaySuff, string.Empty);
+ temp.Add(KoreanHourSuff, string.Empty);
+ temp.Add(KoreanMinuteSuff, string.Empty);
+ temp.Add(KoreanSecondSuff, string.Empty);
+ temp.Add(CJKHourSuff, string.Empty);
+ temp.Add(ChineseHourSuff, string.Empty);
+ temp.Add(CJKMinuteSuff, string.Empty);
+ temp.Add(CJKSecondSuff, string.Empty);
s_knownWords = temp;
}
@@ -163,7 +163,7 @@ namespace System.Globalization
// Note that the index can be pattern.Length if we reach the end of the string.
//
////////////////////////////////////////////////////////////////////////////
- internal static int SkipWhiteSpacesAndNonLetter(String pattern, int currentIndex)
+ internal static int SkipWhiteSpacesAndNonLetter(string pattern, int currentIndex)
{
while (currentIndex < pattern.Length)
{
@@ -189,7 +189,7 @@ namespace System.Globalization
break;
}
}
- if (Char.IsLetter(ch) || ch == '\'' || ch == '.')
+ if (char.IsLetter(ch) || ch == '\'' || ch == '.')
{
break;
}
@@ -211,7 +211,7 @@ namespace System.Globalization
// word: The date word or postfix to be added.
//
////////////////////////////////////////////////////////////////////////////
- internal void AddDateWordOrPostfix(String formatPostfix, String str)
+ internal void AddDateWordOrPostfix(string formatPostfix, string str)
{
if (str.Length > 0)
{
@@ -221,7 +221,7 @@ namespace System.Globalization
AddIgnorableSymbols(".");
return;
}
- String words;
+ string words;
if (KnownWords.TryGetValue(str, out words) == false)
{
if (m_dateWords == null)
@@ -231,7 +231,7 @@ namespace System.Globalization
if (formatPostfix == "MMMM")
{
// Add the word into the ArrayList as "\xfffe" + real month postfix.
- String temp = MonthPostfixChar + str;
+ string temp = MonthPostfixChar + str;
if (!m_dateWords.Contains(temp))
{
m_dateWords.Add(temp);
@@ -246,7 +246,7 @@ namespace System.Globalization
if (str[str.Length - 1] == '.')
{
// Old version ignore the trialing dot in the date words. Support this as well.
- String strWithoutDot = str.Substring(0, str.Length - 1);
+ string strWithoutDot = str.Substring(0, str.Length - 1);
if (!m_dateWords.Contains(strWithoutDot))
{
m_dateWords.Add(strWithoutDot);
@@ -272,7 +272,7 @@ namespace System.Globalization
//
//
////////////////////////////////////////////////////////////////////////////
- internal int AddDateWords(String pattern, int index, String formatPostfix)
+ internal int AddDateWords(string pattern, int index, string formatPostfix)
{
// Skip any whitespaces so we will start from a letter.
int newIndex = SkipWhiteSpacesAndNonLetter(pattern, index);
@@ -314,7 +314,7 @@ namespace System.Globalization
index++;
}
}
- else if (Char.IsWhiteSpace(ch))
+ else if (char.IsWhiteSpace(ch))
{
// Found a whitespace. We have to add the current date word/postfix.
AddDateWordOrPostfix(formatPostfix, dateWord.ToString());
@@ -341,7 +341,7 @@ namespace System.Globalization
// A simple helper to find the repeat count for a specified char.
//
////////////////////////////////////////////////////////////////////////////
- internal static int ScanRepeatChar(String pattern, char ch, int index, out int count)
+ internal static int ScanRepeatChar(string pattern, char ch, int index, out int count)
{
count = 1;
while (++index < pattern.Length && pattern[index] == ch)
@@ -367,7 +367,7 @@ namespace System.Globalization
//
////////////////////////////////////////////////////////////////////////////
- internal void AddIgnorableSymbols(String text)
+ internal void AddIgnorableSymbols(string text)
{
if (m_dateWords == null)
{
@@ -375,7 +375,7 @@ namespace System.Globalization
m_dateWords = new List<string>();
}
// Add the ignorable symbol into the ArrayList.
- String temp = IgnorableSymbolChar + text;
+ string temp = IgnorableSymbolChar + text;
if (!m_dateWords.Contains(temp))
{
m_dateWords.Add(temp);
@@ -421,7 +421,7 @@ namespace System.Globalization
// Windows style pattern uses '' for single quote, while .NET uses \'
//
////////////////////////////////////////////////////////////////////////////
- internal void ScanDateWord(String pattern)
+ internal void ScanDateWord(string pattern)
{
// Check if we have found all of the year/month/day pattern.
_ymdFlags = FoundDatePattern.None;
@@ -479,7 +479,7 @@ namespace System.Globalization
i++;
break;
default:
- if (_ymdFlags == FoundDatePattern.FoundYMDPatternFlag && !Char.IsWhiteSpace(ch))
+ if (_ymdFlags == FoundDatePattern.FoundYMDPatternFlag && !char.IsWhiteSpace(ch))
{
// We are not seeing "." after YMD. Clear the flag.
_ymdFlags = FoundDatePattern.None;
@@ -497,10 +497,10 @@ namespace System.Globalization
//
////////////////////////////////////////////////////////////////////////////
- internal String[] GetDateWordsOfDTFI(DateTimeFormatInfo dtfi)
+ internal string[] GetDateWordsOfDTFI(DateTimeFormatInfo dtfi)
{
// Enumarate all LongDatePatterns, and get the DateWords and scan for month postfix.
- String[] datePatterns = dtfi.GetAllDateTimePatterns('D');
+ string[] datePatterns = dtfi.GetAllDateTimePatterns('D');
int i;
// Scan the long date patterns
@@ -539,10 +539,10 @@ namespace System.Globalization
ScanDateWord(datePatterns[i]);
}
- String[] result = null;
+ string[] result = null;
if (m_dateWords != null && m_dateWords.Count > 0)
{
- result = new String[m_dateWords.Count];
+ result = new string[m_dateWords.Count];
for (i = 0; i < m_dateWords.Count; i++)
{
result[i] = m_dateWords[i];
@@ -558,7 +558,7 @@ namespace System.Globalization
// the format flag.
//
////////////////////////////////////////////////////////////////////////////
- internal static FORMATFLAGS GetFormatFlagGenitiveMonth(String[] monthNames, String[] genitveMonthNames, String[] abbrevMonthNames, String[] genetiveAbbrevMonthNames)
+ internal static FORMATFLAGS GetFormatFlagGenitiveMonth(string[] monthNames, string[] genitveMonthNames, string[] abbrevMonthNames, string[] genetiveAbbrevMonthNames)
{
// If we have different names in regular and genitive month names, use genitive month flag.
return ((!EqualStringArrays(monthNames, genitveMonthNames) || !EqualStringArrays(abbrevMonthNames, genetiveAbbrevMonthNames))
@@ -570,7 +570,7 @@ namespace System.Globalization
// Scan the month names to see if spaces are used or start with a digit, and return the format flag
//
////////////////////////////////////////////////////////////////////////////
- internal static FORMATFLAGS GetFormatFlagUseSpaceInMonthNames(String[] monthNames, String[] genitveMonthNames, String[] abbrevMonthNames, String[] genetiveAbbrevMonthNames)
+ internal static FORMATFLAGS GetFormatFlagUseSpaceInMonthNames(string[] monthNames, string[] genitveMonthNames, string[] abbrevMonthNames, string[] genetiveAbbrevMonthNames)
{
FORMATFLAGS formatFlags = 0;
formatFlags |= (ArrayElementsBeginWithDigit(monthNames) ||
@@ -592,7 +592,7 @@ namespace System.Globalization
// Scan the day names and set the correct format flag.
//
////////////////////////////////////////////////////////////////////////////
- internal static FORMATFLAGS GetFormatFlagUseSpaceInDayNames(String[] dayNames, String[] abbrevDayNames)
+ internal static FORMATFLAGS GetFormatFlagUseSpaceInDayNames(string[] dayNames, string[] abbrevDayNames)
{
return ((ArrayElementsHaveSpace(dayNames) ||
ArrayElementsHaveSpace(abbrevDayNames))
@@ -659,7 +659,7 @@ namespace System.Globalization
// so we don't have to go to native code side.
for (int j = 0; j < array[i].Length; j++)
{
- if (Char.IsWhiteSpace(array[i][j]))
+ if (char.IsWhiteSpace(array[i][j]))
{
return true;
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs
index 5b285eb5d..8d703ea98 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/DateTimeParse.cs
@@ -11,7 +11,7 @@ namespace System
{
internal static class DateTimeParse
{
- internal const Int32 MaxDateTimeNumberDigits = 8;
+ internal const int MaxDateTimeNumberDigits = 8;
internal delegate bool MatchNumberDelegate(ref __DTString str, int digitLen, out int result);
@@ -96,7 +96,7 @@ namespace System
return DoStrictParse(s, format, style, dtfi, ref result);
}
- internal static DateTime ParseExactMultiple(ReadOnlySpan<char> s, String[] formats,
+ internal static DateTime ParseExactMultiple(ReadOnlySpan<char> s, string[] formats,
DateTimeFormatInfo dtfi, DateTimeStyles style)
{
DateTimeResult result = new DateTimeResult(); // The buffer to store the parsing result.
@@ -112,7 +112,7 @@ namespace System
}
- internal static DateTime ParseExactMultiple(ReadOnlySpan<char> s, String[] formats,
+ internal static DateTime ParseExactMultiple(ReadOnlySpan<char> s, string[] formats,
DateTimeFormatInfo dtfi, DateTimeStyles style, out TimeSpan offset)
{
DateTimeResult result = new DateTimeResult(); // The buffer to store the parsing result.
@@ -130,7 +130,7 @@ namespace System
}
}
- internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, String[] formats,
+ internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, string[] formats,
DateTimeFormatInfo dtfi, DateTimeStyles style, out DateTime result, out TimeSpan offset)
{
result = DateTime.MinValue;
@@ -148,7 +148,7 @@ namespace System
}
- internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, String[] formats,
+ internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, string[] formats,
DateTimeFormatInfo dtfi, DateTimeStyles style, out DateTime result)
{
result = DateTime.MinValue;
@@ -162,7 +162,7 @@ namespace System
return false;
}
- internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, String[] formats,
+ internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, string[] formats,
DateTimeFormatInfo dtfi, DateTimeStyles style, ref DateTimeResult result)
{
if (formats == null)
@@ -331,7 +331,7 @@ namespace System
//
////////////////////////////////////////////////////////////////////////////
- // End NumEnd NumAmPm NumSpace NumDaySep NumTimesep MonthEnd MonthSpace MonthDSep NumDateSuff NumTimeSuff DayOfWeek YearSpace YearDateSep YearEnd TimeZone Era UTCTimeMark
+ // End NumEnd NumAmPm NumSpace NumDaySep NumTimesep MonthEnd MonthSpace MonthDSep NumDateSuff NumTimeSuff DayOfWeek YearSpace YearDateSep YearEnd TimeZone Era UTCTimeMark
private static DS[][] dateParsingStates = {
// DS.BEGIN // DS.BEGIN
new DS[] { DS.BEGIN, DS.ERROR, DS.TX_N, DS.N, DS.D_Nd, DS.T_Nt, DS.ERROR, DS.D_M, DS.D_M, DS.D_S, DS.T_S, DS.BEGIN, DS.D_Y, DS.D_Y, DS.ERROR, DS.BEGIN, DS.BEGIN, DS.ERROR},
@@ -395,13 +395,13 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
};
// End NumEnd NumAmPm NumSpace NumDaySep NumTimesep MonthEnd MonthSpace MonthDSep NumDateSuff NumTimeSuff DayOfWeek YearSpace YearDateSep YearEnd TimeZone Era UTCMark
- internal const String GMTName = "GMT";
- internal const String ZuluName = "Z";
+ internal const string GMTName = "GMT";
+ internal const string ZuluName = "Z";
//
// Search from the index of str at str.Index to see if the target string exists in the str.
//
- private static bool MatchWord(ref __DTString str, String target)
+ private static bool MatchWord(ref __DTString str, string target)
{
if (target.Length > (str.Value.Length - str.Index))
{
@@ -418,7 +418,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (nextCharIndex < str.Value.Length)
{
char nextCh = str.Value[nextCharIndex];
- if (Char.IsLetter(nextCh))
+ if (char.IsLetter(nextCh))
{
return (false);
}
@@ -573,7 +573,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
char nextCh = str.Value[str.Index];
// Skip whitespace, but don't update the index unless we find a time zone marker
int whitespaceCount = 0;
- while (Char.IsWhiteSpace(nextCh) && str.Index + whitespaceCount < str.Length - 1)
+ while (char.IsWhiteSpace(nextCh) && str.Index + whitespaceCount < str.Length - 1)
{
whitespaceCount++;
nextCh = str.Value[str.Index + whitespaceCount];
@@ -602,7 +602,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// This is the lexer. Check the character at the current index, and put the found token in dtok and
// some raw date/time information in raw.
//
- private static Boolean Lex(DS dps, ref __DTString str, ref DateTimeToken dtok, ref DateTimeRawInfo raw, ref DateTimeResult result, ref DateTimeFormatInfo dtfi, DateTimeStyles styles)
+ private static bool Lex(DS dps, ref __DTString str, ref DateTimeToken dtok, ref DateTimeRawInfo raw, ref DateTimeResult result, ref DateTimeFormatInfo dtfi, DateTimeStyles styles)
{
TokenType tokenType;
int tokenValue;
@@ -713,7 +713,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- // we have the date and time separators are same and getting a year number, then change the token to YearDateSep as
+ // we have the date and time separators are same and getting a year number, then change the token to YearDateSep as
// we are sure we are not parsing time.
dtok.dtt = DTT.YearDateSep;
break;
@@ -1002,7 +1002,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- // we have the date and time separators are same and getting a Month name, then change the token to MonthDatesep as
+ // we have the date and time separators are same and getting a Month name, then change the token to MonthDatesep as
// we are sure we are not parsing time.
dtok.dtt = DTT.MonthDatesep;
break;
@@ -1119,7 +1119,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
break;
case TokenType.UnknownToken:
- if (Char.IsLetter(str.m_current))
+ if (char.IsLetter(str.m_current))
{
result.SetFailure(ParseFailureKind.FormatWithOriginalDateTimeAndParameter, nameof(SR.Format_UnknownDateTimeWord), str.Index);
LexTraceExit("0200", dps);
@@ -1128,7 +1128,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if ((str.m_current == '-' || str.m_current == '+') && ((result.flags & ParseFlags.TimeZoneUsed) == 0))
{
- Int32 originalIndex = str.Index;
+ int originalIndex = str.Index;
if (ParseTimeZone(ref str, ref result.timeZoneOffset))
{
result.flags |= ParseFlags.TimeZoneUsed;
@@ -1160,10 +1160,10 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean VerifyValidPunctuation(ref __DTString str)
+ private static bool VerifyValidPunctuation(ref __DTString str)
{
// Compatability Behavior. Allow trailing nulls and surrounding hashes
- Char ch = str.Value[str.Index];
+ char ch = str.Value[str.Index];
if (ch == '#')
{
bool foundStart = false;
@@ -1198,7 +1198,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
}
- else if ((!Char.IsWhiteSpace(ch)))
+ else if ((!char.IsWhiteSpace(ch)))
{
// Anything other than whitespace outside hashes is invalid
if (!foundStart || foundEnd)
@@ -1212,7 +1212,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// The has was un-paired
return false;
}
- // Valid Hash usage: eat the hash and continue.
+ // Valid Hash usage: eat the hash and continue.
str.GetNext();
return true;
}
@@ -1247,7 +1247,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
// Return 0 for YMD, 1 for MDY, 2 for DMY, otherwise -1.
//
- private static Boolean GetYearMonthDayOrder(String datePattern, DateTimeFormatInfo dtfi, out int order)
+ private static bool GetYearMonthDayOrder(string datePattern, DateTimeFormatInfo dtfi, out int order)
{
int yearOrder = -1;
int monthOrder = -1;
@@ -1345,7 +1345,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
// Return 0 for YM, 1 for MY, otherwise -1.
//
- private static Boolean GetYearMonthOrder(String pattern, DateTimeFormatInfo dtfi, out int order)
+ private static bool GetYearMonthOrder(string pattern, DateTimeFormatInfo dtfi, out int order)
{
int yearOrder = -1;
int monthOrder = -1;
@@ -1411,7 +1411,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
// Return 0 for MD, 1 for DM, otherwise -1.
//
- private static Boolean GetMonthDayOrder(String pattern, DateTimeFormatInfo dtfi, out int order)
+ private static bool GetMonthDayOrder(string pattern, DateTimeFormatInfo dtfi, out int order)
{
int monthOrder = -1;
int dayOrder = -1;
@@ -1539,7 +1539,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
// Processing teriminal case: DS.DX_NN
- private static Boolean GetDayOfNN(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfNN(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1582,7 +1582,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
// Processing teriminal case: DS.DX_NNN
- private static Boolean GetDayOfNNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfNNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1639,7 +1639,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- private static Boolean GetDayOfMN(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfMN(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1701,7 +1701,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
////////////////////////////////////////////////////////////////////////
- private static Boolean GetHebrewDayOfNM(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetHebrewDayOfNM(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
int monthDayOrder;
if (!GetMonthDayOrder(dtfi.MonthDayPattern, dtfi, out monthDayOrder))
@@ -1722,7 +1722,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- private static Boolean GetDayOfNM(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfNM(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1778,7 +1778,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean GetDayOfMNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfMNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1848,7 +1848,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- private static Boolean GetDayOfYNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfYNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1859,7 +1859,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int n1 = raw.GetNumber(0);
int n2 = raw.GetNumber(1);
- String pattern = dtfi.ShortDatePattern;
+ string pattern = dtfi.ShortDatePattern;
// For compatibility, don't throw if we can't determine the order, but default to YMD instead
int order;
@@ -1883,7 +1883,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- private static Boolean GetDayOfNNY(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDayOfNNY(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1923,7 +1923,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
- private static Boolean GetDayOfYMN(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetDayOfYMN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1941,7 +1941,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- private static Boolean GetDayOfYN(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetDayOfYN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -1959,7 +1959,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return false;
}
- private static Boolean GetDayOfYM(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetDayOfYM(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if ((result.flags & ParseFlags.HaveDate) != 0)
{
@@ -2004,7 +2004,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
// Adjust hour according to the time mark.
//
- private static Boolean AdjustHour(ref int hour, TM timeMark)
+ private static bool AdjustHour(ref int hour, TM timeMark)
{
if (timeMark != TM.NotSet)
{
@@ -2031,7 +2031,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean GetTimeOfN(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetTimeOfN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if ((result.flags & ParseFlags.HaveTime) != 0)
{
@@ -2052,7 +2052,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean GetTimeOfNN(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetTimeOfNN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
Debug.Assert(raw.numCount >= 2, "raw.numCount >= 2");
if ((result.flags & ParseFlags.HaveTime) != 0)
@@ -2068,7 +2068,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean GetTimeOfNNN(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetTimeOfNNN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if ((result.flags & ParseFlags.HaveTime) != 0)
{
@@ -2087,7 +2087,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
// Processing terminal state: A Date suffix followed by one number.
//
- private static Boolean GetDateOfDSN(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetDateOfDSN(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if (raw.numCount != 1 || result.Day != -1)
{
@@ -2098,7 +2098,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean GetDateOfNDS(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ private static bool GetDateOfNDS(ref DateTimeResult result, ref DateTimeRawInfo raw)
{
if (result.Month == -1)
{
@@ -2122,7 +2122,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return true;
}
- private static Boolean GetDateOfNNDS(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ private static bool GetDateOfNNDS(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
// For partial CJK Dates, the only valid formats are with a specified year, followed by two numbers, which
// will be the Month and Day, and with a specified Month, when the numbers are either the year and day or
@@ -2236,7 +2236,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
////////////////////////////////////////////////////////////////////////
- internal static Boolean ProcessHebrewTerminalState(DS dps, ref __DTString str, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ internal static bool ProcessHebrewTerminalState(DS dps, ref __DTString str, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
// The following are accepted terminal state for Hebrew date.
switch (dps)
@@ -2346,7 +2346,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// A terminal state has been reached, call the appropriate function to fill in the parsing result.
// Return true if the state is a terminal state.
//
- internal static Boolean ProcessTerminalState(DS dps, ref __DTString str, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ internal static bool ProcessTerminalState(DS dps, ref __DTString str, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
{
bool passed = true;
switch (dps)
@@ -2516,7 +2516,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
DateTimeRawInfo raw = new DateTimeRawInfo(); // The buffer to store temporary parsing information.
unsafe
{
- Int32* numberPointer = stackalloc Int32[3];
+ int* numberPointer = stackalloc int[3];
raw.Init(numberPointer);
}
raw.hasSameDateAndTimeSeparators = dtfi.DateSeparator.Equals(dtfi.TimeSeparator, StringComparison.Ordinal);
@@ -2591,7 +2591,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
if (dtok.dtt == DTT.YearEnd || dtok.dtt == DTT.YearSpace || dtok.dtt == DTT.YearDateSep)
{
- // When time and date separators are same and we are hitting a year number while the first parsed part of the string was recognized
+ // When time and date separators are same and we are hitting a year number while the first parsed part of the string was recognized
// as part of time (and not a date) DS.T_Nt, DS.T_NNt then change the state to be a date so we try to parse it as a date instead
if (dps == DS.T_Nt)
{
@@ -2608,7 +2608,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
switch (dtok.dtt)
{
- // we have the case of Serbia have dates in forms 'd.M.yyyy.' so we can expect '.' after the date parts.
+ // we have the case of Serbia have dates in forms 'd.M.yyyy.' so we can expect '.' after the date parts.
// changing the token to end with space instead of Date Separator will avoid failing the parsing.
case DTT.YearDateSep: dtok.dtt = atEnd ? DTT.YearEnd : DTT.YearSpace; break;
@@ -2719,7 +2719,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
result.parsedDate = time;
- if (!DetermineTimeZoneAdjustments(ref str, ref result, styles, bTimeOnly))
+ if (!DetermineTimeZoneAdjustments(ref result, styles, bTimeOnly))
{
TPTraceExit("0120 (DetermineTimeZoneAdjustments)", dps);
return false;
@@ -2730,17 +2730,17 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// Handles time zone adjustments and sets DateTimeKind values as required by the styles
- private static Boolean DetermineTimeZoneAdjustments(ref __DTString str, ref DateTimeResult result, DateTimeStyles styles, Boolean bTimeOnly)
+ private static bool DetermineTimeZoneAdjustments(ref DateTimeResult result, DateTimeStyles styles, bool bTimeOnly)
{
if ((result.flags & ParseFlags.CaptureOffset) != 0)
{
- // This is a DateTimeOffset parse, so the offset will actually be captured directly, and
+ // This is a DateTimeOffset parse, so the offset will actually be captured directly, and
// no adjustment is required in most cases
- return DateTimeOffsetTimeZonePostProcessing(ref str, ref result, styles);
+ return DateTimeOffsetTimeZonePostProcessing(ref result, styles);
}
else
{
- Int64 offsetTicks = result.timeZoneOffset.Ticks;
+ long offsetTicks = result.timeZoneOffset.Ticks;
// the DateTime offset must be within +- 14:00 hours.
if (offsetTicks < DateTimeOffset.MinOffset || offsetTicks > DateTimeOffset.MaxOffset)
@@ -2808,9 +2808,9 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
// Apply validation and adjustments specific to DateTimeOffset
- private static Boolean DateTimeOffsetTimeZonePostProcessing(ref __DTString str, ref DateTimeResult result, DateTimeStyles styles)
+ private static bool DateTimeOffsetTimeZonePostProcessing(ref DateTimeResult result, DateTimeStyles styles)
{
- // For DateTimeOffset, default to the Utc or Local offset when an offset was not specified by
+ // For DateTimeOffset, default to the Utc or Local offset when an offset was not specified by
// the input string.
if ((result.flags & ParseFlags.TimeZoneUsed) == 0)
{
@@ -2826,14 +2826,14 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
}
- Int64 offsetTicks = result.timeZoneOffset.Ticks;
+ long offsetTicks = result.timeZoneOffset.Ticks;
// there should be no overflow, because the offset can be no more than -+100 hours and the date already
// fits within a DateTime.
- Int64 utcTicks = result.parsedDate.Ticks - offsetTicks;
+ long utcTicks = result.parsedDate.Ticks - offsetTicks;
// For DateTimeOffset, both the parsed time and the corresponding UTC value must be within the boundaries
- // of a DateTime instance.
+ // of a DateTime instance.
if (utcTicks < DateTime.MinTicks || utcTicks > DateTime.MaxTicks)
{
result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_UTCOutOfRange));
@@ -2854,7 +2854,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (((result.flags & ParseFlags.TimeZoneUsed) == 0) && ((styles & DateTimeStyles.AssumeUniversal) == 0))
{
// Handle the special case where the timeZoneOffset was defaulted to Local
- Boolean toUtcResult = AdjustTimeZoneToUniversal(ref result);
+ bool toUtcResult = AdjustTimeZoneToUniversal(ref result);
result.timeZoneOffset = TimeSpan.Zero;
return toUtcResult;
}
@@ -2875,7 +2875,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// the time is 2001/06/08 14:00, and timeZoneOffset = -07:00.
// The result will be "2001/06/08 21:00"
//
- private static Boolean AdjustTimeZoneToUniversal(ref DateTimeResult result)
+ private static bool AdjustTimeZoneToUniversal(ref DateTimeResult result)
{
long resultTicks = result.parsedDate.Ticks;
resultTicks -= result.timeZoneOffset.Ticks;
@@ -2900,12 +2900,12 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// the time is 2001/06/08 14:00, and timeZoneOffset = -05:00.
// The result will be "2001/06/08 11:00"
//
- private static Boolean AdjustTimeZoneToLocal(ref DateTimeResult result, bool bTimeOnly)
+ private static bool AdjustTimeZoneToLocal(ref DateTimeResult result, bool bTimeOnly)
{
long resultTicks = result.parsedDate.Ticks;
// Convert to local ticks
TimeZoneInfo tz = TimeZoneInfo.Local;
- Boolean isAmbiguousLocalDst = false;
+ bool isAmbiguousLocalDst = false;
if (resultTicks < Calendar.TicksPerDay)
{
//
@@ -2936,7 +2936,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
// Convert the GMT time to local time.
DateTime utcDt = new DateTime(resultTicks, DateTimeKind.Utc);
- Boolean isDaylightSavings = false;
+ bool isDaylightSavings = false;
resultTicks += TimeZoneInfo.GetUtcOffsetFromUtc(utcDt, TimeZoneInfo.Local, out isDaylightSavings, out isAmbiguousLocalDst).Ticks;
}
}
@@ -3061,7 +3061,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
time = time.AddTicks((long)Math.Round(partSecond * Calendar.TicksPerSecond));
result.parsedDate = time;
- if (!DetermineTimeZoneAdjustments(ref str, ref result, styles, false))
+ if (!DetermineTimeZoneAdjustments(ref result, styles, false))
{
return false;
}
@@ -3315,7 +3315,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int monthsInYear = (dtfi.GetMonthName(13).Length == 0 ? 12 : 13);
for (int i = 1; i <= monthsInYear; i++)
{
- String searchStr = dtfi.GetAbbreviatedMonthName(i);
+ string searchStr = dtfi.GetAbbreviatedMonthName(i);
int matchStrLen = searchStr.Length;
if (dtfi.HasSpacesInMonthNames
? str.MatchSpecifiedWords(searchStr, false, ref matchStrLen)
@@ -3373,7 +3373,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int monthsInYear = (dtfi.GetMonthName(13).Length == 0 ? 12 : 13);
for (int i = 1; i <= monthsInYear; i++)
{
- String searchStr = dtfi.GetMonthName(i);
+ string searchStr = dtfi.GetMonthName(i);
int matchStrLen = searchStr.Length;
if (dtfi.HasSpacesInMonthNames
? str.MatchSpecifiedWords(searchStr, false, ref matchStrLen)
@@ -3438,7 +3438,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
for (DayOfWeek i = DayOfWeek.Sunday; i <= DayOfWeek.Saturday; i++)
{
- String searchStr = dtfi.GetAbbreviatedDayName(i);
+ string searchStr = dtfi.GetAbbreviatedDayName(i);
int matchStrLen = searchStr.Length;
if (dtfi.HasSpacesInDayNames
? str.MatchSpecifiedWords(searchStr, false, ref matchStrLen)
@@ -3477,7 +3477,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
for (DayOfWeek i = DayOfWeek.Sunday; i <= DayOfWeek.Saturday; i++)
{
- String searchStr = dtfi.GetDayName(i);
+ string searchStr = dtfi.GetDayName(i);
int matchStrLen = searchStr.Length;
if (dtfi.HasSpacesInDayNames
? str.MatchSpecifiedWords(searchStr, false, ref matchStrLen)
@@ -3517,7 +3517,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
for (int i = 0; i < eras.Length; i++)
{
- String searchStr = dtfi.GetEraName(eras[i]);
+ string searchStr = dtfi.GetEraName(eras[i]);
if (str.MatchSpecifiedWord(searchStr))
{
str.Index += (searchStr.Length - 1);
@@ -3560,7 +3560,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (str.GetNext())
{
- String searchStr = dtfi.AMDesignator;
+ string searchStr = dtfi.AMDesignator;
if (searchStr.Length > 0)
{
if (str.MatchSpecifiedWord(searchStr))
@@ -3668,7 +3668,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
}
- // assume the offset is Local
+ // assume the offset is Local
return DateTime.Now;
}
@@ -3774,7 +3774,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// This method also set the dtfi according/parseInfo to some special pre-defined
// formats.
//
- private static String ExpandPredefinedFormat(ReadOnlySpan<char> format, ref DateTimeFormatInfo dtfi, ref ParsingInfo parseInfo, ref DateTimeResult result)
+ private static string ExpandPredefinedFormat(ReadOnlySpan<char> format, ref DateTimeFormatInfo dtfi, ref ParsingInfo parseInfo, ref DateTimeResult result)
{
//
// Check the format to see if we need to override the dtfi to be InvariantInfo,
@@ -3782,24 +3782,14 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
//
switch (format[0])
{
+ case 's': // Sortable format (in local time)
case 'o':
case 'O': // Round Trip Format
- parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
- dtfi = DateTimeFormatInfo.InvariantInfo;
+ ConfigureFormatOS(ref dtfi, ref parseInfo);
break;
case 'r':
case 'R': // RFC 1123 Standard. (in Universal time)
- parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
- dtfi = DateTimeFormatInfo.InvariantInfo;
-
- if ((result.flags & ParseFlags.CaptureOffset) != 0)
- {
- result.flags |= ParseFlags.Rfc1123Pattern;
- }
- break;
- case 's': // Sortable format (in local time)
- dtfi = DateTimeFormatInfo.InvariantInfo;
- parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
+ ConfigureFormatR(ref dtfi, ref parseInfo, ref result);
break;
case 'u': // Universal time format in sortable format.
parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
@@ -3829,9 +3819,21 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return (DateTimeFormat.GetRealFormat(format, dtfi));
}
+ private static void ConfigureFormatR(ref DateTimeFormatInfo dtfi, ref ParsingInfo parseInfo, ref DateTimeResult result)
+ {
+ parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
+ dtfi = DateTimeFormatInfo.InvariantInfo;
+ if ((result.flags & ParseFlags.CaptureOffset) != 0)
+ {
+ result.flags |= ParseFlags.Rfc1123Pattern;
+ }
+ }
-
-
+ private static void ConfigureFormatOS(ref DateTimeFormatInfo dtfi, ref ParsingInfo parseInfo)
+ {
+ parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
+ dtfi = DateTimeFormatInfo.InvariantInfo;
+ }
// Given a specified format character, parse and update the parsing result.
//
@@ -4201,7 +4203,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// Some cultures uses space in the quoted string. E.g. Spanish has long date format as:
// "dddd, dd' de 'MMMM' de 'yyyy". When inner spaces flag is set, we should skip whitespaces if there is space
// in the quoted string.
- String quotedStr = StringBuilderCache.GetStringAndRelease(enquotedString);
+ string quotedStr = StringBuilderCache.GetStringAndRelease(enquotedString);
for (int i = 0; i < quotedStr.Length; i++)
{
@@ -4218,7 +4220,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
// The "r" and "u" formats incorrectly quoted 'GMT' and 'Z', respectively. We cannot
- // correct this mistake for DateTime.ParseExact for compatibility reasons, but we can
+ // correct this mistake for DateTime.ParseExact for compatibility reasons, but we can
// fix it for DateTimeOffset.ParseExact as DateTimeOffset has not been publically released
// with this issue.
if ((result.flags & ParseFlags.CaptureOffset) != 0)
@@ -4443,12 +4445,32 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
if (formatParam.Length == 1)
{
- if (((result.flags & ParseFlags.CaptureOffset) != 0) && formatParam[0] == 'U')
+ char formatParamChar = formatParam[0];
+
+ // Fast-paths for common and important formats/configurations.
+ if (styles == DateTimeStyles.None)
+ {
+ switch (formatParamChar)
+ {
+ case 'R':
+ case 'r':
+ ConfigureFormatR(ref dtfi, ref parseInfo, ref result);
+ return ParseFormatR(s, ref parseInfo, ref result);
+
+ case 'O':
+ case 'o':
+ ConfigureFormatOS(ref dtfi, ref parseInfo);
+ return ParseFormatO(s, ref parseInfo, ref result);
+ }
+ }
+
+ if (((result.flags & ParseFlags.CaptureOffset) != 0) && formatParamChar == 'U')
{
// The 'U' format is not allowed for DateTimeOffset
result.SetBadFormatSpecifierFailure(formatParam);
return false;
}
+
formatParam = ExpandPredefinedFormat(formatParam, ref dtfi, ref parseInfo, ref result);
}
@@ -4614,13 +4636,417 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
- if (!DetermineTimeZoneAdjustments(ref str, ref result, styles, bTimeOnly))
+ if (!DetermineTimeZoneAdjustments(ref result, styles, bTimeOnly))
{
return false;
}
return true;
}
+ private static bool ParseFormatR(ReadOnlySpan<char> source, ref ParsingInfo parseInfo, ref DateTimeResult result)
+ {
+ // Example:
+ // Tue, 03 Jan 2017 08:08:05 GMT
+
+ // The format is exactly 29 characters.
+ if ((uint)source.Length != 29)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Parse the three-letter day of week. Any casing is valid.
+ DayOfWeek dayOfWeek;
+ {
+ uint dow0 = source[0], dow1 = source[1], dow2 = source[2], comma = source[3];
+
+ if ((dow0 | dow1 | dow2 | comma) > 0x7F)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ uint dowString = (dow0 << 24) | (dow1 << 16) | (dow2 << 8) | comma | 0x20202000;
+ switch (dowString)
+ {
+ case 0x73756E2c /* 'sun,' */: dayOfWeek = DayOfWeek.Sunday; break;
+ case 0x6d6f6e2c /* 'mon,' */: dayOfWeek = DayOfWeek.Monday; break;
+ case 0x7475652c /* 'tue,' */: dayOfWeek = DayOfWeek.Tuesday; break;
+ case 0x7765642c /* 'wed,' */: dayOfWeek = DayOfWeek.Wednesday; break;
+ case 0x7468752c /* 'thu,' */: dayOfWeek = DayOfWeek.Thursday; break;
+ case 0x6672692c /* 'fri,' */: dayOfWeek = DayOfWeek.Friday; break;
+ case 0x7361742c /* 'sat,' */: dayOfWeek = DayOfWeek.Saturday; break;
+ default:
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+ }
+
+ if (source[4] != ' ')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Parse the two digit day.
+ int day;
+ {
+ uint digit1 = (uint)(source[5] - '0'), digit2 = (uint)(source[6] - '0');
+
+ if (digit1 > 9 || digit2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ day = (int)(digit1*10 + digit2);
+ }
+
+ if (source[7] != ' ')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Parse the three letter month (followed by a space). Any casing is valid.
+ int month;
+ {
+ uint m0 = source[8], m1 = source[9], m2 = source[10], space = source[11];
+
+ if ((m0 | m1 | m2 | space) > 0x7F)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ switch ((m0 << 24) | (m1 << 16) | (m2 << 8) | space | 0x20202000)
+ {
+ case 0x6a616e20 /* 'jan ' */ : month = 1; break;
+ case 0x66656220 /* 'feb ' */ : month = 2; break;
+ case 0x6d617220 /* 'mar ' */ : month = 3; break;
+ case 0x61707220 /* 'apr ' */ : month = 4; break;
+ case 0x6d617920 /* 'may ' */ : month = 5; break;
+ case 0x6a756e20 /* 'jun ' */ : month = 6; break;
+ case 0x6a756c20 /* 'jul ' */ : month = 7; break;
+ case 0x61756720 /* 'aug ' */ : month = 8; break;
+ case 0x73657020 /* 'sep ' */ : month = 9; break;
+ case 0x6f637420 /* 'oct ' */ : month = 10; break;
+ case 0x6e6f7620 /* 'nov ' */ : month = 11; break;
+ case 0x64656320 /* 'dec ' */ : month = 12; break;
+ default:
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+ }
+
+ // Parse the four-digit year.
+ int year;
+ {
+ uint y1 = (uint)(source[12] - '0'), y2 = (uint)(source[13] - '0'), y3 = (uint)(source[14] - '0'), y4 = (uint)(source[15] - '0');
+
+ if (y1 > 9 || y2 > 9 || y3 > 9 || y4 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ year = (int)(y1*1000 + y2*100 + y3*10 + y4);
+ }
+
+ if (source[16] != ' ')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Parse the two digit hour.
+ int hour;
+ {
+ uint h1 = (uint)(source[17] - '0'), h2 = (uint)(source[18] - '0');
+
+ if (h1 > 9 || h2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ hour = (int)(h1*10 + h2);
+ }
+
+ if (source[19] != ':')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Parse the two-digit minute.
+ int minute;
+ {
+ uint m1 = (uint)(source[20] - '0');
+ uint m2 = (uint)(source[21] - '0');
+
+ if (m1 > 9 || m2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ minute = (int)(m1*10 + m2);
+ }
+
+ if (source[22] != ':')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Parse the two-digit second.
+ int second;
+ {
+ uint s1 = (uint)(source[23] - '0'), s2 = (uint)(source[24] - '0');
+
+ if (s1 > 9 || s2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ second = (int)(s1*10 + s2);
+ }
+
+ // Parse " GMT". It must be upper case.
+ if (source[25] != ' ' || source[26] != 'G' || source[27] != 'M' || source[28] != 'T')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ // Validate that the parsed date is valid according to the calendar.
+ if (!parseInfo.calendar.TryToDateTime(year, month, day, hour, minute, second, 0, 0, out result.parsedDate))
+ {
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, nameof(SR.Format_BadDateTimeCalendar));
+ return false;
+ }
+
+ // And validate that the parsed day of week matches what the calendar said it should be.
+ if (dayOfWeek != result.parsedDate.DayOfWeek)
+ {
+ result.SetFailure(ParseFailureKind.FormatWithOriginalDateTime, nameof(SR.Format_BadDayOfWeek));
+ return false;
+ }
+
+ return true;
+ }
+
+ private static bool ParseFormatO(ReadOnlySpan<char> source, ref ParsingInfo parseInfo, ref DateTimeResult result)
+ {
+ // Examples:
+ // 2017-06-12T05:30:45.7680000 (interpreted as local time wrt to current time zone)
+ // 2017-06-12T05:30:45.7680000Z (Z is short for "+00:00" but also distinguishes DateTimeKind.Utc from DateTimeKind.Local)
+ // 2017-06-12T05:30:45.7680000-7:00 (special-case of one-digit offset hour)
+ // 2017-06-12T05:30:45.7680000-07:00
+
+ if ((uint)source.Length < 27 ||
+ source[4] != '-' ||
+ source[7] != '-' ||
+ source[10] != 'T' ||
+ source[13] != ':' ||
+ source[16] != ':' ||
+ source[19] != '.')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ int year;
+ {
+ uint y1 = (uint)(source[0] - '0'), y2 = (uint)(source[1] - '0'), y3 = (uint)(source[2] - '0'), y4 = (uint)(source[3] - '0');
+
+ if (y1 > 9 || y2 > 9 || y3 > 9 || y4 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ year = (int)(y1*1000 + y2*100 + y3*10 + y4);
+ }
+
+ int month;
+ {
+ uint m1 = (uint)(source[5] - '0'), m2 = (uint)(source[6] - '0');
+
+ if (m1 > 9 || m2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ month = (int)(m1*10 + m2);
+ }
+
+ int day;
+ {
+ uint d1 = (uint)(source[8] - '0'), d2 = (uint)(source[9] - '0');
+
+ if (d1 > 9 || d2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ day = (int)(d1*10 + d2);
+ }
+
+ int hour;
+ {
+ uint h1 = (uint)(source[11] - '0'), h2 = (uint)(source[12] - '0');
+
+ if (h1 > 9 || h2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ hour = (int)(h1*10 + h2);
+ }
+
+ int minute;
+ {
+ uint m1 = (uint)(source[14] - '0'), m2 = (uint)(source[15] - '0');
+
+ if (m1 > 9 || m2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ minute = (int)(m1*10 + m2);
+ }
+
+ int second;
+ {
+ uint s1 = (uint)(source[17] - '0'), s2 = (uint)(source[18] - '0');
+
+ if (s1 > 9 || s2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ second = (int)(s1*10 + s2);
+ }
+
+ double fraction;
+ {
+ uint f1 = (uint)(source[20] - '0');
+ uint f2 = (uint)(source[21] - '0');
+ uint f3 = (uint)(source[22] - '0');
+ uint f4 = (uint)(source[23] - '0');
+ uint f5 = (uint)(source[24] - '0');
+ uint f6 = (uint)(source[25] - '0');
+ uint f7 = (uint)(source[26] - '0');
+
+ if (f1 > 9 || f2 > 9 || f3 > 9 || f4 > 9 || f5 > 9 || f6 > 9 || f7 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ fraction = (f1*1000000 + f2*100000 + f3*10000 + f4*1000 + f5*100 + f6*10 + f7) / 10000000.0;
+ }
+
+ if (!DateTime.TryCreate(year, month, day, hour, minute, second, 0, out DateTime dateTime))
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+ result.parsedDate = dateTime.AddTicks((long)Math.Round(fraction * Calendar.TicksPerSecond));
+
+ if ((uint)source.Length > 27)
+ {
+ char offsetChar = source[27];
+ switch (offsetChar)
+ {
+ case 'Z':
+ if (source.Length != 28)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+ result.flags |= ParseFlags.TimeZoneUsed | ParseFlags.TimeZoneUtc;
+ break;
+
+ case '+':
+ case '-':
+ int offsetHours, colonIndex;
+
+ if ((uint)source.Length == 33)
+ {
+ uint oh1 = (uint)(source[28] - '0'), oh2 = (uint)(source[29] - '0');
+
+ if (oh1 > 9 || oh2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ offsetHours = (int)(oh1 * 10 + oh2);
+ colonIndex = 30;
+ }
+ else if ((uint)source.Length == 32) // special-case allowed for compat: only one offset hour digit
+ {
+ offsetHours = source[28] - '0';
+
+ if ((uint)offsetHours > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ colonIndex = 29;
+ }
+ else
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ if (source[colonIndex] != ':')
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ int offsetMinutes;
+ {
+ uint om1 = (uint)(source[colonIndex + 1] - '0'), om2 = (uint)(source[colonIndex + 2] - '0');
+
+ if (om1 > 9 || om2 > 9)
+ {
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+
+ offsetMinutes = (int)(om1*10 + om2);
+ }
+
+ result.flags |= ParseFlags.TimeZoneUsed;
+ result.timeZoneOffset = new TimeSpan(offsetHours, offsetMinutes, 0);
+ if (offsetChar == '-')
+ {
+ result.timeZoneOffset = result.timeZoneOffset.Negate();
+ }
+ break;
+
+ default:
+ result.SetBadDateTimeFailure();
+ return false;
+ }
+ }
+
+ return DetermineTimeZoneAdjustments(ref result, DateTimeStyles.None, bTimeOnly: false);
+ }
+
private static Exception GetDateTimeParseException(ref DateTimeResult result)
{
switch (result.failure)
@@ -4700,7 +5126,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
private static string Hex(string[] strs)
{
if (strs == null || strs.Length == 0)
- return String.Empty;
+ return string.Empty;
if (strs.Length == 1)
return Hex(strs[0]);
@@ -4713,7 +5139,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
StringBuilder buffer = new StringBuilder();
buffer.Append(Hex(strs[0]));
curLineLength = buffer.Length;
- String s;
+ string s;
for (int i = 1; i < strs.Length - 1; i++)
{
@@ -4766,7 +5192,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return buffer.ToString();
}
// return an unicode escaped string form of char c
- private static String Hex(char c)
+ private static string Hex(char c)
{
if (c <= '\x007f')
return c.ToString(CultureInfo.InvariantCulture);
@@ -4819,20 +5245,14 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
internal __DTString(ReadOnlySpan<char> str, DateTimeFormatInfo dtfi)
{
+ Debug.Assert(dtfi != null, "Expected non-null DateTimeFormatInfo");
+
Index = -1;
Value = str;
m_current = '\0';
- if (dtfi != null)
- {
- m_info = dtfi.CompareInfo;
- m_checkDigitToken = ((dtfi.FormatFlags & DateTimeFormatFlags.UseDigitPrefixInTokens) != 0);
- }
- else
- {
- m_info = CultureInfo.CurrentCulture.CompareInfo;
- m_checkDigitToken = false;
- }
+ m_info = dtfi.CompareInfo;
+ m_checkDigitToken = ((dtfi.FormatFlags & DateTimeFormatFlags.UseDigitPrefixInTokens) != 0);
}
internal CompareInfo CompareInfo
@@ -4954,13 +5374,13 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
}
}
- else if (Char.IsWhiteSpace(m_current))
+ else if (char.IsWhiteSpace(m_current))
{
// Just skip to the next character.
while (++Index < Length)
{
m_current = Value[Index];
- if (!(Char.IsWhiteSpace(m_current)))
+ if (!(char.IsWhiteSpace(m_current)))
{
goto Start;
}
@@ -5004,13 +5424,13 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal bool MatchSpecifiedWord(String target) =>
+ internal bool MatchSpecifiedWord(string target) =>
Index + target.Length <= Length &&
m_info.Compare(Value.Slice(Index, target.Length), target, CompareOptions.IgnoreCase) == 0;
- private static readonly Char[] WhiteSpaceChecks = new Char[] { ' ', '\u00A0' };
+ private static readonly char[] WhiteSpaceChecks = new char[] { ' ', '\u00A0' };
- internal bool MatchSpecifiedWords(String target, bool checkWordBoundary, ref int matchLength)
+ internal bool MatchSpecifiedWords(string target, bool checkWordBoundary, ref int matchLength)
{
int valueRemaining = Value.Length - Index;
matchLength = target.Length;
@@ -5041,11 +5461,11 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
else
{
// Make sure we also have whitespace in the input string
- if (!Char.IsWhiteSpace(Value[thisPosition + segmentLength]))
+ if (!char.IsWhiteSpace(Value[thisPosition + segmentLength]))
{
return false;
}
- if (m_info.Compare(Value.Slice(thisPosition, segmentLength), target.AsSpan().Slice(targetPosition, segmentLength), CompareOptions.IgnoreCase) != 0)
+ if (m_info.CompareOptionIgnoreCase(Value.Slice(thisPosition, segmentLength), target.AsSpan(targetPosition, segmentLength)) != 0)
{
return false;
}
@@ -5057,7 +5477,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// Skip past multiple whitespace
- while (thisPosition < Value.Length && Char.IsWhiteSpace(Value[thisPosition]))
+ while (thisPosition < Value.Length && char.IsWhiteSpace(Value[thisPosition]))
{
thisPosition++;
matchLength++;
@@ -5071,7 +5491,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
{
return false;
}
- if (m_info.Compare(Value.Slice(thisPosition, segmentLength), target.AsSpan().Slice(targetPosition, segmentLength), CompareOptions.IgnoreCase) != 0)
+ if (m_info.CompareOptionIgnoreCase(Value.Slice(thisPosition, segmentLength), target.AsSpan(targetPosition, segmentLength)) != 0)
{
return false;
}
@@ -5083,7 +5503,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
int nextCharIndex = Index + matchLength;
if (nextCharIndex < Value.Length)
{
- if (Char.IsLetter(Value[nextCharIndex]))
+ if (char.IsLetter(Value[nextCharIndex]))
{
return (false);
}
@@ -5098,7 +5518,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// If a match is found, true value is returned and Index is updated to the next character to be parsed.
// Otherwise, Index is unchanged.
//
- internal bool Match(String str)
+ internal bool Match(string str)
{
if (++Index >= Length)
{
@@ -5147,12 +5567,12 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// maxMatchStrLen [in/out] the initailized maximum length. This parameter can be used to
// find the longest match in two string arrays.
//
- internal int MatchLongestWords(String[] words, ref int maxMatchStrLen)
+ internal int MatchLongestWords(string[] words, ref int maxMatchStrLen)
{
int result = -1;
for (int i = 0; i < words.Length; i++)
{
- String word = words[i];
+ string word = words[i];
int matchLength = word.Length;
if (MatchSpecifiedWords(word, false, ref matchLength))
{
@@ -5225,7 +5645,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
while (Index + 1 < Length)
{
char ch = Value[Index + 1];
- if (!Char.IsWhiteSpace(ch))
+ if (!char.IsWhiteSpace(ch))
{
return;
}
@@ -5246,7 +5666,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
return (false);
}
- if (!Char.IsWhiteSpace(m_current))
+ if (!char.IsWhiteSpace(m_current))
{
return (true);
}
@@ -5254,7 +5674,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
while (++Index < Length)
{
m_current = Value[Index];
- if (!Char.IsWhiteSpace(m_current))
+ if (!char.IsWhiteSpace(m_current))
{
return (true);
}
@@ -5266,7 +5686,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
internal void TrimTail()
{
int i = Length - 1;
- while (i >= 0 && Char.IsWhiteSpace(Value[i]))
+ while (i >= 0 && char.IsWhiteSpace(Value[i]))
{
i--;
}
@@ -5286,14 +5706,17 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// Check if the last character is a quote.
if (ch == '\'' || ch == '\"')
{
- if (Char.IsWhiteSpace(Value[i - 1]))
+ if (char.IsWhiteSpace(Value[i - 1]))
{
i--;
- while (i >= 1 && Char.IsWhiteSpace(Value[i - 1]))
+ while (i >= 1 && char.IsWhiteSpace(Value[i - 1]))
{
i--;
}
- Value = Value.Remove(i, Value.Length - 1 - i);
+ Span<char> result = new char[i + 1];
+ result[i] = ch;
+ Value.Slice(0, i).CopyTo(result);
+ Value = result;
}
}
}
@@ -5311,13 +5734,16 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
// Check if the last character is a quote.
if (ch == '\'' || ch == '\"')
{
- while ((i + 1) < Length && Char.IsWhiteSpace(Value[i + 1]))
+ while ((i + 1) < Length && char.IsWhiteSpace(Value[i + 1]))
{
i++;
}
if (i != 0)
{
- Value = Value.Remove(1, i);
+ Span<char> result = new char[Value.Length - i];
+ result[0] = ch;
+ Value.Slice(i + 1).CopyTo(result.Slice(1));
+ Value = result;
}
}
}
@@ -5330,7 +5756,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
while (Index + sub.length < Length)
{
DTSubStringType currentType;
- Char ch = Value[Index + sub.length];
+ char ch = Value[Index + sub.length];
if (ch >= '0' && ch <= '9')
{
currentType = DTSubStringType.Number;
@@ -5406,12 +5832,12 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
internal ref struct DTSubString
{
internal ReadOnlySpan<char> s;
- internal Int32 index;
- internal Int32 length;
+ internal int index;
+ internal int length;
internal DTSubStringType type;
- internal Int32 value;
+ internal int value;
- internal Char this[Int32 relativeIndex]
+ internal char this[int relativeIndex]
{
get
{
@@ -5510,7 +5936,7 @@ new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR,
internal int Month;
internal int Day;
//
- // Set time defualt to 00:00:00.
+ // Set time default to 00:00:00.
//
internal int Hour;
internal int Minute;
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/DaylightTime.cs b/src/System.Private.CoreLib/shared/System/Globalization/DaylightTime.cs
index e6920b366..72a572c97 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/DaylightTime.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/DaylightTime.cs
@@ -11,10 +11,6 @@ namespace System.Globalization
private readonly DateTime _end;
private readonly TimeSpan _delta;
- private DaylightTime()
- {
- }
-
public DaylightTime(DateTime start, DateTime end, TimeSpan delta)
{
_start = start;
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/EastAsianLunisolarCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/EastAsianLunisolarCalendar.cs
index 358f4df18..a29f8a1ee 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/EastAsianLunisolarCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/EastAsianLunisolarCalendar.cs
@@ -162,7 +162,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"time",
- String.Format(CultureInfo.InvariantCulture, SR.ArgumentOutOfRange_CalendarRange,
+ string.Format(CultureInfo.InvariantCulture, SR.ArgumentOutOfRange_CalendarRange,
MinSupportedDateTime, MaxSupportedDateTime));
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/GregorianCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/GregorianCalendar.cs
index 16023209e..6b08ee540 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/GregorianCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/GregorianCalendar.cs
@@ -20,8 +20,14 @@ namespace System.Globalization
public const int ADEra = 1;
//
- // This is the max Gregorian year can be represented by DateTime class. The limitation
- // is derived from DateTime class.
+ // This is the min Gregorian year can be represented by the DateTime class.
+ // The limitation is derived from the DateTime class.
+ //
+ internal const int MinYear = 1;
+
+ //
+ // This is the max Gregorian year can be represented by the DateTime class.
+ // The limitation is derived from the DateTime class.
//
internal const int MaxYear = 9999;
@@ -206,7 +212,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(months),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
-120000,
@@ -317,7 +323,7 @@ namespace System.Globalization
}
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -364,7 +370,7 @@ namespace System.Globalization
}
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -451,7 +457,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range, 1, MaxYear));
}
@@ -473,7 +479,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range, 1, MaxYear));
}
@@ -501,7 +507,7 @@ namespace System.Globalization
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range, 1, MaxYear));
}
@@ -520,25 +526,11 @@ namespace System.Globalization
throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue);
}
- internal override Boolean TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result)
+ internal override bool TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result)
{
if (era == CurrentEra || era == ADEra)
{
- try
- {
- result = new DateTime(year, month, day, hour, minute, second, millisecond);
- return true;
- }
- catch (ArgumentOutOfRangeException)
- {
- result = DateTime.Now;
- return false;
- }
- catch (ArgumentException)
- {
- result = DateTime.Now;
- return false;
- }
+ return DateTime.TryCreate(year, month, day, hour, minute, second, millisecond, out result);
}
result = DateTime.MinValue;
return false;
@@ -565,7 +557,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"year",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
99,
@@ -588,7 +580,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range, 1, MaxYear));
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/GregorianCalendarHelper.cs b/src/System.Private.CoreLib/shared/System/Globalization/GregorianCalendarHelper.cs
index 2842bd3a1..34206b380 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/GregorianCalendarHelper.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/GregorianCalendarHelper.cs
@@ -19,9 +19,9 @@ namespace System.Globalization
// be affected by the DateTime.MinValue;
internal int maxEraYear; // Max year value in this era. (== the year length of the era + 1)
- internal String eraName; // The era name
- internal String abbrevEraName; // Abbreviated Era Name
- internal String englishEraName; // English era name
+ internal string eraName; // The era name
+ internal string abbrevEraName; // Abbreviated Era Name
+ internal string englishEraName; // English era name
internal EraInfo(int era, int startYear, int startMonth, int startDay, int yearOffset, int minEraYear, int maxEraYear)
{
@@ -33,7 +33,7 @@ namespace System.Globalization
}
internal EraInfo(int era, int startYear, int startMonth, int startDay, int yearOffset, int minEraYear, int maxEraYear,
- String eraName, String abbrevEraName, String englishEraName)
+ string eraName, string abbrevEraName, string englishEraName)
{
this.era = era;
this.yearOffset = yearOffset;
@@ -47,8 +47,8 @@ namespace System.Globalization
}
// This calendar recognizes two era values:
- // 0 CurrentEra (AD)
- // 1 BeforeCurrentEra (BC)
+ // 0 CurrentEra (AD)
+ // 1 BeforeCurrentEra (BC)
internal class GregorianCalendarHelper
{
// 1 tick = 100ns = 10E-7 second
@@ -87,7 +87,7 @@ namespace System.Globalization
//
// This is the max Gregorian year can be represented by DateTime class. The limitation
// is derived from DateTime class.
- //
+ //
internal int MaxYear
{
get
@@ -123,22 +123,19 @@ namespace System.Globalization
m_minYear = m_EraInfo[0].minEraYear; ;
}
- /*=================================GetGregorianYear==========================
- **Action: Get the Gregorian year value for the specified year in an era.
- **Returns: The Gregorian year value.
- **Arguments:
- ** year the year value in Japanese calendar
- ** era the Japanese emperor era value.
- **Exceptions:
- ** ArgumentOutOfRangeException if year value is invalid or era value is invalid.
- ============================================================================*/
-
- internal int GetGregorianYear(int year, int era)
+ // EraInfo.yearOffset: The offset to Gregorian year when the era starts. Gregorian Year = Era Year + yearOffset
+ // Era Year = Gregorian Year - yearOffset
+ // EraInfo.minEraYear: Min year value in this era. Generally, this value is 1, but this may be affected by the DateTime.MinValue;
+ // EraInfo.maxEraYear: Max year value in this era. (== the year length of the era + 1)
+ private int GetYearOffset(int year, int era, bool throwOnError)
{
if (year < 0)
{
- throw new ArgumentOutOfRangeException(nameof(year),
- SR.ArgumentOutOfRange_NeedNonNegNum);
+ if (throwOnError)
+ {
+ throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ return -1;
}
if (era == Calendar.CurrentEra)
@@ -150,48 +147,78 @@ namespace System.Globalization
{
if (era == m_EraInfo[i].era)
{
- if (year < m_EraInfo[i].minEraYear || year > m_EraInfo[i].maxEraYear)
+ if (year >= m_EraInfo[i].minEraYear)
+ {
+ if (year <= m_EraInfo[i].maxEraYear)
+ {
+ return m_EraInfo[i].yearOffset;
+ }
+ else if (!AppContextSwitches.EnforceJapaneseEraYearRanges)
+ {
+ // If we got the year number exceeding the era max year number, this still possible be valid as the date can be created before
+ // introducing new eras after the era we are checking. we'll loop on the eras after the era we have and ensure the year
+ // can exist in one of these eras. otherwise, we'll throw.
+ // Note, we always return the offset associated with the requested era.
+ //
+ // Here is some example:
+ // if we are getting the era number 4 (Heisei) and getting the year number 32. if the era 4 has year range from 1 to 31
+ // then year 32 exceeded the range of era 4 and we'll try to find out if the years difference (32 - 31 = 1) would lay in
+ // the subsequent eras (e.g era 5 and up)
+
+ int remainingYears = year - m_EraInfo[i].maxEraYear;
+
+ for (int j = i - 1; j >= 0; j--)
+ {
+ if (remainingYears <= m_EraInfo[j].maxEraYear)
+ {
+ return m_EraInfo[i].yearOffset;
+ }
+ remainingYears -= m_EraInfo[j].maxEraYear;
+ }
+ }
+ }
+
+ if (throwOnError)
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
m_EraInfo[i].minEraYear,
m_EraInfo[i].maxEraYear));
}
- return (m_EraInfo[i].yearOffset + year);
+
+ break; // no need to iterate more on eras.
}
}
- throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue);
- }
- internal bool IsValidYear(int year, int era)
- {
- if (year < 0)
+ if (throwOnError)
{
- return false;
+ throw new ArgumentOutOfRangeException(nameof(era), SR.ArgumentOutOfRange_InvalidEraValue);
}
+ return -1;
+ }
- if (era == Calendar.CurrentEra)
- {
- era = m_Cal.CurrentEraValue;
- }
+ /*=================================GetGregorianYear==========================
+ **Action: Get the Gregorian year value for the specified year in an era.
+ **Returns: The Gregorian year value.
+ **Arguments:
+ ** year the year value in Japanese calendar
+ ** era the Japanese emperor era value.
+ **Exceptions:
+ ** ArgumentOutOfRangeException if year value is invalid or era value is invalid.
+ ============================================================================*/
- for (int i = 0; i < m_EraInfo.Length; i++)
- {
- if (era == m_EraInfo[i].era)
- {
- if (year < m_EraInfo[i].minEraYear || year > m_EraInfo[i].maxEraYear)
- {
- return false;
- }
- return true;
- }
- }
- return false;
+ internal int GetGregorianYear(int year, int era)
+ {
+ return GetYearOffset(year, era, throwOnError: true) + year;
}
+ internal bool IsValidYear(int year, int era)
+ {
+ return GetYearOffset(year, era, throwOnError: false) >= 0;
+ }
// Returns a given date part of this DateTime. This method is used
// to compute the year, day-of-year, month, or day part.
@@ -297,7 +324,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(millisecond),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
0,
@@ -315,7 +342,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"time",
- String.Format(
+ string.Format(
CultureInfo.InvariantCulture,
SR.ArgumentOutOfRange_CalendarRange,
m_Cal.MinSupportedDateTime,
@@ -346,7 +373,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(months),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
-120000,
@@ -544,7 +571,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(day),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -583,7 +610,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(month),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -638,7 +665,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range, m_minYear, m_maxYear));
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/HebrewCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/HebrewCalendar.cs
index 533d3831b..06807811e 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/HebrewCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/HebrewCalendar.cs
@@ -100,7 +100,7 @@ namespace System.Globalization
A 99 means the year is not supported for translation.
for convenience the table was defined for 750 year,
but only 640 years are supported. (from 1583 to 2239)
- the years before 1582 (starting of Georgian calander)
+ the years before 1582 (starting of Georgian calendar)
and after 2239, are filled with 99.
Greogrian January 1st falls usually in Tevet (4th month). Tevet has always 29 days.
@@ -344,14 +344,14 @@ namespace System.Globalization
** We use a table for the Hebrew calendar calculation, so the year supported is limited.
============================================================================*/
- private static void CheckHebrewYearValue(int y, int era, String varName)
+ private static void CheckHebrewYearValue(int y, int era, string varName)
{
CheckEraRange(era);
if (y > MaxHebrewYear || y < MinHebrewYear)
{
throw new ArgumentOutOfRangeException(
varName,
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
MinHebrewYear,
@@ -376,7 +376,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(month),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -402,7 +402,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(day),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -425,7 +425,7 @@ namespace System.Globalization
throw new ArgumentOutOfRangeException(
"time",
// Print out the date in Gregorian using InvariantCulture since the DateTime is based on GreograinCalendar.
- String.Format(
+ string.Format(
CultureInfo.InvariantCulture,
SR.ArgumentOutOfRange_CalendarRange,
calendarMinValue,
@@ -708,7 +708,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(months),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_AddValue));
}
@@ -1104,7 +1104,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
MinHebrewYear,
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/HebrewNumber.cs b/src/System.Private.CoreLib/shared/System/Globalization/HebrewNumber.cs
index 1e8fff2bc..4413cd9fa 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/HebrewNumber.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/HebrewNumber.cs
@@ -87,7 +87,7 @@ namespace System.Globalization
//
////////////////////////////////////////////////////////////////////////////
- internal static String ToString(int Number)
+ internal static string ToString(int Number)
{
char cTens = '\x0';
char cUnits; // tens and units chars
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Win32.cs b/src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Win32.cs
index 365942cce..7333f87d5 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Win32.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.Win32.cs
@@ -10,7 +10,7 @@ namespace System.Globalization
{
private int GetHijriDateAdjustment()
{
- if (_hijriAdvance == Int32.MinValue)
+ if (_hijriAdvance == int.MinValue)
{
// Never been set before. Use the system value from registry.
_hijriAdvance = GetAdvanceHijriDate();
@@ -18,8 +18,8 @@ namespace System.Globalization
return (_hijriAdvance);
}
- private const String InternationalRegKey = "Control Panel\\International";
- private const String HijriAdvanceRegKeyEntry = "AddHijriDate";
+ private const string InternationalRegKey = "Control Panel\\International";
+ private const string HijriAdvanceRegKeyEntry = "AddHijriDate";
/*=================================GetAdvanceHijriDate==========================
**Action: Gets the AddHijriDate value from the registry.
@@ -45,7 +45,7 @@ namespace System.Globalization
try
{
// Open in read-only mode.
- key = RegistryKey.GetBaseKey(RegistryKey.HKEY_CURRENT_USER).OpenSubKey(InternationalRegKey, false);
+ key = RegistryKey.OpenBaseKey(RegistryHive.CurrentUser).OpenSubKey(InternationalRegKey, false);
}
//If this fails for any reason, we'll just return 0.
catch (ObjectDisposedException) { return 0; }
@@ -55,13 +55,13 @@ namespace System.Globalization
{
try
{
- Object value = key.InternalGetValue(HijriAdvanceRegKeyEntry, null, false, false);
+ object value = key.InternalGetValue(HijriAdvanceRegKeyEntry, null, false, false);
if (value == null)
{
return (0);
}
- String str = value.ToString();
- if (String.Compare(str, 0, HijriAdvanceRegKeyEntry, 0, HijriAdvanceRegKeyEntry.Length, StringComparison.OrdinalIgnoreCase) == 0)
+ string str = value.ToString();
+ if (string.Compare(str, 0, HijriAdvanceRegKeyEntry, 0, HijriAdvanceRegKeyEntry.Length, StringComparison.OrdinalIgnoreCase) == 0)
{
if (str.Length == HijriAdvanceRegKeyEntry.Length)
hijriAdvance = -1;
@@ -69,7 +69,7 @@ namespace System.Globalization
{
try
{
- int advance = Int32.Parse(str.AsSpan().Slice(HijriAdvanceRegKeyEntry.Length), provider:CultureInfo.InvariantCulture);
+ int advance = int.Parse(str.AsSpan(HijriAdvanceRegKeyEntry.Length), provider:CultureInfo.InvariantCulture);
if ((advance >= MinAdvancedHijri) && (advance <= MaxAdvancedHijri))
{
hijriAdvance = advance;
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.cs
index 675584462..3eaf3d253 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/HijriCalendar.cs
@@ -55,7 +55,7 @@ namespace System.Globalization
internal static readonly int[] HijriMonthDays = { 0, 30, 59, 89, 118, 148, 177, 207, 236, 266, 295, 325, 355 };
- private int _hijriAdvance = Int32.MinValue;
+ private int _hijriAdvance = int.MinValue;
// DateTime.MaxValue = Hijri calendar (year:9666, month: 4, day: 3).
internal const int MaxCalendarYear = 9666;
@@ -176,7 +176,7 @@ namespace System.Globalization
{
get
{
- if (_hijriAdvance == Int32.MinValue)
+ if (_hijriAdvance == int.MinValue)
{
// Never been set before. Use the system value from registry.
_hijriAdvance = GetHijriDateAdjustment();
@@ -191,7 +191,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"HijriAdjustment",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Bounds_Lower_Upper,
MinAdvancedHijri,
@@ -209,7 +209,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"time",
- String.Format(
+ string.Format(
CultureInfo.InvariantCulture,
SR.ArgumentOutOfRange_CalendarRange,
calendarMinValue,
@@ -232,7 +232,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -249,7 +249,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(month),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -387,7 +387,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(months),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
-120000,
@@ -541,7 +541,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(day),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Day,
daysInMonth,
@@ -591,7 +591,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(day),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Day,
daysInMonth,
@@ -631,7 +631,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(value),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
99,
@@ -659,7 +659,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/ISOWeek.cs b/src/System.Private.CoreLib/shared/System/Globalization/ISOWeek.cs
new file mode 100644
index 000000000..3b3ba15ec
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Globalization/ISOWeek.cs
@@ -0,0 +1,162 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using static System.Globalization.GregorianCalendar;
+
+namespace System.Globalization
+{
+ public static class ISOWeek
+ {
+ private const int WeeksInLongYear = 53;
+ private const int WeeksInShortYear = 52;
+
+ private const int MinWeek = 1;
+ private const int MaxWeek = WeeksInLongYear;
+
+ public static int GetWeekOfYear(DateTime date)
+ {
+ int week = GetWeekNumber(date);
+
+ if (week < MinWeek)
+ {
+ // If the week number obtained equals 0, it means that the
+ // given date belongs to the preceding (week-based) year.
+ return GetWeeksInYear(date.Year - 1);
+ }
+
+ if (week > GetWeeksInYear(date.Year))
+ {
+ // If a week number of 53 is obtained, one must check that
+ // the date is not actually in week 1 of the following year.
+ return MinWeek;
+ }
+
+ return week;
+ }
+
+ public static int GetYear(DateTime date)
+ {
+ int week = GetWeekNumber(date);
+
+ if (week < MinWeek)
+ {
+ // If the week number obtained equals 0, it means that the
+ // given date belongs to the preceding (week-based) year.
+ return date.Year - 1;
+ }
+
+ if (week > GetWeeksInYear(date.Year))
+ {
+ // If a week number of 53 is obtained, one must check that
+ // the date is not actually in week 1 of the following year.
+ return date.Year + 1;
+ }
+
+ return date.Year;
+ }
+
+ // The year parameter represents an ISO week-numbering year (also called ISO year informally).
+ // Each week's year is the Gregorian year in which the Thursday falls.
+ // The first week of the year, hence, always contains 4 January.
+ // ISO week year numbering therefore slightly deviates from the Gregorian for some days close to 1 January.
+ public static DateTime GetYearStart(int year)
+ {
+ return ToDateTime(year, MinWeek, DayOfWeek.Monday);
+ }
+
+ // The year parameter represents an ISO week-numbering year (also called ISO year informally).
+ // Each week's year is the Gregorian year in which the Thursday falls.
+ // The first week of the year, hence, always contains 4 January.
+ // ISO week year numbering therefore slightly deviates from the Gregorian for some days close to 1 January.
+ public static DateTime GetYearEnd(int year)
+ {
+ return ToDateTime(year, GetWeeksInYear(year), DayOfWeek.Sunday);
+ }
+
+ // From https://en.wikipedia.org/wiki/ISO_week_date#Weeks_per_year:
+ //
+ // The long years, with 53 weeks in them, can be described by any of the following equivalent definitions:
+ //
+ // - Any year starting on Thursday and any leap year starting on Wednesday.
+ // - Any year ending on Thursday and any leap year ending on Friday.
+ // - Years in which 1 January and 31 December (in common years) or either (in leap years) are Thursdays.
+ //
+ // All other week-numbering years are short years and have 52 weeks.
+ public static int GetWeeksInYear(int year)
+ {
+ if (year < MinYear || year > MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_Year);
+ }
+
+ int P(int y) => (y + (y / 4) - (y / 100) + (y / 400)) % 7;
+
+ if (P(year) == 4 || P(year - 1) == 3)
+ {
+ return WeeksInLongYear;
+ }
+
+ return WeeksInShortYear;
+ }
+
+ // From https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year,_week_number_and_weekday:
+ //
+ // This method requires that one know the weekday of 4 January of the year in question.
+ // Add 3 to the number of this weekday, giving a correction to be used for dates within this year.
+ //
+ // Multiply the week number by 7, then add the weekday. From this sum subtract the correction for the year.
+ // The result is the ordinal date, which can be converted into a calendar date.
+ //
+ // If the ordinal date thus obtained is zero or negative, the date belongs to the previous calendar year.
+ // If greater than the number of days in the year, to the following year.
+ public static DateTime ToDateTime(int year, int week, DayOfWeek dayOfWeek)
+ {
+ if (year < MinYear || year > MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(nameof(year), SR.ArgumentOutOfRange_Year);
+ }
+
+ if (week < MinWeek || week > MaxWeek)
+ {
+ throw new ArgumentOutOfRangeException(nameof(week), SR.ArgumentOutOfRange_Week_ISO);
+ }
+
+ // We allow 7 for convenience in cases where a user already has a valid ISO
+ // day of week value for Sunday. This means that both 0 and 7 will map to Sunday.
+ // The GetWeekday method will normalize this into the 1-7 range required by ISO.
+ if ((int)dayOfWeek < 0 || (int)dayOfWeek > 7)
+ {
+ throw new ArgumentOutOfRangeException(nameof(dayOfWeek), SR.ArgumentOutOfRange_DayOfWeek);
+ }
+
+ var jan4 = new DateTime(year, month: 1, day: 4);
+
+ int correction = GetWeekday(jan4.DayOfWeek) + 3;
+
+ int ordinal = (week * 7) + GetWeekday(dayOfWeek) - correction;
+
+ return new DateTime(year, month: 1, day: 1).AddDays(ordinal - 1);
+ }
+
+ // From https://en.wikipedia.org/wiki/ISO_week_date#Calculating_the_week_number_of_a_given_date:
+ //
+ // Using ISO weekday numbers (running from 1 for Monday to 7 for Sunday),
+ // subtract the weekday from the ordinal date, then add 10. Divide the result by 7.
+ // Ignore the remainder; the quotient equals the week number.
+ //
+ // If the week number thus obtained equals 0, it means that the given date belongs to the preceding (week-based) year.
+ // If a week number of 53 is obtained, one must check that the date is not actually in week 1 of the following year.
+ private static int GetWeekNumber(DateTime date)
+ {
+ return (date.DayOfYear - GetWeekday(date.DayOfWeek) + 10) / 7;
+ }
+
+ // Day of week in ISO is represented by an integer from 1 through 7, beginning with Monday and ending with Sunday.
+ // This matches the underlying values of the DayOfWeek enum, except for Sunday, which needs to be converted.
+ private static int GetWeekday(DayOfWeek dayOfWeek)
+ {
+ return dayOfWeek == DayOfWeek.Sunday ? 7 : (int) dayOfWeek;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Unix.cs b/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Unix.cs
index 5320936a7..20f753e98 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Unix.cs
@@ -8,9 +8,10 @@ namespace System.Globalization
{
sealed partial class IdnMapping
{
- private unsafe string GetAsciiCore(char* unicode, int count)
+ private unsafe string GetAsciiCore(string unicodeString, char* unicode, int count)
{
Debug.Assert(!GlobalizationMode.Invariant);
+ Debug.Assert(unicodeString != null && unicodeString.Length >= count);
uint flags = Flags;
CheckInvalidIdnCharacters(unicode, count, flags, nameof(unicode));
@@ -26,7 +27,7 @@ namespace System.Globalization
actualLength = Interop.Globalization.ToAscii(flags, unicode, count, outputStack, estimatedLength);
if (actualLength > 0 && actualLength <= estimatedLength)
{
- return new string(outputStack, 0, actualLength);
+ return GetStringForOutput(unicodeString, unicode, count, outputStack, actualLength);
}
}
else
@@ -46,13 +47,14 @@ namespace System.Globalization
{
throw new ArgumentException(SR.Argument_IdnIllegalName, nameof(unicode));
}
- return new string(pOutputHeap, 0, actualLength);
+ return GetStringForOutput(unicodeString, unicode, count, pOutputHeap, actualLength);
}
}
- private unsafe string GetUnicodeCore(char* ascii, int count)
+ private unsafe string GetUnicodeCore(string asciiString, char* ascii, int count)
{
Debug.Assert(!GlobalizationMode.Invariant);
+ Debug.Assert(asciiString != null && asciiString.Length >= count);
uint flags = Flags;
CheckInvalidIdnCharacters(ascii, count, flags, nameof(ascii));
@@ -61,21 +63,22 @@ namespace System.Globalization
if (count < StackAllocThreshold)
{
char* output = stackalloc char[count];
- return GetUnicodeCore(ascii, count, flags, output, count, reattempt: true);
+ return GetUnicodeCore(asciiString, ascii, count, flags, output, count, reattempt: true);
}
else
{
char[] output = new char[count];
fixed (char* pOutput = &output[0])
{
- return GetUnicodeCore(ascii, count, flags, pOutput, count, reattempt: true);
+ return GetUnicodeCore(asciiString, ascii, count, flags, pOutput, count, reattempt: true);
}
}
}
- private unsafe string GetUnicodeCore(char* ascii, int count, uint flags, char* output, int outputLength, bool reattempt)
+ private unsafe string GetUnicodeCore(string asciiString, char* ascii, int count, uint flags, char* output, int outputLength, bool reattempt)
{
Debug.Assert(!GlobalizationMode.Invariant);
+ Debug.Assert(asciiString != null && asciiString.Length >= count);
int realLen = Interop.Globalization.ToUnicode(flags, ascii, count, output, outputLength);
@@ -85,14 +88,14 @@ namespace System.Globalization
}
else if (realLen <= outputLength)
{
- return new string(output, 0, realLen);
+ return GetStringForOutput(asciiString, ascii, count, output, realLen);
}
else if (reattempt)
{
char[] newOutput = new char[realLen];
fixed (char* pNewOutput = newOutput)
{
- return GetUnicodeCore(ascii, count, flags, pNewOutput, realLen, reattempt: false);
+ return GetUnicodeCore(asciiString, ascii, count, flags, pNewOutput, realLen, reattempt: false);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Windows.cs b/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Windows.cs
index 35da7343e..9d491dfbb 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.Windows.cs
@@ -9,9 +9,10 @@ namespace System.Globalization
{
public sealed partial class IdnMapping
{
- private unsafe string GetAsciiCore(char* unicode, int count)
+ private unsafe string GetAsciiCore(string unicodeString, char* unicode, int count)
{
Debug.Assert(!GlobalizationMode.Invariant);
+ Debug.Assert(unicodeString != null && unicodeString.Length >= count);
uint flags = Flags;
@@ -27,21 +28,22 @@ namespace System.Globalization
if (length < StackAllocThreshold)
{
char* output = stackalloc char[length];
- return GetAsciiCore(unicode, count, flags, output, length);
+ return GetAsciiCore(unicodeString, unicode, count, flags, output, length);
}
else
{
char[] output = new char[length];
fixed (char* pOutput = &output[0])
{
- return GetAsciiCore(unicode, count, flags, pOutput, length);
+ return GetAsciiCore(unicodeString, unicode, count, flags, pOutput, length);
}
}
}
- private unsafe string GetAsciiCore(char* unicode, int count, uint flags, char* output, int outputLength)
+ private unsafe string GetAsciiCore(string unicodeString, char* unicode, int count, uint flags, char* output, int outputLength)
{
Debug.Assert(!GlobalizationMode.Invariant);
+ Debug.Assert(unicodeString != null && unicodeString.Length >= count);
int length = Interop.Normaliz.IdnToAscii(flags, unicode, count, output, outputLength);
if (length == 0)
@@ -49,12 +51,13 @@ namespace System.Globalization
ThrowForZeroLength(unicode: true);
}
Debug.Assert(length == outputLength);
- return new string(output, 0, length);
+ return GetStringForOutput(unicodeString, unicode, count, output, length);
}
- private unsafe string GetUnicodeCore(char* ascii, int count)
+ private unsafe string GetUnicodeCore(string asciiString, char* ascii, int count)
{
Debug.Assert(!GlobalizationMode.Invariant);
+ Debug.Assert(asciiString != null && asciiString.Length >= count);
uint flags = Flags;
@@ -70,21 +73,22 @@ namespace System.Globalization
if (length < StackAllocThreshold)
{
char* output = stackalloc char[length];
- return GetUnicodeCore(ascii, count, flags, output, length);
+ return GetUnicodeCore(asciiString, ascii, count, flags, output, length);
}
else
{
char[] output = new char[length];
fixed (char* pOutput = &output[0])
{
- return GetUnicodeCore(ascii, count, flags, pOutput, length);
+ return GetUnicodeCore(asciiString, ascii, count, flags, pOutput, length);
}
}
}
- private unsafe string GetUnicodeCore(char* ascii, int count, uint flags, char* output, int outputLength)
+ private unsafe string GetUnicodeCore(string asciiString, char* ascii, int count, uint flags, char* output, int outputLength)
{
Debug.Assert(!GlobalizationMode.Invariant);
+ Debug.Assert(asciiString != null && asciiString.Length >= count);
int length = Interop.Normaliz.IdnToUnicode(flags, ascii, count, output, outputLength);
if (length == 0)
@@ -92,7 +96,7 @@ namespace System.Globalization
ThrowForZeroLength(unicode: false);
}
Debug.Assert(length == outputLength);
- return new string(output, 0, length);
+ return GetStringForOutput(asciiString, ascii, count, output, length);
}
// -----------------------------
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.cs b/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.cs
index 176e5feed..164e46dc8 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/IdnMapping.cs
@@ -25,6 +25,7 @@
// RFC 3492 - Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)
using System.Diagnostics;
+using System.Runtime.CompilerServices;
using System.Text;
namespace System.Globalization
@@ -93,7 +94,7 @@ namespace System.Globalization
{
fixed (char* pUnicode = unicode)
{
- return GetAsciiCore(pUnicode + index, count);
+ return GetAsciiCore(unicode, pUnicode + index, count);
}
}
}
@@ -137,7 +138,7 @@ namespace System.Globalization
{
fixed (char* pAscii = ascii)
{
- return GetUnicodeCore(pAscii + index, count);
+ return GetUnicodeCore(ascii, pAscii + index, count);
}
}
}
@@ -156,6 +157,14 @@ namespace System.Globalization
return (_allowUnassigned ? 100 : 200) + (_useStd3AsciiRules ? 1000 : 2000);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static unsafe string GetStringForOutput(string originalString, char* input, int inputLength, char* output, int outputLength)
+ {
+ return originalString.Length == inputLength && new ReadOnlySpan<char>(input, inputLength).SequenceEqual(new ReadOnlySpan<char>(output, outputLength)) ?
+ originalString :
+ new string(output, 0, outputLength);
+ }
+
//
// Invariant implementation
//
@@ -272,7 +281,7 @@ namespace System.Globalization
// Need to validate entire string length, 1 shorter if last char wasn't a dot
if (unicode.Length > c_defaultNameLimit - (IsDot(unicode[unicode.Length - 1]) ? 0 : 1))
- throw new ArgumentException(SR.Format(SR.Argument_IdnBadNameSize,
+ throw new ArgumentException(SR.Format(SR.Argument_IdnBadNameSize,
c_defaultNameLimit - (IsDot(unicode[unicode.Length - 1]) ? 0 : 1)), nameof(unicode));
// If last char wasn't a dot we need to check for trailing -
@@ -352,7 +361,7 @@ namespace System.Globalization
// Check last char
int iTest = iNextDot - 1;
- if (Char.IsLowSurrogate(unicode, iTest))
+ if (char.IsLowSurrogate(unicode, iTest))
{
iTest--;
}
@@ -371,7 +380,7 @@ namespace System.Globalization
for (basicCount = iAfterLastDot; basicCount < iNextDot; basicCount++)
{
// Can't be lonely surrogate because it would've thrown in normalization
- Debug.Assert(Char.IsLowSurrogate(unicode, basicCount) == false, "[IdnMapping.punycode_encode]Unexpected low surrogate");
+ Debug.Assert(char.IsLowSurrogate(unicode, basicCount) == false, "[IdnMapping.punycode_encode]Unexpected low surrogate");
// Double check our bidi rules
BidiCategory testBidi = CharUnicodeInfo.GetBidiCategory(unicode, basicCount);
@@ -397,7 +406,7 @@ namespace System.Globalization
numProcessed++;
}
// If its a surrogate, skip the next since our bidi category tester doesn't handle it.
- else if (Char.IsSurrogatePair(unicode, basicCount))
+ else if (char.IsSurrogatePair(unicode, basicCount))
basicCount++;
}
@@ -443,7 +452,7 @@ namespace System.Globalization
j < iNextDot;
j += IsSupplementary(test) ? 2 : 1)
{
- test = Char.ConvertToUtf32(unicode, j);
+ test = char.ConvertToUtf32(unicode, j);
if (test >= n && test < m) m = test;
}
@@ -456,7 +465,7 @@ namespace System.Globalization
for (j = iAfterLastDot; j < iNextDot; j+= IsSupplementary(test) ? 2 : 1)
{
// Make sure we're aware of surrogates
- test = Char.ConvertToUtf32(unicode, j);
+ test = char.ConvertToUtf32(unicode, j);
// Adjust for character position (only the chars in our string already, some
// haven't been processed.
@@ -512,7 +521,7 @@ namespace System.Globalization
// Throw if we're too long
if (output.Length > c_defaultNameLimit - (IsDot(unicode[unicode.Length-1]) ? 0 : 1))
- throw new ArgumentException(SR.Format(SR.Argument_IdnBadNameSize,
+ throw new ArgumentException(SR.Format(SR.Argument_IdnBadNameSize,
c_defaultNameLimit - (IsDot(unicode[unicode.Length-1]) ? 0 : 1)), nameof(unicode));
// Return our output string
return output.ToString();
@@ -594,7 +603,7 @@ namespace System.Globalization
// Throw if we're too long
if (ascii.Length > c_defaultNameLimit - (IsDot(ascii[ascii.Length-1]) ? 0 : 1))
- throw new ArgumentException(SR.Format(SR.Argument_IdnBadNameSize,
+ throw new ArgumentException(SR.Format(SR.Argument_IdnBadNameSize,
c_defaultNameLimit - (IsDot(ascii[ascii.Length-1]) ? 0 : 1)), nameof(ascii));
// output stringbuilder
@@ -628,11 +637,11 @@ namespace System.Globalization
throw new ArgumentException(SR.Argument_IdnBadLabelSize, nameof(ascii));
// See if this section's ASCII or ACE
- if (ascii.Length < c_strAcePrefix.Length + iAfterLastDot ||
- !ascii.Substring(iAfterLastDot,c_strAcePrefix.Length).Equals(c_strAcePrefix, StringComparison.OrdinalIgnoreCase))
+ if (ascii.Length < c_strAcePrefix.Length + iAfterLastDot ||
+ string.Compare(ascii, iAfterLastDot, c_strAcePrefix, 0, c_strAcePrefix.Length, StringComparison.OrdinalIgnoreCase) != 0)
{
// Its ASCII, copy it
- output.Append(ascii.Substring(iAfterLastDot, iNextDot - iAfterLastDot));
+ output.Append(ascii, iAfterLastDot, iNextDot - iAfterLastDot);
}
else
{
@@ -706,7 +715,7 @@ namespace System.Globalization
i += (int)(digit * w);
int t = k <= bias ? c_tmin : k >= bias + c_tmax ? c_tmax : k - bias;
- if (digit < t)
+ if (digit < t)
break;
Debug.Assert(c_punycodeBase != t, "[IdnMapping.punycode_decode]Expected t != c_punycodeBase (36)");
if (w > c_maxint / (c_punycodeBase - t))
@@ -731,7 +740,7 @@ namespace System.Globalization
// insert n at position i of the output: Really tricky if we have surrogates
int iUseInsertLocation;
- String strTemp = Char.ConvertFromUtf32(n);
+ string strTemp = char.ConvertFromUtf32(n);
// If we have supplimentary characters
if (numSurrogatePairs > 0)
@@ -743,7 +752,7 @@ namespace System.Globalization
// If its a surrogate, we have to go one more
if (iUseInsertLocation >= output.Length)
throw new ArgumentException(SR.Argument_IdnBadPunycode, nameof(ascii));
- if (Char.IsSurrogate(output[iUseInsertLocation]))
+ if (char.IsSurrogate(output[iUseInsertLocation]))
iUseInsertLocation++;
}
}
@@ -768,7 +777,7 @@ namespace System.Globalization
bool bRightToLeft = false;
// Check for RTL. If right-to-left, then 1st & last chars must be RTL
- BidiCategory eBidi = CharUnicodeInfo.GetBidiCategory(output.ToString(), iOutputAfterLastDot);
+ BidiCategory eBidi = CharUnicodeInfo.GetBidiCategory(output, iOutputAfterLastDot);
if (eBidi == BidiCategory.RightToLeft || eBidi == BidiCategory.RightToLeftArabic)
{
// It has to be right to left.
@@ -779,11 +788,11 @@ namespace System.Globalization
for (int iTest = iOutputAfterLastDot; iTest < output.Length; iTest++)
{
// This might happen if we run into a pair
- if (Char.IsLowSurrogate(output.ToString(), iTest))
+ if (char.IsLowSurrogate(output[iTest]))
continue;
// Check to see if its LTR
- eBidi = CharUnicodeInfo.GetBidiCategory(output.ToString(), iTest);
+ eBidi = CharUnicodeInfo.GetBidiCategory(output, iTest);
if ((bRightToLeft && eBidi == BidiCategory.LeftToRight) ||
(!bRightToLeft && (eBidi == BidiCategory.RightToLeft || eBidi == BidiCategory.RightToLeftArabic)))
throw new ArgumentException(SR.Argument_IdnBadBidi, nameof(ascii));
@@ -888,6 +897,5 @@ namespace System.Globalization
// 0-25 map to a-z or A-Z
return (char)(d + 'a');
}
-
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/InternalGlobalizationHelper.cs b/src/System.Private.CoreLib/shared/System/Globalization/InternalGlobalizationHelper.cs
index 60abcecf6..6dc2b1951 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/InternalGlobalizationHelper.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/InternalGlobalizationHelper.cs
@@ -25,8 +25,8 @@ namespace System.Globalization
internal const long TicksPerMillisecond = 10000;
internal const long TicksPerTenthSecond = TicksPerMillisecond * 100;
internal const long TicksPerSecond = TicksPerMillisecond * 1000; // 10,000,000
- internal const long MaxSeconds = Int64.MaxValue / TicksPerSecond;
- internal const long MinSeconds = Int64.MinValue / TicksPerSecond;
+ internal const long MaxSeconds = long.MaxValue / TicksPerSecond;
+ internal const long MinSeconds = long.MinValue / TicksPerSecond;
private const int DaysPerYear = 365;
private const int DaysPer4Years = DaysPerYear * 4 + 1; // 1461
private const int DaysPer100Years = DaysPer4Years * 25 - 1; // 36524
@@ -37,12 +37,12 @@ namespace System.Globalization
private const long TicksPerDay = TicksPerHour * 24;
internal const long MaxTicks = DaysTo10000 * TicksPerDay - 1;
internal const long MinTicks = 0;
- internal const long MaxMilliSeconds = Int64.MaxValue / TicksPerMillisecond;
- internal const long MinMilliSeconds = Int64.MinValue / TicksPerMillisecond;
+ internal const long MaxMilliSeconds = long.MaxValue / TicksPerMillisecond;
+ internal const long MinMilliSeconds = long.MinValue / TicksPerMillisecond;
internal const int StringBuilderDefaultCapacity = 16;
- internal const Int64 MaxOffset = TimeSpan.TicksPerHour * 14;
- internal const Int64 MinOffset = -MaxOffset;
+ internal const long MaxOffset = TimeSpan.TicksPerHour * 14;
+ internal const long MinOffset = -MaxOffset;
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Win32.cs b/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Win32.cs
index 1d0180b00..2356afe35 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Win32.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.Win32.cs
@@ -37,13 +37,13 @@ namespace System.Globalization
try
{
// Need to access registry
- RegistryKey key = RegistryKey.GetBaseKey(RegistryKey.HKEY_LOCAL_MACHINE).OpenSubKey(c_japaneseErasHive, false);
+ RegistryKey key = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine).OpenSubKey(c_japaneseErasHive, false);
// Abort if we didn't find anything
if (key == null) return null;
// Look up the values in our reg key
- String[] valueNames = key.GetValueNames();
+ string[] valueNames = key.GetValueNames();
if (valueNames != null && valueNames.Length > 0)
{
registryEraRanges = new EraInfo[valueNames.Length];
@@ -143,7 +143,7 @@ namespace System.Globalization
// . is a delimiter, but the value of . doesn't matter.
// '_' marks the space between the japanese era name, japanese abbreviated era name
// english name, and abbreviated english names.
- private static EraInfo GetEraFromValue(String value, String data)
+ private static EraInfo GetEraFromValue(string value, string data)
{
// Need inputs
if (value == null || data == null) return null;
@@ -160,9 +160,9 @@ namespace System.Globalization
int day;
ReadOnlySpan<char> valueSpan = value.AsSpan();
- if (!Int32.TryParse(valueSpan.Slice(0, 4), NumberStyles.None, NumberFormatInfo.InvariantInfo, out year) ||
- !Int32.TryParse(valueSpan.Slice(5, 2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out month) ||
- !Int32.TryParse(valueSpan.Slice(8, 2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out day))
+ if (!int.TryParse(valueSpan.Slice(0, 4), NumberStyles.None, NumberFormatInfo.InvariantInfo, out year) ||
+ !int.TryParse(valueSpan.Slice(5, 2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out month) ||
+ !int.TryParse(valueSpan.Slice(8, 2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out day))
{
// Couldn't convert integer, fail
return null;
@@ -172,7 +172,7 @@ namespace System.Globalization
// Get Strings
//
// Needs to be a certain length e_a_E_A at least (7 chars, exactly 4 groups)
- String[] names = data.Split('_');
+ string[] names = data.Split('_');
// Should have exactly 4 parts
// 0 - Era Name
@@ -199,7 +199,7 @@ namespace System.Globalization
// PAL Layer ends here
- private static string[] s_japaneseErasEnglishNames = new String[] { "M", "T", "S", "H" };
+ private static string[] s_japaneseErasEnglishNames = new string[] { "M", "T", "S", "H" };
private static string GetJapaneseEnglishEraName(int era)
{
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.WinRT.cs b/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.WinRT.cs
index 6a9df9720..818cb5b42 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.WinRT.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.WinRT.cs
@@ -46,7 +46,7 @@ namespace System.Globalization
// PAL Layer ends here
- private static string[] JapaneseErasEnglishNames = new String[] { "M", "T", "S", "H" };
+ private static string[] JapaneseErasEnglishNames = new string[] { "M", "T", "S", "H" };
private static string GetJapaneseEnglishEraName(int era)
{
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.cs
index 50195d7f1..fdf2dc670 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/JapaneseCalendar.cs
@@ -303,7 +303,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -325,10 +325,10 @@ namespace System.Globalization
// Return the various era strings
// Note: The arrays are backwards of the eras
//
- internal static String[] EraNames()
+ internal static string[] EraNames()
{
EraInfo[] eras = GetEraInfo();
- String[] eraNames = new String[eras.Length];
+ string[] eraNames = new string[eras.Length];
for (int i = 0; i < eras.Length; i++)
{
@@ -339,10 +339,10 @@ namespace System.Globalization
return eraNames;
}
- internal static String[] AbbrevEraNames()
+ internal static string[] AbbrevEraNames()
{
EraInfo[] eras = GetEraInfo();
- String[] erasAbbrev = new String[eras.Length];
+ string[] erasAbbrev = new string[eras.Length];
for (int i = 0; i < eras.Length; i++)
{
@@ -353,10 +353,10 @@ namespace System.Globalization
return erasAbbrev;
}
- internal static String[] EnglishEraNames()
+ internal static string[] EnglishEraNames()
{
EraInfo[] eras = GetEraInfo();
- String[] erasEnglish = new String[eras.Length];
+ string[] erasEnglish = new string[eras.Length];
for (int i = 0; i < eras.Length; i++)
{
@@ -392,7 +392,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"year",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
99,
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/JapaneseLunisolarCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/JapaneseLunisolarCalendar.cs
index e8a2dcd63..64aa79d87 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/JapaneseLunisolarCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/JapaneseLunisolarCalendar.cs
@@ -62,101 +62,103 @@ namespace System.Globalization
}
}
+ // Data for years 1960-2049 matches output of Calendrical Calculations [1] and published calendar tables [2].
+ // [1] Reingold, Edward M, and Nachum Dershowitz. Calendrical Calculations: The Ultimate Edition. Cambridge [etc.: Cambridge University Press, 2018. Print.
+ // [2] Nishizawa, Yūsō. Rekijitsu Taikan: Meiji Kaireki 1873-Nen-2100-Nen Shinkyūreki, Kanshi Kyūsei Rokuyō Taishō. Tōkyō: Shin Jinbutsu Ōraisha, 1994. Print.
private static readonly int[,] s_yinfo =
{
- /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
- 1960 */
- { 6 , 1 , 28 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1961 */{ 0 , 2 , 15 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1962 */{ 0 , 2 , 5 , 19808 },/* 29 30 29 29 30 30 29 30 29 30 30 29 0 354
-1963 */{ 4 , 1 , 25 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1964 */{ 0 , 2 , 13 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1965 */{ 0 , 2 , 2 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
-1966 */{ 3 , 1 , 22 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
-1967 */{ 0 , 2 , 9 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
-1968 */{ 7 , 1 , 30 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1969 */{ 0 , 2 , 17 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1970 */{ 0 , 2 , 6 , 39632 },/* 30 29 29 30 30 29 30 29 30 30 29 30 0 355
-1971 */{ 5 , 1 , 27 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1972 */{ 0 , 2 , 15 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1973 */{ 0 , 2 , 3 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
-1974 */{ 4 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1975 */{ 0 , 2 , 11 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-1976 */{ 8 , 1 , 31 , 54600 },/* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
-1977 */{ 0 , 2 , 18 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
-1978 */{ 0 , 2 , 7 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355
-1979 */{ 6 , 1 , 28 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
-1980 */{ 0 , 2 , 16 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1981 */{ 0 , 2 , 5 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1982 */{ 4 , 1 , 25 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1983 */{ 0 , 2 , 13 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1984 */{ 10 , 2 , 2 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1985 */{ 0 , 2 , 20 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
-1986 */{ 0 , 2 , 9 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
-1987 */{ 6 , 1 , 29 , 46504 },/* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
-1988 */{ 0 , 2 , 18 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1989 */{ 0 , 2 , 6 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1990 */{ 5 , 1 , 27 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1991 */{ 0 , 2 , 15 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1992 */{ 0 , 2 , 4 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1993 */{ 3 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1994 */{ 0 , 2 , 10 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
-1995 */{ 8 , 1 , 31 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
-1996 */{ 0 , 2 , 19 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
-1997 */{ 0 , 2 , 8 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1998 */{ 5 , 1 , 28 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
-1999 */{ 0 , 2 , 16 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-2000 */{ 0 , 2 , 5 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-2001 */{ 4 , 1 , 24 , 58536 },/* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
-2002 */{ 0 , 2 , 12 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-2003 */{ 0 , 2 , 1 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-2004 */{ 2 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-2005 */{ 0 , 2 , 9 , 22208 },/* 29 30 29 30 29 30 30 29 30 30 29 29 0 354
-2006 */{ 7 , 1 , 29 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
-2007 */{ 0 , 2 , 18 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-2008 */{ 0 , 2 , 7 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
-2009 */{ 5 , 1 , 26 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
-2010 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-2011 */{ 0 , 2 , 3 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-2012 */{ 3 , 1 , 23 , 47696 },/* 30 29 30 30 30 29 30 29 29 30 29 30 29 384
-2013 */{ 0 , 2 , 10 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-2014 */{ 9 , 1 , 31 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-2015 */{ 0 , 2 , 19 , 19360 },/* 29 30 29 29 30 29 30 30 30 29 30 29 0 354
-2016 */{ 0 , 2 , 8 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
-2017 */{ 5 , 1 , 28 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-2018 */{ 0 , 2 , 16 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-2019 */{ 0 , 2 , 5 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-2020 */{ 4 , 1 , 25 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-2021 */{ 0 , 2 , 12 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-2022 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-2023 */{ 2 , 1 , 22 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-2024 */{ 0 , 2 , 10 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-2025 */{ 6 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-2026 */{ 0 , 2 , 17 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-2027 */{ 0 , 2 , 7 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
-2028 */{ 5 , 1 , 27 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
-2029 */{ 0 , 2 , 13 , 55600 },/* 30 30 29 30 30 29 29 30 29 29 30 30 0 355
-2030 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-2031 */{ 3 , 1 , 23 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
-2032 */{ 0 , 2 , 11 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-2033 */{ 11 , 1 , 31 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-2034 */{ 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-2035 */{ 0 , 2 , 8 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-2036 */{ 6 , 1 , 28 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-2037 */{ 0 , 2 , 15 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-2038 */{ 0 , 2 , 4 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
-2039 */{ 5 , 1 , 24 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
-2040 */{ 0 , 2 , 12 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355
-2041 */{ 0 , 2 , 1 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-2042 */{ 2 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
-2043 */{ 0 , 2 , 10 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-2044 */{ 7 , 1 , 30 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-2045 */{ 0 , 2 , 17 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-2046 */{ 0 , 2 , 6 , 45648 },/* 30 29 30 30 29 29 30 29 29 30 29 30 0 354
-2047 */{ 5 , 1 , 26 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-2048 */{ 0 , 2 , 14 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
-2049 */{ 0 , 2 , 2 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
- */ };
+/*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
+1960 */ { 06, 01, 28, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1961 */ { 00, 02, 15, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1962 */ { 00, 02, 05, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+1963 */ { 04, 01, 25, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1964 */ { 00, 02, 13, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1965 */ { 00, 02, 02, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 354
+1966 */ { 03, 01, 22, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
+1967 */ { 00, 02, 09, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
+1968 */ { 07, 01, 30, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1969 */ { 00, 02, 17, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1970 */ { 00, 02, 06, 0b1001101011010000 }, /* 30 29 29 30 30 29 30 29 30 30 29 30 355
+1971 */ { 05, 01, 27, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1972 */ { 00, 02, 15, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1973 */ { 00, 02, 03, 0b1010010011100000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 354
+1974 */ { 04, 01, 23, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1975 */ { 00, 02, 11, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+1976 */ { 08, 01, 31, 0b1101010101001000 }, /* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
+1977 */ { 00, 02, 18, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
+1978 */ { 00, 02, 07, 0b1101011010100000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 355
+1979 */ { 06, 01, 28, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1980 */ { 00, 02, 16, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1981 */ { 00, 02, 05, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1982 */ { 04, 01, 25, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1983 */ { 00, 02, 13, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1984 */ { 10, 02, 02, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1985 */ { 00, 02, 20, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
+1986 */ { 00, 02, 09, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
+1987 */ { 06, 01, 29, 0b1011010110101000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
+1988 */ { 00, 02, 18, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1989 */ { 00, 02, 06, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1990 */ { 05, 01, 27, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1991 */ { 00, 02, 15, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1992 */ { 00, 02, 04, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1993 */ { 03, 01, 23, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1994 */ { 00, 02, 10, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
+1995 */ { 08, 01, 31, 0b0110110101001000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
+1996 */ { 00, 02, 19, 0b0101101011010000 }, /* 29 30 29 30 30 29 30 29 30 30 29 30 355
+1997 */ { 00, 02, 08, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1998 */ { 05, 01, 28, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1999 */ { 00, 02, 16, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+2000 */ { 00, 02, 05, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+2001 */ { 04, 01, 24, 0b1110010010101000 }, /* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
+2002 */ { 00, 02, 12, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+2003 */ { 00, 02, 01, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
+2004 */ { 02, 01, 22, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+2005 */ { 00, 02, 09, 0b0101011011000000 }, /* 29 30 29 30 29 30 30 29 30 30 29 29 354
+2006 */ { 07, 01, 29, 0b1010101011011000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+2007 */ { 00, 02, 18, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+2008 */ { 00, 02, 07, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
+2009 */ { 05, 01, 26, 0b1100100101011000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+2010 */ { 00, 02, 14, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+2011 */ { 00, 02, 03, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+2012 */ { 03, 01, 23, 0b1011101001010000 }, /* 30 29 30 30 30 29 30 29 29 30 29 30 29 384
+2013 */ { 00, 02, 10, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+2014 */ { 09, 01, 31, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2015 */ { 00, 02, 19, 0b0100101110100000 }, /* 29 30 29 29 30 29 30 30 30 29 30 29 354
+2016 */ { 00, 02, 08, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
+2017 */ { 05, 01, 28, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+2018 */ { 00, 02, 16, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+2019 */ { 00, 02, 05, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+2020 */ { 04, 01, 25, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+2021 */ { 00, 02, 12, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+2022 */ { 00, 02, 01, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+2023 */ { 02, 01, 22, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2024 */ { 00, 02, 10, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+2025 */ { 06, 01, 29, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+2026 */ { 00, 02, 17, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+2027 */ { 00, 02, 07, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 354
+2028 */ { 05, 01, 27, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
+2029 */ { 00, 02, 13, 0b1101100100110000 }, /* 30 30 29 30 30 29 29 30 29 29 30 30 355
+2030 */ { 00, 02, 03, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+2031 */ { 03, 01, 23, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+2032 */ { 00, 02, 11, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+2033 */ { 11, 01, 31, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+2034 */ { 00, 02, 19, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+2035 */ { 00, 02, 08, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+2036 */ { 06, 01, 28, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+2037 */ { 00, 02, 15, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+2038 */ { 00, 02, 04, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
+2039 */ { 05, 01, 24, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
+2040 */ { 00, 02, 12, 0b1011011010100000 }, /* 30 29 30 30 29 30 30 29 30 29 30 29 355
+2041 */ { 00, 02, 01, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+2042 */ { 02, 01, 22, 0b0100101011011000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+2043 */ { 00, 02, 10, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+2044 */ { 07, 01, 30, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+2045 */ { 00, 02, 17, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+2046 */ { 00, 02, 06, 0b1011001001010000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 354
+2047 */ { 05, 01, 26, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+2048 */ { 00, 02, 14, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
+2049 */ { 00, 02, 02, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
+ */ };
internal override int MinCalendarYear
{
@@ -204,7 +206,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"year",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
MIN_LUNISOLAR_YEAR,
@@ -261,14 +263,12 @@ namespace System.Globalization
return newEras;
}
-
// Construct an instance of JapaneseLunisolar calendar.
public JapaneseLunisolarCalendar()
{
helper = new GregorianCalendarHelper(this, TrimEras(JapaneseCalendar.GetEraInfo()));
}
-
public override int GetEra(DateTime time)
{
return (helper.GetEra(time));
@@ -290,7 +290,6 @@ namespace System.Globalization
}
}
-
public override int[] Eras
{
get
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/JulianCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/JulianCalendar.cs
index 82e4d589d..a1ffbeb48 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/JulianCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/JulianCalendar.cs
@@ -98,7 +98,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -142,7 +142,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(day),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -214,7 +214,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(months),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
-120000,
@@ -372,7 +372,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(millisecond),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
0,
@@ -404,7 +404,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"year",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
99,
@@ -427,7 +427,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Bounds_Lower_Upper,
1,
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/KoreanCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/KoreanCalendar.cs
index 9168b664e..3f265f69e 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/KoreanCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/KoreanCalendar.cs
@@ -237,7 +237,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"year",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
99,
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/KoreanLunisolarCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/KoreanLunisolarCalendar.cs
index 8cdade866..63636f5e3 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/KoreanLunisolarCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/KoreanLunisolarCalendar.cs
@@ -7,10 +7,10 @@ namespace System.Globalization
{
/*
** Calendar support range:
- ** Calendar Minimum Maximum
- ** ========== ========== ==========
- ** Gregorian 918/02/14 2051/02/10
- ** KoreanLunisolar 918/01/01 2050/13/29
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 918/02/19 2051/02/10
+ ** KoreanLunisolar 918/01/01 2050/13/29
*/
public class KoreanLunisolarCalendar : EastAsianLunisolarCalendar
@@ -26,7 +26,7 @@ namespace System.Globalization
internal const int MIN_GREGORIAN_YEAR = 918;
internal const int MIN_GREGORIAN_MONTH = 2;
- internal const int MIN_GREGORIAN_DAY = 14;
+ internal const int MIN_GREGORIAN_DAY = 19;
internal const int MAX_GREGORIAN_YEAR = 2051;
internal const int MAX_GREGORIAN_MONTH = 2;
@@ -43,8 +43,6 @@ namespace System.Globalization
}
}
-
-
public override DateTime MaxSupportedDateTime
{
get
@@ -63,1145 +61,1146 @@ namespace System.Globalization
}
}
+// Data for years 1391-2050 matches that available from
+// Korea Astronomy and Space Science Institute (KASI)
+// https://astro.kasi.re.kr:444/life/pageView/5
private static readonly int[,] s_yinfo =
{
- /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
- 918 */
- { 0 , 2 , 14 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
-919 */{ 0 , 2 , 4 , 17872 },/* 29 30 29 29 29 30 29 30 30 30 29 30 0 354
-920 */{ 6 , 1 , 24 , 41688 },/* 30 29 30 29 29 29 30 29 30 30 29 30 30 384
-921 */{ 0 , 2 , 11 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354
-922 */{ 0 , 1 , 31 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-923 */{ 4 , 1 , 20 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-924 */{ 0 , 2 , 8 , 27936 },/* 29 30 30 29 30 30 29 30 29 29 30 29 0 354
-925 */{ 12 , 1 , 27 , 44384 },/* 30 29 30 29 30 30 29 30 29 30 30 29 29 384
-926 */{ 0 , 2 , 15 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-927 */{ 0 , 2 , 5 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
-928 */{ 8 , 1 , 26 , 17848 },/* 29 30 29 29 29 30 29 30 30 29 30 30 30 384
-929 */{ 0 , 2 , 13 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354
-930 */{ 0 , 2 , 2 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-931 */{ 5 , 1 , 22 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 29 383
-932 */{ 0 , 2 , 9 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
-933 */{ 0 , 1 , 29 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-934 */{ 1 , 1 , 18 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-935 */{ 0 , 2 , 6 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-936 */{ 11 , 1 , 27 , 21344 },/* 29 30 29 30 29 29 30 30 29 30 30 29 29 383
-937 */{ 0 , 2 , 13 , 51904 },/* 30 30 29 29 30 29 30 29 30 30 29 29 0 354
-938 */{ 0 , 2 , 2 , 58720 },/* 30 30 30 29 29 30 29 30 29 30 30 29 0 355
-939 */{ 7 , 1 , 23 , 53928 },/* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
-940 */{ 0 , 2 , 11 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
-941 */{ 0 , 1 , 30 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
-942 */{ 3 , 1 , 20 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-943 */{ 0 , 2 , 8 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-944 */{ 12 , 1 , 28 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 29 384
-945 */{ 0 , 2 , 15 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
-946 */{ 0 , 2 , 5 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
-947 */{ 7 , 1 , 25 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-948 */{ 0 , 2 , 13 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-949 */{ 0 , 2 , 1 , 45664 },/* 30 29 30 30 29 29 30 29 29 30 30 29 0 354
-950 */{ 5 , 1 , 21 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-951 */{ 0 , 2 , 9 , 45936 },/* 30 29 30 30 29 30 29 30 29 30 29 0 0 325
-952 */{ 0 , 12 , 31 , 43728 },/* 30 29 30 29 30 29 30 29 30 30 29 30 29 384
-953 */{ 1 , 1 , 18 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
-954 */{ 0 , 2 , 6 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-955 */{ 9 , 1 , 27 , 19128 },/* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
-956 */{ 0 , 2 , 15 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-957 */{ 0 , 2 , 3 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-958 */{ 7 , 1 , 23 , 43672 },/* 30 29 30 29 30 29 30 29 30 29 29 30 30 384
-959 */{ 0 , 2 , 11 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-960 */{ 0 , 1 , 31 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-961 */{ 3 , 1 , 20 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
-962 */{ 0 , 2 , 8 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-963 */{ 12 , 1 , 28 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
-964 */{ 0 , 2 , 16 , 41840 },/* 30 29 30 29 29 29 30 30 29 30 30 30 0 355
-965 */{ 0 , 2 , 5 , 20848 },/* 29 30 29 30 29 29 29 30 29 30 30 30 0 354
-966 */{ 8 , 1 , 25 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
-967 */{ 0 , 2 , 12 , 54448 },/* 30 30 29 30 29 30 29 29 30 29 30 30 0 355
-968 */{ 0 , 2 , 2 , 23184 },/* 29 30 29 30 30 29 30 29 30 29 29 30 0 354
-969 */{ 5 , 1 , 21 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
-970 */{ 0 , 2 , 9 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-971 */{ 0 , 1 , 30 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354
-972 */{ 2 , 1 , 19 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
-973 */{ 0 , 2 , 6 , 41696 },/* 30 29 30 29 29 29 30 29 30 30 30 29 0 354
-974 */{ 10 , 1 , 26 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-975 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-976 */{ 0 , 2 , 3 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-977 */{ 7 , 1 , 22 , 55952 },/* 30 30 29 30 30 29 30 29 30 29 29 30 29 384
-978 */{ 0 , 2 , 10 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
-979 */{ 0 , 1 , 31 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-980 */{ 3 , 1 , 21 , 10968 },/* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
-981 */{ 0 , 2 , 8 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-982 */{ 12 , 1 , 28 , 37592 },/* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
-983 */{ 0 , 2 , 16 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
-984 */{ 0 , 2 , 5 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-985 */{ 9 , 1 , 24 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-986 */{ 0 , 2 , 12 , 44192 },/* 30 29 30 29 30 30 29 29 30 29 30 29 0 354
-987 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-988 */{ 5 , 1 , 22 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-989 */{ 0 , 2 , 9 , 19376 },/* 29 30 29 29 30 29 30 30 30 29 30 30 0 355
-990 */{ 0 , 1 , 30 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 0 354
-991 */{ 2 , 1 , 19 , 37560 },/* 30 29 29 30 29 29 30 29 30 29 30 30 30 384
-992 */{ 0 , 2 , 7 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-993 */{ 10 , 1 , 26 , 26968 },/* 29 30 30 29 30 29 29 30 29 30 29 30 30 384
-994 */{ 0 , 2 , 14 , 22864 },/* 29 30 29 30 30 29 29 30 29 30 29 30 0 354
-995 */{ 0 , 2 , 3 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-996 */{ 7 , 1 , 23 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
-997 */{ 0 , 2 , 10 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-998 */{ 0 , 1 , 31 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-999 */{ 3 , 1 , 20 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1000 */{ 0 , 2 , 8 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354
-1001 */{ 12 , 1 , 28 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 29 383
-1002 */{ 0 , 2 , 15 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
-1003 */{ 0 , 2 , 4 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1004 */{ 9 , 1 , 25 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1005 */{ 0 , 2 , 12 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1006 */{ 0 , 2 , 1 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-1007 */{ 5 , 1 , 22 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1008 */{ 0 , 2 , 10 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
-1009 */{ 0 , 1 , 29 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1010 */{ 2 , 1 , 18 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1011 */{ 0 , 2 , 6 , 45664 },/* 30 29 30 30 29 29 30 29 29 30 30 29 0 354
-1012 */{ 10 , 1 , 26 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1013 */{ 0 , 2 , 13 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-1014 */{ 0 , 2 , 3 , 13728 },/* 29 29 30 30 29 30 29 30 30 29 30 29 0 354
-1015 */{ 6 , 1 , 23 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
-1016 */{ 0 , 2 , 11 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1017 */{ 0 , 1 , 31 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1018 */{ 4 , 1 , 20 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1019 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1020 */{ 12 , 1 , 28 , 43608 },/* 30 29 30 29 30 29 30 29 29 30 29 30 30 384
-1021 */{ 0 , 2 , 15 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1022 */{ 0 , 2 , 4 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-1023 */{ 9 , 1 , 25 , 11688 },/* 29 29 30 29 30 30 29 30 30 29 30 29 30 384
-1024 */{ 0 , 2 , 13 , 11088 },/* 29 29 30 29 30 29 30 30 29 30 29 30 0 354
-1025 */{ 0 , 2 , 1 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355
-1026 */{ 5 , 1 , 22 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
-1027 */{ 0 , 2 , 9 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 0 355
-1028 */{ 0 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1029 */{ 2 , 1 , 18 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1030 */{ 0 , 2 , 5 , 55952 },/* 30 30 29 30 30 29 30 29 30 29 29 30 0 355
-1031 */{ 10 , 1 , 26 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
-1032 */{ 0 , 2 , 14 , 26320 },/* 29 30 30 29 29 30 30 29 30 30 29 30 0 355
-1033 */{ 0 , 2 , 3 , 9952 },/* 29 29 30 29 29 30 30 29 30 30 30 29 0 354
-1034 */{ 6 , 1 , 23 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
-1035 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1036 */{ 0 , 1 , 31 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-1037 */{ 4 , 1 , 19 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1038 */{ 0 , 2 , 7 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1039 */{ 12 , 1 , 27 , 54928 },/* 30 30 29 30 29 30 30 29 30 29 29 30 29 384
-1040 */{ 0 , 2 , 15 , 46464 },/* 30 29 30 30 29 30 29 30 30 29 29 29 0 354
-1041 */{ 0 , 2 , 3 , 54960 },/* 30 30 29 30 29 30 30 29 30 29 30 30 0 356
-1042 */{ 9 , 1 , 25 , 9944 },/* 29 29 30 29 29 30 30 29 30 30 29 30 30 384
-1043 */{ 0 , 2 , 13 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1044 */{ 0 , 2 , 2 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
-1045 */{ 5 , 1 , 21 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1046 */{ 0 , 2 , 9 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1047 */{ 0 , 1 , 29 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-1048 */{ 1 , 1 , 18 , 46424 },/* 30 29 30 30 29 30 29 30 29 30 29 30 30 385
-1049 */{ 0 , 2 , 6 , 11600 },/* 29 29 30 29 30 30 29 30 29 30 29 30 0 354
-1050 */{ 11 , 1 , 26 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-1051 */{ 0 , 2 , 14 , 19376 },/* 29 30 29 29 30 29 30 30 30 29 30 30 0 355
-1052 */{ 0 , 2 , 4 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 0 354
-1053 */{ 7 , 1 , 23 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1054 */{ 0 , 2 , 11 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1055 */{ 0 , 1 , 31 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
-1056 */{ 3 , 1 , 20 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1057 */{ 0 , 2 , 7 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1058 */{ 12 , 1 , 27 , 43864 },/* 30 29 30 29 30 29 30 30 29 30 29 30 30 385
-1059 */{ 0 , 2 , 16 , 10064 },/* 29 29 30 29 29 30 30 30 29 30 29 30 0 354
-1060 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-1061 */{ 8 , 1 , 24 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1062 */{ 0 , 2 , 12 , 42336 },/* 30 29 30 29 29 30 29 30 29 30 30 29 0 354
-1063 */{ 0 , 2 , 1 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-1064 */{ 5 , 1 , 21 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-1065 */{ 0 , 2 , 8 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1066 */{ 0 , 1 , 29 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1067 */{ 1 , 1 , 18 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
-1068 */{ 0 , 2 , 6 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-1069 */{ 11 , 1 , 26 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1070 */{ 0 , 2 , 14 , 18896 },/* 29 30 29 29 30 29 29 30 30 30 29 30 0 354
-1071 */{ 0 , 2 , 3 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1072 */{ 7 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1073 */{ 0 , 2 , 10 , 43616 },/* 30 29 30 29 30 29 30 29 29 30 30 29 0 354
-1074 */{ 0 , 1 , 30 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1075 */{ 4 , 1 , 20 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1076 */{ 0 , 2 , 8 , 13728 },/* 29 29 30 30 29 30 29 30 30 29 30 29 0 354
-1077 */{ 0 , 1 , 27 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
-1078 */{ 1 , 1 , 17 , 19352 },/* 29 30 29 29 30 29 30 30 30 29 29 30 30 384
-1079 */{ 0 , 2 , 5 , 17840 },/* 29 30 29 29 29 30 29 30 30 29 30 30 0 354
-1080 */{ 9 , 1 , 25 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-1081 */{ 0 , 2 , 12 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1082 */{ 0 , 2 , 1 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
-1083 */{ 6 , 1 , 21 , 46408 },/* 30 29 30 30 29 30 29 30 29 30 29 29 30 384
-1084 */{ 0 , 2 , 9 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 0 355
-1085 */{ 0 , 1 , 29 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354
-1086 */{ 2 , 1 , 18 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
-1087 */{ 0 , 2 , 6 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
-1088 */{ 12 , 1 , 27 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
-1089 */{ 0 , 2 , 13 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 0 355
-1090 */{ 0 , 2 , 3 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1091 */{ 8 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1092 */{ 0 , 2 , 10 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-1093 */{ 0 , 1 , 30 , 23360 },/* 29 30 29 30 30 29 30 30 29 30 29 29 0 354
-1094 */{ 4 , 1 , 19 , 43880 },/* 30 29 30 29 30 29 30 30 29 30 30 29 30 385
-1095 */{ 0 , 2 , 8 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354
-1096 */{ 0 , 1 , 28 , 58896 },/* 30 30 30 29 29 30 30 29 29 29 29 30 0 354
-1097 */{ 2 , 1 , 16 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
-1098 */{ 0 , 2 , 4 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-1099 */{ 9 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1100 */{ 0 , 2 , 12 , 21664 },/* 29 30 29 30 29 30 29 29 30 29 30 29 0 353
-1101 */{ 0 , 1 , 31 , 54864 },/* 30 30 29 30 29 30 30 29 29 30 29 30 0 355
-1102 */{ 6 , 1 , 21 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1103 */{ 0 , 2 , 9 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
-1104 */{ 0 , 1 , 30 , 9936 },/* 29 29 30 29 29 30 30 29 30 30 29 30 0 354
-1105 */{ 2 , 1 , 18 , 37608 },/* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
-1106 */{ 0 , 2 , 6 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
-1107 */{ 10 , 1 , 26 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1108 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1109 */{ 0 , 2 , 2 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-1110 */{ 8 , 1 , 22 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1111 */{ 0 , 2 , 10 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-1112 */{ 0 , 1 , 31 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
-1113 */{ 4 , 1 , 20 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
-1114 */{ 0 , 2 , 8 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354
-1115 */{ 0 , 1 , 28 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1116 */{ 1 , 1 , 17 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1117 */{ 0 , 2 , 4 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
-1118 */{ 9 , 1 , 24 , 29352 },/* 29 30 30 30 29 29 30 29 30 29 30 29 30 384
-1119 */{ 0 , 2 , 12 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1120 */{ 0 , 2 , 1 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1121 */{ 5 , 1 , 21 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1122 */{ 0 , 2 , 9 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-1123 */{ 0 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1124 */{ 3 , 1 , 19 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
-1125 */{ 0 , 2 , 5 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-1126 */{ 11 , 1 , 25 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-1127 */{ 0 , 2 , 13 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1128 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1129 */{ 8 , 1 , 22 , 39824 },/* 30 29 29 30 30 29 30 30 30 29 29 30 29 384
-1130 */{ 0 , 2 , 10 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-1131 */{ 0 , 1 , 31 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1132 */{ 4 , 1 , 20 , 42216 },/* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
-1133 */{ 0 , 2 , 7 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1134 */{ 0 , 1 , 27 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-1135 */{ 2 , 1 , 16 , 55592 },/* 30 30 29 30 30 29 29 30 29 29 30 29 30 384
-1136 */{ 0 , 2 , 4 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
-1137 */{ 10 , 1 , 23 , 54952 },/* 30 30 29 30 29 30 30 29 30 29 30 29 30 385
-1138 */{ 0 , 2 , 12 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354
-1139 */{ 0 , 2 , 1 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
-1140 */{ 6 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
-1141 */{ 0 , 2 , 9 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1142 */{ 0 , 1 , 29 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1143 */{ 4 , 1 , 18 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1144 */{ 0 , 2 , 6 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
-1145 */{ 11 , 1 , 25 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-1146 */{ 0 , 2 , 13 , 27456 },/* 29 30 30 29 30 29 30 30 29 30 29 29 0 354
-1147 */{ 0 , 2 , 2 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1148 */{ 8 , 1 , 23 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
-1149 */{ 0 , 2 , 10 , 39280 },/* 30 29 29 30 30 29 29 30 29 30 30 30 0 355
-1150 */{ 0 , 1 , 31 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1151 */{ 4 , 1 , 20 , 25784 },/* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
-1152 */{ 0 , 2 , 8 , 21680 },/* 29 30 29 30 29 30 29 29 30 29 30 30 0 354
-1153 */{ 12 , 1 , 27 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1154 */{ 0 , 2 , 14 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-1155 */{ 0 , 2 , 4 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354
-1156 */{ 10 , 1 , 24 , 43880 },/* 30 29 30 29 30 29 30 30 29 30 30 29 30 385
-1157 */{ 0 , 2 , 12 , 9952 },/* 29 29 30 29 29 30 30 29 30 30 30 29 0 354
-1158 */{ 0 , 2 , 1 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1159 */{ 6 , 1 , 21 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
-1160 */{ 0 , 2 , 9 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-1161 */{ 0 , 1 , 28 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1162 */{ 2 , 1 , 17 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1163 */{ 0 , 2 , 5 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1164 */{ 11 , 1 , 26 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1165 */{ 0 , 2 , 13 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
-1166 */{ 0 , 2 , 3 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1167 */{ 7 , 1 , 23 , 37608 },/* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
-1168 */{ 0 , 2 , 11 , 37488 },/* 30 29 29 30 29 29 30 29 29 30 30 30 0 354
-1169 */{ 0 , 1 , 30 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1170 */{ 5 , 1 , 19 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1171 */{ 0 , 2 , 7 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-1172 */{ 0 , 1 , 27 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1173 */{ 1 , 1 , 16 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1174 */{ 0 , 2 , 4 , 19888 },/* 29 30 29 29 30 30 29 30 30 29 30 30 0 355
-1175 */{ 9 , 1 , 25 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 29 383
-1176 */{ 0 , 2 , 12 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1177 */{ 0 , 2 , 1 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1178 */{ 6 , 1 , 21 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1179 */{ 0 , 2 , 9 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
-1180 */{ 0 , 1 , 29 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1181 */{ 3 , 1 , 17 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1182 */{ 0 , 2 , 5 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1183 */{ 11 , 1 , 26 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1184 */{ 0 , 2 , 14 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1185 */{ 0 , 2 , 2 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1186 */{ 7 , 1 , 23 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
-1187 */{ 0 , 2 , 10 , 53392 },/* 30 30 29 30 29 29 30 29 29 30 30 0 0 325
-1188 */{ 0 , 1 , 1 , 29848 },/* 29 30 30 30 29 30 29 29 30 29 29 30 30 384
-1189 */{ 5 , 1 , 19 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1190 */{ 0 , 2 , 7 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1191 */{ 0 , 1 , 27 , 39760 },/* 30 29 29 30 30 29 30 30 29 30 29 30 0 355
-1192 */{ 2 , 1 , 17 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1193 */{ 0 , 2 , 4 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1194 */{ 10 , 1 , 24 , 42216 },/* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
-1195 */{ 0 , 2 , 12 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1196 */{ 0 , 2 , 1 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-1197 */{ 6 , 1 , 20 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
-1198 */{ 0 , 2 , 8 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
-1199 */{ 0 , 1 , 28 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355
-1200 */{ 2 , 1 , 18 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
-1201 */{ 0 , 2 , 5 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
-1202 */{ 12 , 1 , 26 , 18904 },/* 29 30 29 29 30 29 29 30 30 30 29 30 30 384
-1203 */{ 0 , 2 , 14 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1204 */{ 0 , 2 , 3 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1205 */{ 8 , 1 , 22 , 43608 },/* 30 29 30 29 30 29 30 29 29 30 29 30 30 384
-1206 */{ 0 , 2 , 10 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
-1207 */{ 0 , 1 , 30 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
-1208 */{ 4 , 1 , 19 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 29 384
-1209 */{ 0 , 2 , 6 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1210 */{ 0 , 1 , 27 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1211 */{ 2 , 1 , 17 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1212 */{ 0 , 2 , 5 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1213 */{ 9 , 1 , 24 , 25784 },/* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
-1214 */{ 0 , 2 , 12 , 21680 },/* 29 30 29 30 29 30 29 29 30 29 30 30 0 354
-1215 */{ 0 , 2 , 1 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
-1216 */{ 7 , 1 , 21 , 27944 },/* 29 30 30 29 30 30 29 30 29 29 30 29 30 384
-1217 */{ 0 , 2 , 8 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354
-1218 */{ 0 , 1 , 28 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1219 */{ 3 , 1 , 18 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
-1220 */{ 0 , 2 , 6 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1221 */{ 12 , 1 , 25 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
-1222 */{ 0 , 2 , 13 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-1223 */{ 0 , 2 , 2 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1224 */{ 8 , 1 , 22 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1225 */{ 0 , 2 , 9 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1226 */{ 0 , 1 , 30 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1227 */{ 5 , 1 , 19 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
-1228 */{ 0 , 2 , 8 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1229 */{ 0 , 1 , 27 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1230 */{ 2 , 1 , 16 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
-1231 */{ 0 , 2 , 4 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1232 */{ 9 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1233 */{ 0 , 2 , 11 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354
-1234 */{ 0 , 1 , 31 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1235 */{ 7 , 1 , 21 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1236 */{ 0 , 2 , 9 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
-1237 */{ 0 , 1 , 28 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
-1238 */{ 4 , 1 , 18 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1239 */{ 0 , 2 , 6 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1240 */{ 12 , 1 , 26 , 43320 },/* 30 29 30 29 30 29 29 30 29 29 30 30 30 384
-1241 */{ 0 , 2 , 13 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354
-1242 */{ 0 , 2 , 2 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1243 */{ 8 , 1 , 22 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1244 */{ 0 , 2 , 10 , 44624 },/* 30 29 30 29 30 30 30 29 29 30 29 30 0 355
-1245 */{ 0 , 1 , 30 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-1246 */{ 4 , 1 , 19 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1247 */{ 0 , 2 , 7 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1248 */{ 0 , 1 , 28 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
-1249 */{ 2 , 1 , 16 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
-1250 */{ 0 , 2 , 3 , 58672 },/* 30 30 30 29 29 30 29 30 29 29 30 30 0 355
-1251 */{ 10 , 1 , 24 , 27800 },/* 29 30 30 29 30 30 29 29 30 29 29 30 30 384
-1252 */{ 0 , 2 , 12 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1253 */{ 0 , 1 , 31 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
-1254 */{ 6 , 1 , 21 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1255 */{ 0 , 2 , 9 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1256 */{ 0 , 1 , 29 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
-1257 */{ 4 , 1 , 17 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1258 */{ 0 , 2 , 5 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-1259 */{ 11 , 1 , 25 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
-1260 */{ 0 , 2 , 13 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
-1261 */{ 0 , 2 , 1 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355
-1262 */{ 9 , 1 , 22 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
-1263 */{ 0 , 2 , 10 , 21872 },/* 29 30 29 30 29 30 29 30 29 30 30 30 0 355
-1264 */{ 0 , 1 , 31 , 18896 },/* 29 30 29 29 30 29 29 30 30 30 29 30 0 354
-1265 */{ 5 , 1 , 19 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1266 */{ 0 , 2 , 7 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1267 */{ 0 , 1 , 27 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
-1268 */{ 1 , 1 , 16 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-1269 */{ 0 , 2 , 3 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
-1270 */{ 11 , 1 , 23 , 46528 },/* 30 29 30 30 29 30 29 30 30 30 29 29 29 384
-1271 */{ 0 , 2 , 11 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1272 */{ 0 , 2 , 1 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1273 */{ 6 , 1 , 21 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1274 */{ 0 , 2 , 9 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1275 */{ 0 , 1 , 29 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1276 */{ 3 , 1 , 18 , 27224 },/* 29 30 30 29 30 29 30 29 29 30 29 30 30 384
-1277 */{ 0 , 2 , 5 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
-1278 */{ 11 , 1 , 25 , 27432 },/* 29 30 30 29 30 29 30 30 29 29 30 29 30 384
-1279 */{ 0 , 2 , 13 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354
-1280 */{ 0 , 2 , 2 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1281 */{ 8 , 1 , 22 , 10984 },/* 29 29 30 29 30 29 30 29 30 30 30 29 30 384
-1282 */{ 0 , 2 , 10 , 18912 },/* 29 30 29 29 30 29 29 30 30 30 30 29 0 354
-1283 */{ 0 , 1 , 30 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1284 */{ 5 , 1 , 19 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
-1285 */{ 0 , 2 , 6 , 45648 },/* 30 29 30 30 29 29 30 29 29 30 29 30 0 354
-1286 */{ 0 , 1 , 26 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
-1287 */{ 2 , 1 , 15 , 62096 },/* 30 30 30 30 29 29 30 29 30 29 29 30 29 384
-1288 */{ 0 , 2 , 3 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
-1289 */{ 10 , 1 , 23 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
-1290 */{ 0 , 2 , 11 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1291 */{ 0 , 2 , 1 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1292 */{ 6 , 1 , 21 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-1293 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1294 */{ 0 , 1 , 28 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
-1295 */{ 4 , 1 , 17 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-1296 */{ 0 , 2 , 5 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
-1297 */{ 12 , 1 , 24 , 44384 },/* 30 29 30 29 30 30 29 30 29 30 30 29 29 384
-1298 */{ 0 , 2 , 12 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1299 */{ 0 , 2 , 2 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
-1300 */{ 8 , 1 , 23 , 2424 },/* 29 29 29 29 30 29 29 30 29 30 30 30 30 383
-1301 */{ 0 , 2 , 10 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1302 */{ 0 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1303 */{ 5 , 1 , 19 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1304 */{ 0 , 2 , 6 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-1305 */{ 0 , 1 , 26 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1306 */{ 1 , 1 , 15 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
-1307 */{ 0 , 2 , 3 , 42720 },/* 30 29 30 29 29 30 30 29 30 30 30 29 0 355
-1308 */{ 11 , 1 , 24 , 37608 },/* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
-1309 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1310 */{ 0 , 1 , 31 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-1311 */{ 7 , 1 , 20 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1312 */{ 0 , 2 , 8 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1313 */{ 0 , 1 , 27 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1314 */{ 3 , 1 , 17 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1315 */{ 0 , 2 , 5 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1316 */{ 0 , 1 , 25 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
-1317 */{ 1 , 1 , 14 , 37608 },/* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
-1318 */{ 0 , 2 , 2 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
-1319 */{ 8 , 1 , 22 , 42328 },/* 30 29 30 29 29 30 29 30 29 30 29 30 30 384
-1320 */{ 0 , 2 , 10 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1321 */{ 0 , 1 , 29 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354
-1322 */{ 5 , 1 , 18 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1323 */{ 0 , 2 , 6 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-1324 */{ 0 , 1 , 27 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
-1325 */{ 1 , 1 , 15 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
-1326 */{ 0 , 2 , 3 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1327 */{ 9 , 1 , 24 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1328 */{ 0 , 2 , 12 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
-1329 */{ 0 , 1 , 31 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354
-1330 */{ 7 , 1 , 20 , 27288 },/* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
-1331 */{ 0 , 2 , 8 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1332 */{ 0 , 1 , 28 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1333 */{ 3 , 1 , 17 , 19368 },/* 29 30 29 29 30 29 30 30 30 29 30 29 30 384
-1334 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-1335 */{ 12 , 1 , 25 , 42608 },/* 30 29 30 29 29 30 30 29 29 30 30 30 29 384
-1336 */{ 0 , 2 , 13 , 41696 },/* 30 29 30 29 29 29 30 29 30 30 30 29 0 354
-1337 */{ 0 , 2 , 1 , 53600 },/* 30 30 29 30 29 29 29 30 29 30 30 29 0 354
-1338 */{ 8 , 1 , 21 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-1339 */{ 0 , 2 , 9 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1340 */{ 0 , 1 , 29 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
-1341 */{ 5 , 1 , 18 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
-1342 */{ 0 , 2 , 6 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-1343 */{ 0 , 1 , 27 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1344 */{ 2 , 1 , 16 , 41704 },/* 30 29 30 29 29 29 30 29 30 30 30 29 30 384
-1345 */{ 0 , 2 , 3 , 41680 },/* 30 29 30 29 29 29 30 29 30 30 29 30 0 354
-1346 */{ 10 , 1 , 23 , 53592 },/* 30 30 29 30 29 29 29 30 29 30 29 30 30 384
-1347 */{ 0 , 2 , 11 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
-1348 */{ 0 , 1 , 31 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
-1349 */{ 7 , 1 , 19 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 29 384
-1350 */{ 0 , 2 , 7 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
-1351 */{ 0 , 1 , 28 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
-1352 */{ 3 , 1 , 18 , 18904 },/* 29 30 29 29 30 29 29 30 30 30 29 30 30 384
-1353 */{ 0 , 2 , 5 , 17840 },/* 29 30 29 29 29 30 29 30 30 29 30 30 0 354
-1354 */{ 0 , 1 , 25 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354
-1355 */{ 1 , 1 , 14 , 53592 },/* 30 30 29 30 29 29 29 30 29 30 29 30 30 384
-1356 */{ 0 , 2 , 2 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
-1357 */{ 9 , 1 , 21 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-1358 */{ 0 , 2 , 9 , 27424 },/* 29 30 30 29 30 29 30 30 29 29 30 29 0 354
-1359 */{ 0 , 1 , 29 , 44384 },/* 30 29 30 29 30 30 29 30 29 30 30 29 0 355
-1360 */{ 5 , 1 , 19 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-1361 */{ 0 , 2 , 6 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
-1362 */{ 0 , 1 , 27 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354
-1363 */{ 3 , 1 , 16 , 41656 },/* 30 29 30 29 29 29 30 29 30 29 30 30 30 384
-1364 */{ 0 , 2 , 4 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1365 */{ 10 , 1 , 23 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 29 383
-1366 */{ 0 , 2 , 10 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
-1367 */{ 0 , 1 , 31 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1368 */{ 7 , 1 , 20 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
-1369 */{ 0 , 2 , 7 , 42720 },/* 30 29 30 29 29 30 30 29 30 30 30 29 0 355
-1370 */{ 0 , 1 , 28 , 21216 },/* 29 30 29 30 29 29 30 29 30 30 30 29 0 354
-1371 */{ 3 , 1 , 17 , 50544 },/* 30 30 29 29 29 30 29 30 29 30 30 30 29 384
-1372 */{ 0 , 2 , 5 , 42336 },/* 30 29 30 29 29 30 29 30 29 30 30 29 0 354
-1373 */{ 11 , 1 , 24 , 53928 },/* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
-1374 */{ 0 , 2 , 12 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
-1375 */{ 0 , 2 , 1 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1376 */{ 9 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1377 */{ 0 , 2 , 9 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1378 */{ 0 , 1 , 29 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
-1379 */{ 5 , 1 , 19 , 21224 },/* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
-1380 */{ 0 , 2 , 7 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1381 */{ 0 , 1 , 26 , 43216 },/* 30 29 30 29 30 29 29 29 30 30 29 30 0 354
-1382 */{ 2 , 1 , 15 , 53928 },/* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
-1383 */{ 0 , 2 , 3 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354
-1384 */{ 10 , 1 , 23 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1385 */{ 0 , 2 , 10 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-1386 */{ 0 , 1 , 31 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
-1387 */{ 6 , 1 , 20 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
-1388 */{ 0 , 2 , 8 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1389 */{ 0 , 1 , 28 , 20912 },/* 29 30 29 30 29 29 29 30 30 29 30 30 0 354
-1390 */{ 4 , 1 , 17 , 43192 },/* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
-1391 */{ 0 , 2 , 5 , 25904 },/* 29 30 30 29 29 30 29 30 29 29 30 30 0 354
-1392 */{ 12 , 1 , 25 , 27288 },/* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
-1393 */{ 0 , 2 , 12 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1394 */{ 0 , 2 , 1 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1395 */{ 9 , 1 , 22 , 11176 },/* 29 29 30 29 30 29 30 30 30 29 30 29 30 384
-1396 */{ 0 , 2 , 10 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1397 */{ 0 , 1 , 29 , 50032 },/* 30 30 29 29 29 29 30 30 29 30 30 30 0 355
-1398 */{ 5 , 1 , 19 , 20848 },/* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
-1399 */{ 0 , 2 , 6 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-1400 */{ 0 , 1 , 26 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1401 */{ 3 , 1 , 15 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
-1402 */{ 0 , 2 , 2 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
-1403 */{ 11 , 1 , 23 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
-1404 */{ 0 , 2 , 11 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-1405 */{ 0 , 1 , 31 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354
-1406 */{ 7 , 1 , 20 , 41704 },/* 30 29 30 29 29 29 30 29 30 30 30 29 30 384
-1407 */{ 0 , 2 , 8 , 41680 },/* 30 29 30 29 29 29 30 29 30 30 29 30 0 354
-1408 */{ 0 , 1 , 28 , 53584 },/* 30 30 29 30 29 29 29 30 29 30 29 30 0 354
-1409 */{ 4 , 1 , 16 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1410 */{ 0 , 2 , 4 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
-1411 */{ 12 , 1 , 24 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 29 384
-1412 */{ 0 , 2 , 12 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
-1413 */{ 0 , 2 , 1 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
-1414 */{ 9 , 1 , 22 , 9688 },/* 29 29 30 29 29 30 29 30 30 30 29 30 30 384
-1415 */{ 0 , 2 , 10 , 17840 },/* 29 30 29 29 29 30 29 30 30 29 30 30 0 354
-1416 */{ 0 , 1 , 30 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354
-1417 */{ 5 , 1 , 18 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1418 */{ 0 , 2 , 6 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1419 */{ 0 , 1 , 26 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
-1420 */{ 1 , 1 , 15 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1421 */{ 0 , 2 , 2 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1422 */{ 12 , 1 , 23 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-1423 */{ 0 , 2 , 11 , 19312 },/* 29 30 29 29 30 29 30 30 29 30 30 30 0 355
-1424 */{ 0 , 2 , 1 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354
-1425 */{ 7 , 1 , 20 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1426 */{ 0 , 2 , 8 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1427 */{ 0 , 1 , 28 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
-1428 */{ 4 , 1 , 17 , 27816 },/* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
-1429 */{ 0 , 2 , 4 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1430 */{ 12 , 1 , 24 , 39760 },/* 30 29 29 30 30 29 30 30 29 30 29 30 29 384
-1431 */{ 0 , 2 , 12 , 42720 },/* 30 29 30 29 29 30 30 29 30 30 30 29 0 355
-1432 */{ 0 , 2 , 2 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1433 */{ 8 , 1 , 21 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1434 */{ 0 , 2 , 9 , 42336 },/* 30 29 30 29 29 30 29 30 29 30 30 29 0 354
-1435 */{ 0 , 1 , 29 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
-1436 */{ 6 , 1 , 18 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
-1437 */{ 0 , 2 , 5 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1438 */{ 0 , 1 , 26 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1439 */{ 2 , 1 , 15 , 43728 },/* 30 29 30 29 30 29 30 29 30 30 29 30 29 384
-1440 */{ 0 , 2 , 3 , 38368 },/* 30 29 29 30 29 30 29 30 30 30 30 29 0 355
-1441 */{ 11 , 1 , 23 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1442 */{ 0 , 2 , 11 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1443 */{ 0 , 1 , 31 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1444 */{ 7 , 1 , 20 , 53872 },/* 30 30 29 30 29 29 30 29 29 30 30 30 29 384
-1445 */{ 0 , 2 , 7 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354
-1446 */{ 0 , 1 , 27 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1447 */{ 4 , 1 , 17 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1448 */{ 0 , 2 , 5 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354
-1449 */{ 0 , 1 , 24 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1450 */{ 1 , 1 , 14 , 19128 },/* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
-1451 */{ 0 , 2 , 2 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1452 */{ 9 , 1 , 22 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-1453 */{ 0 , 2 , 9 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1454 */{ 0 , 1 , 29 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354
-1455 */{ 6 , 1 , 18 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1456 */{ 0 , 2 , 6 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 0 355
-1457 */{ 0 , 1 , 26 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1458 */{ 2 , 1 , 15 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
-1459 */{ 0 , 2 , 3 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
-1460 */{ 11 , 1 , 24 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
-1461 */{ 0 , 2 , 10 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-1462 */{ 0 , 1 , 30 , 58544 },/* 30 30 30 29 29 30 29 29 30 29 30 30 0 355
-1463 */{ 7 , 1 , 20 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
-1464 */{ 0 , 2 , 7 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
-1465 */{ 0 , 1 , 27 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
-1466 */{ 3 , 1 , 17 , 11112 },/* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
-1467 */{ 0 , 2 , 5 , 9952 },/* 29 29 30 29 29 30 30 29 30 30 30 29 0 354
-1468 */{ 0 , 1 , 25 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1469 */{ 2 , 1 , 13 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-1470 */{ 0 , 2 , 1 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
-1471 */{ 9 , 1 , 21 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1472 */{ 0 , 2 , 9 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-1473 */{ 0 , 1 , 28 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 0 355
-1474 */{ 6 , 1 , 18 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
-1475 */{ 0 , 2 , 6 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
-1476 */{ 0 , 1 , 27 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1477 */{ 2 , 1 , 15 , 37592 },/* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
-1478 */{ 0 , 2 , 3 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
-1479 */{ 10 , 1 , 23 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1480 */{ 0 , 2 , 11 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
-1481 */{ 0 , 1 , 30 , 29856 },/* 29 30 30 30 29 30 29 29 30 29 30 29 0 354
-1482 */{ 8 , 1 , 19 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1483 */{ 0 , 2 , 7 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
-1484 */{ 0 , 1 , 28 , 21424 },/* 29 30 29 30 29 29 30 30 30 29 30 30 0 355
-1485 */{ 4 , 1 , 17 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
-1486 */{ 0 , 2 , 5 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354
-1487 */{ 0 , 1 , 25 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1488 */{ 1 , 1 , 14 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1489 */{ 0 , 2 , 1 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
-1490 */{ 9 , 1 , 21 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1491 */{ 0 , 2 , 9 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1492 */{ 0 , 1 , 29 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1493 */{ 5 , 1 , 18 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1494 */{ 0 , 2 , 6 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1495 */{ 0 , 1 , 26 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1496 */{ 3 , 1 , 16 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
-1497 */{ 0 , 2 , 2 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
-1498 */{ 11 , 1 , 22 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 29 384
-1499 */{ 0 , 2 , 10 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1500 */{ 0 , 1 , 31 , 5792 },/* 29 29 29 30 29 30 30 29 30 29 30 29 0 353
-1501 */{ 7 , 1 , 19 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
-1502 */{ 0 , 2 , 7 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
-1503 */{ 0 , 1 , 28 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1504 */{ 4 , 1 , 17 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1505 */{ 0 , 2 , 4 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1506 */{ 0 , 1 , 24 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-1507 */{ 1 , 1 , 13 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 29 384
-1508 */{ 0 , 2 , 1 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1509 */{ 9 , 1 , 21 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1510 */{ 0 , 2 , 9 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354
-1511 */{ 0 , 1 , 29 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1512 */{ 5 , 1 , 19 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1513 */{ 0 , 2 , 6 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1514 */{ 0 , 1 , 26 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1515 */{ 4 , 1 , 15 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1516 */{ 0 , 2 , 3 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354
-1517 */{ 12 , 1 , 22 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1518 */{ 0 , 2 , 10 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 0 355
-1519 */{ 0 , 1 , 31 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1520 */{ 8 , 1 , 20 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
-1521 */{ 0 , 2 , 7 , 37616 },/* 30 29 29 30 29 29 30 29 30 30 30 30 0 355
-1522 */{ 0 , 1 , 28 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1523 */{ 4 , 1 , 17 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
-1524 */{ 0 , 2 , 4 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1525 */{ 12 , 1 , 23 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 29 384
-1526 */{ 0 , 2 , 11 , 54928 },/* 30 30 29 30 29 30 30 29 30 29 29 30 0 355
-1527 */{ 0 , 2 , 1 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-1528 */{ 10 , 1 , 22 , 11112 },/* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
-1529 */{ 0 , 2 , 9 , 9952 },/* 29 29 30 29 29 30 30 29 30 30 30 29 0 354
-1530 */{ 0 , 1 , 29 , 21216 },/* 29 30 29 30 29 29 30 29 30 30 30 29 0 354
-1531 */{ 6 , 1 , 18 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-1532 */{ 0 , 2 , 6 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
-1533 */{ 0 , 1 , 25 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1534 */{ 2 , 1 , 14 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1535 */{ 0 , 2 , 2 , 46480 },/* 30 29 30 30 29 30 29 30 30 29 29 30 0 355
-1536 */{ 12 , 1 , 23 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
-1537 */{ 0 , 2 , 10 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
-1538 */{ 0 , 1 , 31 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1539 */{ 7 , 1 , 20 , 37592 },/* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
-1540 */{ 0 , 2 , 8 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
-1541 */{ 0 , 1 , 27 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1542 */{ 5 , 1 , 16 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-1543 */{ 0 , 2 , 4 , 27808 },/* 29 30 30 29 30 30 29 29 30 29 30 29 0 354
-1544 */{ 0 , 1 , 24 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-1545 */{ 1 , 1 , 13 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-1546 */{ 0 , 2 , 1 , 19376 },/* 29 30 29 29 30 29 30 30 30 29 30 30 0 355
-1547 */{ 9 , 1 , 22 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
-1548 */{ 0 , 2 , 10 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354
-1549 */{ 0 , 1 , 29 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1550 */{ 6 , 1 , 18 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
-1551 */{ 0 , 2 , 5 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
-1552 */{ 0 , 1 , 26 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1553 */{ 3 , 1 , 14 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1554 */{ 0 , 2 , 2 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1555 */{ 11 , 1 , 23 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1556 */{ 0 , 2 , 11 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1557 */{ 0 , 1 , 30 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1558 */{ 7 , 1 , 20 , 21096 },/* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
-1559 */{ 0 , 2 , 7 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-1560 */{ 0 , 1 , 27 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
-1561 */{ 5 , 1 , 16 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1562 */{ 0 , 2 , 4 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1563 */{ 0 , 1 , 24 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-1564 */{ 2 , 1 , 14 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1565 */{ 0 , 2 , 1 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1566 */{ 10 , 1 , 21 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1567 */{ 0 , 2 , 9 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1568 */{ 0 , 1 , 29 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-1569 */{ 6 , 1 , 17 , 54600 },/* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
-1570 */{ 0 , 2 , 5 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1571 */{ 0 , 1 , 26 , 13728 },/* 29 29 30 30 29 30 29 30 30 29 30 29 0 354
-1572 */{ 2 , 1 , 15 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
-1573 */{ 0 , 2 , 2 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1574 */{ 12 , 1 , 23 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1575 */{ 0 , 2 , 11 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1576 */{ 0 , 1 , 31 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1577 */{ 8 , 1 , 19 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1578 */{ 0 , 2 , 7 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
-1579 */{ 0 , 1 , 27 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
-1580 */{ 4 , 1 , 16 , 44456 },/* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
-1581 */{ 0 , 2 , 4 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1582 */{ 0 , 1 , 24 , 39024 },/* 30 29 29 30 29 29 30 30 39 30 30 30 0 365
-1583 */{ 2 , 1 , 24 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
-1584 */{ 0 , 2 , 12 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1585 */{ 9 , 1 , 31 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
-1586 */{ 0 , 2 , 18 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1587 */{ 0 , 3 , 9 , 53968 },/* 30 30 29 30 29 30 29 29 30 29 30 0 0 325
-1588 */{ 6 , 1 , 28 , 27464 },/* 29 30 30 29 30 29 30 30 29 30 29 29 30 384
-1589 */{ 0 , 2 , 15 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-1590 */{ 0 , 2 , 5 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1591 */{ 3 , 1 , 25 , 37616 },/* 30 29 29 30 29 29 30 29 30 30 30 30 29 384
-1592 */{ 0 , 2 , 13 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1593 */{ 11 , 2 , 1 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-1594 */{ 0 , 2 , 20 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1595 */{ 0 , 2 , 9 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1596 */{ 8 , 1 , 29 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1597 */{ 0 , 2 , 16 , 46288 },/* 30 29 30 30 29 30 29 29 30 30 29 30 0 355
-1598 */{ 0 , 2 , 6 , 22192 },/* 29 30 29 30 29 30 30 29 30 29 30 30 0 355
-1599 */{ 4 , 1 , 27 , 9944 },/* 29 29 30 29 29 30 30 29 30 30 29 30 30 384
-1600 */{ 0 , 2 , 15 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1601 */{ 0 , 2 , 3 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
-1602 */{ 2 , 1 , 23 , 51608 },/* 30 30 29 29 30 29 29 30 30 29 29 30 30 384
-1603 */{ 0 , 2 , 11 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1604 */{ 9 , 1 , 31 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-1605 */{ 0 , 2 , 18 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1606 */{ 0 , 2 , 7 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-1607 */{ 6 , 1 , 28 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-1608 */{ 0 , 2 , 16 , 19376 },/* 29 30 29 29 30 29 30 30 30 29 30 30 0 355
-1609 */{ 0 , 2 , 5 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 0 354
-1610 */{ 3 , 1 , 25 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1611 */{ 0 , 2 , 13 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1612 */{ 11 , 2 , 2 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
-1613 */{ 0 , 2 , 19 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
-1614 */{ 0 , 2 , 9 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1615 */{ 8 , 1 , 29 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1616 */{ 0 , 2 , 17 , 39760 },/* 30 29 29 30 30 29 30 30 29 30 29 30 0 355
-1617 */{ 0 , 2 , 6 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-1618 */{ 4 , 1 , 26 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1619 */{ 0 , 2 , 14 , 42224 },/* 30 29 30 29 29 30 29 29 30 30 30 30 0 355
-1620 */{ 0 , 2 , 4 , 21088 },/* 29 30 29 30 29 29 30 29 29 30 30 29 0 353
-1621 */{ 2 , 1 , 22 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-1622 */{ 0 , 2 , 10 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1623 */{ 10 , 1 , 31 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1624 */{ 0 , 2 , 19 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1625 */{ 0 , 2 , 7 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-1626 */{ 6 , 1 , 28 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1627 */{ 0 , 2 , 16 , 18912 },/* 29 30 29 29 30 29 29 30 30 30 30 29 0 354
-1628 */{ 0 , 2 , 5 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1629 */{ 4 , 1 , 24 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1630 */{ 0 , 2 , 12 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-1631 */{ 11 , 2 , 1 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
-1632 */{ 0 , 2 , 20 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
-1633 */{ 0 , 2 , 8 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
-1634 */{ 8 , 1 , 29 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
-1635 */{ 0 , 2 , 17 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1636 */{ 0 , 2 , 7 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1637 */{ 4 , 1 , 26 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-1638 */{ 0 , 2 , 14 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1639 */{ 0 , 2 , 3 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
-1640 */{ 1 , 1 , 23 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-1641 */{ 0 , 2 , 10 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
-1642 */{ 11 , 1 , 30 , 44456 },/* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
-1643 */{ 0 , 2 , 19 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1644 */{ 0 , 2 , 8 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
-1645 */{ 6 , 1 , 28 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
-1646 */{ 0 , 2 , 16 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1647 */{ 0 , 2 , 5 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1648 */{ 3 , 1 , 24 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1649 */{ 0 , 2 , 11 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-1650 */{ 11 , 2 , 1 , 27464 },/* 29 30 30 29 30 29 30 30 29 30 29 29 30 384
-1651 */{ 0 , 2 , 20 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-1652 */{ 0 , 2 , 10 , 11168 },/* 29 29 30 29 30 29 30 30 30 29 30 29 0 354
-1653 */{ 7 , 1 , 29 , 37616 },/* 30 29 29 30 29 29 30 29 30 30 30 30 29 384
-1654 */{ 0 , 2 , 17 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1655 */{ 0 , 2 , 6 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-1656 */{ 5 , 1 , 26 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1657 */{ 0 , 2 , 13 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1658 */{ 0 , 2 , 2 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-1659 */{ 3 , 1 , 23 , 39592 },/* 30 29 29 30 30 29 30 29 30 29 30 29 30 384
-1660 */{ 0 , 2 , 11 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1661 */{ 7 , 1 , 30 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 29 384
-1662 */{ 0 , 2 , 18 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 0 355
-1663 */{ 0 , 2 , 8 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
-1664 */{ 6 , 1 , 28 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1665 */{ 0 , 2 , 15 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1666 */{ 0 , 2 , 4 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-1667 */{ 4 , 1 , 24 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1668 */{ 0 , 2 , 12 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-1669 */{ 0 , 2 , 1 , 21920 },/* 29 30 29 30 29 30 29 30 30 29 30 29 0 354
-1670 */{ 2 , 1 , 21 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
-1671 */{ 0 , 2 , 9 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
-1672 */{ 7 , 1 , 30 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1673 */{ 0 , 2 , 17 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1674 */{ 0 , 2 , 6 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354
-1675 */{ 5 , 1 , 26 , 29864 },/* 29 30 30 30 29 30 29 29 30 29 30 29 30 384
-1676 */{ 0 , 2 , 14 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1677 */{ 0 , 2 , 2 , 44432 },/* 30 29 30 29 30 30 29 30 30 29 29 30 0 355
-1678 */{ 3 , 1 , 23 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
-1679 */{ 0 , 2 , 11 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-1680 */{ 8 , 1 , 31 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1681 */{ 0 , 2 , 18 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
-1682 */{ 0 , 2 , 7 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-1683 */{ 6 , 1 , 27 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
-1684 */{ 0 , 2 , 15 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
-1685 */{ 0 , 2 , 3 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
-1686 */{ 4 , 1 , 24 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
-1687 */{ 0 , 2 , 12 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-1688 */{ 0 , 2 , 2 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1689 */{ 3 , 1 , 21 , 42216 },/* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
-1690 */{ 0 , 2 , 9 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1691 */{ 7 , 1 , 29 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
-1692 */{ 0 , 2 , 17 , 45136 },/* 30 29 29 32 29 29 29 29 29 30 29 30 0 354
-1693 */{ 0 , 2 , 5 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
-1694 */{ 5 , 1 , 25 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 29 384
-1695 */{ 0 , 2 , 13 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
-1696 */{ 0 , 2 , 3 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
-1697 */{ 3 , 1 , 23 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
-1698 */{ 0 , 2 , 11 , 18896 },/* 29 30 29 29 30 29 29 30 30 30 29 30 0 354
-1699 */{ 7 , 1 , 31 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-1700 */{ 0 , 2 , 19 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1701 */{ 0 , 2 , 8 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
-1702 */{ 6 , 1 , 28 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-1703 */{ 0 , 2 , 16 , 27936 },/* 29 30 30 29 30 30 29 30 29 29 30 29 0 354
-1704 */{ 0 , 2 , 5 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
-1705 */{ 4 , 1 , 25 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-1706 */{ 0 , 2 , 13 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
-1707 */{ 0 , 2 , 3 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1708 */{ 3 , 1 , 23 , 25784 },/* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
-1709 */{ 0 , 2 , 10 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1710 */{ 7 , 1 , 30 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1711 */{ 0 , 2 , 17 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-1712 */{ 0 , 2 , 7 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1713 */{ 5 , 1 , 26 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
-1714 */{ 0 , 2 , 14 , 43744 },/* 30 29 30 29 30 29 30 29 30 30 30 29 0 355
-1715 */{ 0 , 2 , 4 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1716 */{ 3 , 1 , 24 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
-1717 */{ 0 , 2 , 11 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-1718 */{ 8 , 1 , 31 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1719 */{ 0 , 2 , 19 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1720 */{ 0 , 2 , 8 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1721 */{ 6 , 1 , 28 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-1722 */{ 0 , 2 , 16 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1723 */{ 0 , 2 , 5 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
-1724 */{ 4 , 1 , 26 , 21224 },/* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
-1725 */{ 0 , 2 , 13 , 21200 },/* 29 30 29 30 29 29 30 29 30 30 29 30 0 354
-1726 */{ 0 , 2 , 2 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1727 */{ 3 , 1 , 22 , 58536 },/* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
-1728 */{ 0 , 2 , 10 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-1729 */{ 7 , 1 , 29 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1730 */{ 0 , 2 , 17 , 40272 },/* 30 29 29 30 30 30 29 30 29 30 29 30 0 355
-1731 */{ 0 , 2 , 7 , 21920 },/* 29 30 29 30 29 30 29 30 30 29 30 29 0 354
-1732 */{ 5 , 1 , 27 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
-1733 */{ 0 , 2 , 14 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
-1734 */{ 0 , 2 , 4 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1735 */{ 4 , 1 , 24 , 43192 },/* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
-1736 */{ 0 , 2 , 12 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354
-1737 */{ 9 , 1 , 31 , 27288 },/* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
-1738 */{ 0 , 2 , 19 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1739 */{ 0 , 2 , 8 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1740 */{ 6 , 1 , 29 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
-1741 */{ 0 , 2 , 16 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-1742 */{ 0 , 2 , 5 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1743 */{ 4 , 1 , 26 , 20848 },/* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
-1744 */{ 0 , 2 , 13 , 53600 },/* 30 30 29 30 29 29 29 30 29 30 30 29 0 354
-1745 */{ 0 , 2 , 1 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 0 355
-1746 */{ 3 , 1 , 22 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
-1747 */{ 0 , 2 , 9 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
-1748 */{ 7 , 1 , 30 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
-1749 */{ 0 , 2 , 17 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-1750 */{ 0 , 2 , 7 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1751 */{ 5 , 1 , 27 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1752 */{ 0 , 2 , 15 , 41680 },/* 30 29 30 29 29 29 30 29 30 30 29 30 0 354
-1753 */{ 0 , 2 , 3 , 53592 },/* 30 30 29 30 29 29 29 30 29 30 29 30 30 384
-1754 */{ 4 , 2 , 22 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
-1755 */{ 0 , 2 , 11 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
-1756 */{ 9 , 1 , 31 , 54928 },/* 30 30 29 30 29 30 30 29 30 29 29 30 29 384
-1757 */{ 0 , 2 , 18 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
-1758 */{ 0 , 2 , 8 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
-1759 */{ 6 , 1 , 29 , 10968 },/* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
-1760 */{ 0 , 2 , 17 , 17840 },/* 29 30 29 29 29 30 29 30 30 29 30 30 0 354
-1761 */{ 0 , 2 , 5 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354
-1762 */{ 5 , 1 , 25 , 45400 },/* 30 29 30 30 29 29 29 30 29 30 29 30 30 384
-1763 */{ 0 , 2 , 13 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1764 */{ 0 , 2 , 2 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
-1765 */{ 2 , 1 , 21 , 46480 },/* 30 29 30 30 29 30 29 30 30 29 29 30 29 384
-1766 */{ 0 , 2 , 9 , 44384 },/* 30 29 30 29 30 30 29 30 29 30 30 29 0 355
-1767 */{ 7 , 1 , 30 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
-1768 */{ 0 , 2 , 18 , 21360 },/* 29 30 29 30 29 29 30 30 29 30 30 30 0 355
-1769 */{ 0 , 2 , 7 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354
-1770 */{ 5 , 1 , 27 , 25272 },/* 29 30 30 29 29 29 30 29 30 29 30 30 30 384
-1771 */{ 0 , 2 , 15 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1772 */{ 0 , 2 , 4 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
-1773 */{ 3 , 1 , 23 , 27816 },/* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
-1774 */{ 0 , 2 , 11 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1775 */{ 10 , 1 , 31 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
-1776 */{ 0 , 2 , 19 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
-1777 */{ 0 , 2 , 8 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1778 */{ 6 , 1 , 28 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
-1779 */{ 0 , 2 , 16 , 42336 },/* 30 29 30 29 29 30 29 30 29 30 30 29 0 354
-1780 */{ 0 , 2 , 5 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
-1781 */{ 5 , 1 , 24 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
-1782 */{ 0 , 2 , 12 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1783 */{ 0 , 2 , 2 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1784 */{ 3 , 1 , 22 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
-1785 */{ 0 , 2 , 9 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
-1786 */{ 7 , 1 , 30 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1787 */{ 0 , 2 , 18 , 19120 },/* 29 30 29 29 30 29 30 29 30 29 30 30 0 354
-1788 */{ 0 , 2 , 7 , 43216 },/* 30 29 30 29 30 29 29 29 30 30 29 30 0 354
-1789 */{ 5 , 1 , 26 , 53928 },/* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
-1790 */{ 0 , 2 , 14 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354
-1791 */{ 0 , 2 , 3 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1792 */{ 4 , 1 , 24 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1793 */{ 0 , 2 , 11 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
-1794 */{ 0 , 1 , 31 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
-1795 */{ 2 , 1 , 21 , 19128 },/* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
-1796 */{ 0 , 2 , 9 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1797 */{ 6 , 1 , 28 , 43192 },/* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
-1798 */{ 0 , 2 , 16 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1799 */{ 0 , 2 , 5 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354
-1800 */{ 4 , 1 , 25 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1801 */{ 0 , 2 , 13 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 0 355
-1802 */{ 0 , 2 , 3 , 11168 },/* 29 29 30 29 30 29 30 30 30 29 30 29 0 354
-1803 */{ 2 , 1 , 23 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
-1804 */{ 0 , 2 , 11 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
-1805 */{ 6 , 1 , 31 , 20848 },/* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
-1806 */{ 0 , 2 , 18 , 53600 },/* 30 30 29 30 29 29 29 30 29 30 30 29 0 354
-1807 */{ 0 , 2 , 7 , 58544 },/* 30 30 30 29 29 30 29 29 30 29 30 30 0 355
-1808 */{ 5 , 1 , 28 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
-1809 */{ 0 , 2 , 14 , 55952 },/* 30 30 29 30 30 29 30 29 30 29 29 30 0 355
-1810 */{ 0 , 2 , 4 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 0 355
-1811 */{ 3 , 1 , 25 , 11112 },/* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
-1812 */{ 0 , 2 , 13 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354
-1813 */{ 0 , 2 , 1 , 41696 },/* 30 29 30 29 29 29 30 29 30 30 30 29 0 354
-1814 */{ 2 , 1 , 21 , 53608 },/* 30 30 29 30 29 29 29 30 29 30 30 29 30 384
-1815 */{ 0 , 2 , 9 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
-1816 */{ 6 , 1 , 29 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1817 */{ 0 , 2 , 16 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
-1818 */{ 0 , 2 , 5 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 0 355
-1819 */{ 4 , 1 , 26 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
-1820 */{ 0 , 2 , 14 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
-1821 */{ 0 , 2 , 3 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1822 */{ 3 , 1 , 23 , 41688 },/* 30 29 30 29 29 29 30 29 30 30 29 30 30 384
-1823 */{ 0 , 2 , 11 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354
-1824 */{ 7 , 1 , 31 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1825 */{ 0 , 2 , 18 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1826 */{ 0 , 2 , 7 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-1827 */{ 5 , 1 , 27 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
-1828 */{ 0 , 2 , 15 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-1829 */{ 0 , 2 , 4 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
-1830 */{ 4 , 1 , 25 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
-1831 */{ 0 , 2 , 13 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354
-1832 */{ 9 , 2 , 2 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-1833 */{ 0 , 2 , 20 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1834 */{ 0 , 2 , 9 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
-1835 */{ 6 , 1 , 29 , 27816 },/* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
-1836 */{ 0 , 2 , 17 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1837 */{ 0 , 2 , 5 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1838 */{ 4 , 1 , 26 , 21352 },/* 29 30 29 30 29 29 30 30 29 30 30 29 30 384
-1839 */{ 0 , 2 , 14 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1840 */{ 0 , 2 , 3 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1841 */{ 3 , 1 , 23 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 29 383
-1842 */{ 0 , 2 , 10 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
-1843 */{ 7 , 1 , 30 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
-1844 */{ 0 , 2 , 18 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
-1845 */{ 0 , 2 , 7 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-1846 */{ 5 , 1 , 27 , 43728 },/* 30 29 30 29 30 29 30 29 30 30 29 30 29 384
-1847 */{ 0 , 2 , 15 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
-1848 */{ 0 , 2 , 5 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1849 */{ 4 , 1 , 24 , 42328 },/* 30 29 30 29 29 30 29 30 29 30 29 30 30 384
-1850 */{ 0 , 2 , 12 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1851 */{ 8 , 2 , 1 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
-1852 */{ 0 , 2 , 20 , 45712 },/* 30 29 30 30 29 29 30 29 30 29 29 30 0 354
-1853 */{ 0 , 2 , 8 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1854 */{ 7 , 1 , 29 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1855 */{ 0 , 2 , 17 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354
-1856 */{ 0 , 2 , 6 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
-1857 */{ 5 , 1 , 26 , 19128 },/* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
-1858 */{ 0 , 2 , 14 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1859 */{ 0 , 2 , 3 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1860 */{ 3 , 1 , 23 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1861 */{ 0 , 2 , 10 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354
-1862 */{ 8 , 1 , 30 , 44360 },/* 30 29 30 29 30 30 29 30 29 30 29 29 30 384
-1863 */{ 0 , 2 , 18 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 0 355
-1864 */{ 0 , 2 , 8 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1865 */{ 5 , 1 , 27 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
-1866 */{ 0 , 2 , 15 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
-1867 */{ 0 , 2 , 5 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1868 */{ 4 , 1 , 25 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
-1869 */{ 0 , 2 , 11 , 58528 },/* 30 30 30 29 29 30 29 29 30 29 30 29 0 354
-1870 */{ 10 , 1 , 31 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 29 384
-1871 */{ 0 , 2 , 19 , 55952 },/* 30 30 29 30 30 29 30 29 30 29 29 30 0 355
-1872 */{ 0 , 2 , 9 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
-1873 */{ 6 , 1 , 29 , 11112 },/* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
-1874 */{ 0 , 2 , 17 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354
-1875 */{ 0 , 2 , 6 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1876 */{ 5 , 1 , 26 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-1877 */{ 0 , 2 , 13 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
-1878 */{ 0 , 2 , 2 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1879 */{ 3 , 1 , 22 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1880 */{ 0 , 2 , 10 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 0 355
-1881 */{ 7 , 1 , 30 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
-1882 */{ 0 , 2 , 18 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
-1883 */{ 0 , 2 , 8 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1884 */{ 5 , 1 , 28 , 37592 },/* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
-1885 */{ 0 , 2 , 15 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
-1886 */{ 0 , 2 , 4 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1887 */{ 4 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1888 */{ 0 , 2 , 12 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-1889 */{ 0 , 1 , 31 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1890 */{ 2 , 1 , 21 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1891 */{ 0 , 2 , 9 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
-1892 */{ 6 , 1 , 30 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
-1893 */{ 0 , 2 , 17 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354
-1894 */{ 0 , 2 , 6 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1895 */{ 5 , 1 , 26 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
-1896 */{ 0 , 2 , 13 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
-1897 */{ 0 , 2 , 2 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1898 */{ 3 , 1 , 22 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1899 */{ 0 , 2 , 10 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1900 */{ 8 , 1 , 31 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
-1901 */{ 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1902 */{ 0 , 2 , 8 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1903 */{ 5 , 1 , 29 , 21096 },/* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
-1904 */{ 0 , 2 , 16 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
-1905 */{ 0 , 2 , 4 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
-1906 */{ 4 , 1 , 25 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1907 */{ 0 , 2 , 13 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1908 */{ 0 , 2 , 2 , 39632 },/* 30 29 29 30 30 29 30 29 30 30 29 30 0 355
-1909 */{ 2 , 1 , 22 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1910 */{ 0 , 2 , 10 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1911 */{ 6 , 1 , 30 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1912 */{ 0 , 2 , 18 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-1913 */{ 0 , 2 , 6 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-1914 */{ 5 , 1 , 26 , 55624 },/* 30 30 29 30 30 29 29 30 29 30 29 29 30 384
-1915 */{ 0 , 2 , 14 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1916 */{ 0 , 2 , 4 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1917 */{ 2 , 1 , 23 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
-1918 */{ 0 , 2 , 11 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
-1919 */{ 7 , 2 , 1 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
-1920 */{ 0 , 2 , 20 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1921 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1922 */{ 5 , 1 , 28 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1923 */{ 0 , 2 , 16 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354
-1924 */{ 0 , 2 , 5 , 44352 },/* 30 29 30 29 30 30 29 30 29 30 29 29 0 354
-1925 */{ 4 , 1 , 24 , 46504 },/* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
-1926 */{ 0 , 2 , 13 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1927 */{ 0 , 2 , 2 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1928 */{ 2 , 1 , 23 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1929 */{ 0 , 2 , 10 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1930 */{ 6 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
-1931 */{ 0 , 2 , 17 , 58528 },/* 30 30 30 29 29 30 29 29 30 29 30 29 0 354
-1932 */{ 0 , 2 , 6 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
-1933 */{ 5 , 1 , 26 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
-1934 */{ 0 , 2 , 14 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 0 355
-1935 */{ 0 , 2 , 4 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1936 */{ 3 , 1 , 24 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
-1937 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-1938 */{ 7 , 1 , 31 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
-1939 */{ 0 , 2 , 19 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
-1940 */{ 0 , 2 , 8 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-1941 */{ 6 , 1 , 27 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
-1942 */{ 0 , 2 , 15 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 0 355
-1943 */{ 0 , 2 , 5 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
-1944 */{ 4 , 1 , 26 , 10968 },/* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
-1945 */{ 0 , 2 , 13 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-1946 */{ 0 , 2 , 2 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
-1947 */{ 2 , 1 , 22 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
-1948 */{ 0 , 2 , 10 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-1949 */{ 7 , 1 , 29 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
-1950 */{ 0 , 2 , 17 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-1951 */{ 0 , 2 , 6 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-1952 */{ 5 , 1 , 27 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
-1953 */{ 0 , 2 , 14 , 19888 },/* 29 30 29 29 30 30 29 30 30 29 30 30 0 355
-1954 */{ 0 , 2 , 4 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 0 354
-1955 */{ 3 , 1 , 24 , 37560 },/* 30 29 29 30 29 29 30 29 30 29 30 30 30 384
-1956 */{ 0 , 2 , 12 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-1957 */{ 8 , 1 , 31 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
-1958 */{ 0 , 2 , 19 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
-1959 */{ 0 , 2 , 8 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-1960 */{ 6 , 1 , 28 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
-1961 */{ 0 , 2 , 15 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
-1962 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-1963 */{ 4 , 1 , 25 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-1964 */{ 0 , 2 , 13 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-1965 */{ 0 , 2 , 2 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
-1966 */{ 3 , 1 , 22 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
-1967 */{ 0 , 2 , 9 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
-1968 */{ 7 , 1 , 30 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
-1969 */{ 0 , 2 , 17 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
-1970 */{ 0 , 2 , 6 , 39632 },/* 30 29 29 30 30 29 30 29 30 30 29 30 0 355
-1971 */{ 5 , 1 , 27 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-1972 */{ 0 , 2 , 15 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-1973 */{ 0 , 2 , 3 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
-1974 */{ 4 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-1975 */{ 0 , 2 , 11 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-1976 */{ 8 , 1 , 31 , 54600 },/* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
-1977 */{ 0 , 2 , 18 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
-1978 */{ 0 , 2 , 7 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355
-1979 */{ 6 , 1 , 28 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
-1980 */{ 0 , 2 , 16 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1981 */{ 0 , 2 , 5 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-1982 */{ 4 , 1 , 25 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
-1983 */{ 0 , 2 , 13 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-1984 */{ 10 , 2 , 2 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
-1985 */{ 0 , 2 , 20 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
-1986 */{ 0 , 2 , 9 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
-1987 */{ 6 , 1 , 29 , 46504 },/* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
-1988 */{ 0 , 2 , 18 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1989 */{ 0 , 2 , 6 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
-1990 */{ 5 , 1 , 27 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
-1991 */{ 0 , 2 , 15 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
-1992 */{ 0 , 2 , 4 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
-1993 */{ 3 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
-1994 */{ 0 , 2 , 10 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
-1995 */{ 8 , 1 , 31 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
-1996 */{ 0 , 2 , 19 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
-1997 */{ 0 , 2 , 8 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
-1998 */{ 5 , 1 , 28 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
-1999 */{ 0 , 2 , 16 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
-2000 */{ 0 , 2 , 5 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
-2001 */{ 4 , 1 , 24 , 58536 },/* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
-2002 */{ 0 , 2 , 12 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
-2003 */{ 0 , 2 , 1 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
-2004 */{ 2 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
-2005 */{ 0 , 2 , 9 , 22208 },/* 29 30 29 30 29 30 30 29 30 30 29 29 0 354
-2006 */{ 7 , 1 , 29 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
-2007 */{ 0 , 2 , 18 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
-2008 */{ 0 , 2 , 7 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
-2009 */{ 5 , 1 , 26 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
-2010 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-2011 */{ 0 , 2 , 3 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
-2012 */{ 3 , 1 , 23 , 47696 },/* 30 29 30 30 30 29 30 29 29 30 29 30 29 384
-2013 */{ 0 , 2 , 10 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
-2014 */{ 9 , 1 , 31 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-2015 */{ 0 , 2 , 19 , 19360 },/* 29 30 29 29 30 29 30 30 30 29 30 29 0 354
-2016 */{ 0 , 2 , 8 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
-2017 */{ 5 , 1 , 28 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
-2018 */{ 0 , 2 , 16 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
-2019 */{ 0 , 2 , 5 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
-2020 */{ 4 , 1 , 25 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
-2021 */{ 0 , 2 , 12 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
-2022 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
-2023 */{ 2 , 1 , 22 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
-2024 */{ 0 , 2 , 10 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
-2025 */{ 6 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
-2026 */{ 0 , 2 , 17 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
-2027 */{ 0 , 2 , 7 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
-2028 */{ 5 , 1 , 27 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
-2029 */{ 0 , 2 , 13 , 55600 },/* 30 30 29 30 30 29 29 30 29 29 30 30 0 355
-2030 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
-2031 */{ 3 , 1 , 23 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
-2032 */{ 0 , 2 , 11 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-2033 */{ 11 , 1 , 31 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
-2034 */{ 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
-2035 */{ 0 , 2 , 8 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
-2036 */{ 6 , 1 , 28 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
-2037 */{ 0 , 2 , 15 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
-2038 */{ 0 , 2 , 4 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
-2039 */{ 5 , 1 , 24 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
-2040 */{ 0 , 2 , 12 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355
-2041 */{ 0 , 2 , 1 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
-2042 */{ 2 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
-2043 */{ 0 , 2 , 10 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
-2044 */{ 7 , 1 , 30 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
-2045 */{ 0 , 2 , 17 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
-2046 */{ 0 , 2 , 6 , 45648 },/* 30 29 30 30 29 29 30 29 29 30 29 30 0 354
-2047 */{ 5 , 1 , 26 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
-2048 */{ 0 , 2 , 14 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
-2049 */{ 0 , 2 , 2 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
-2050 */{ 3 , 1 , 23 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
- */};
-
+/*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
+0918 */ { 00, 02, 19, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
+0919 */ { 00, 02, 09, 0b0100010111010000 }, /* 29 30 29 29 29 30 29 30 30 30 29 30 354
+0920 */ { 06, 01, 29, 0b1010001011011000 }, /* 30 29 30 29 29 29 30 29 30 30 29 30 30 384
+0921 */ { 00, 02, 16, 0b1010001010110000 }, /* 30 29 30 29 29 29 30 29 30 29 30 30 354
+0922 */ { 00, 02, 05, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+0923 */ { 04, 01, 25, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+0924 */ { 00, 02, 13, 0b0110110100100000 }, /* 29 30 30 29 30 30 29 30 29 29 30 29 354
+0925 */ { 12, 02, 01, 0b1010110101100000 }, /* 30 29 30 29 30 30 29 30 29 30 30 29 29 384
+0926 */ { 00, 02, 20, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+0927 */ { 00, 02, 10, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
+0928 */ { 08, 01, 31, 0b0100010110111000 }, /* 29 30 29 29 29 30 29 30 30 29 30 30 30 384
+0929 */ { 00, 02, 18, 0b0100010101110000 }, /* 29 30 29 29 29 30 29 30 29 30 30 30 354
+0930 */ { 00, 02, 07, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+0931 */ { 05, 01, 27, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 29 383
+0932 */ { 00, 02, 14, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 355
+0933 */ { 00, 02, 03, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+0934 */ { 01, 01, 23, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+0935 */ { 00, 02, 11, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+0936 */ { 11, 02, 01, 0b0101001101100000 }, /* 29 30 29 30 29 29 30 30 29 30 30 29 29 383
+0937 */ { 00, 02, 18, 0b1100101011000000 }, /* 30 30 29 29 30 29 30 29 30 30 29 29 354
+0938 */ { 00, 02, 07, 0b1110010101100000 }, /* 30 30 30 29 29 30 29 30 29 30 30 29 355
+0939 */ { 07, 01, 28, 0b1101001010101000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
+0940 */ { 00, 02, 16, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
+0941 */ { 00, 02, 04, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
+0942 */ { 03, 01, 25, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+0943 */ { 00, 02, 13, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+0944 */ { 12, 02, 02, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 29 384
+0945 */ { 00, 02, 20, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
+0946 */ { 00, 02, 10, 0b0100101011010000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 354
+0947 */ { 07, 01, 30, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+0948 */ { 00, 02, 18, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+0949 */ { 00, 02, 06, 0b1011001001100000 }, /* 30 29 30 30 29 29 30 29 29 30 30 29 354
+0950 */ { 05, 01, 26, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+0951 */ { 00, 02, 14, 0b1011001101110000 }, /* 30 29 30 30 29 29 30 30 29 30 30 30 356
+0953 */ { 00, 01, 05, 0b1010101011010000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 355
+0953 */ { 01, 01, 23, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
+0954 */ { 00, 02, 11, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+0955 */ { 09, 02, 01, 0b0100101010111000 }, /* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
+0956 */ { 00, 02, 20, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+0957 */ { 00, 02, 08, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+0958 */ { 07, 01, 28, 0b1010101010011000 }, /* 30 29 30 29 30 29 30 29 30 29 29 30 30 384
+0959 */ { 00, 02, 16, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+0960 */ { 00, 02, 05, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+0961 */ { 03, 01, 25, 0b0100110110101000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+0962 */ { 00, 02, 13, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+0963 */ { 12, 02, 02, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
+0964 */ { 00, 02, 21, 0b1010001101110000 }, /* 30 29 30 29 29 29 30 30 29 30 30 30 355
+0965 */ { 00, 02, 10, 0b0101000101110000 }, /* 29 30 29 30 29 29 29 30 29 30 30 30 354
+0966 */ { 08, 01, 30, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+0967 */ { 00, 02, 17, 0b1101010010110000 }, /* 30 30 29 30 29 30 29 29 30 29 30 30 355
+0968 */ { 00, 02, 07, 0b0101101010010000 }, /* 29 30 29 30 30 29 30 29 30 29 29 30 354
+0969 */ { 05, 01, 26, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+0970 */ { 00, 02, 14, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+0971 */ { 00, 02, 04, 0b0010101011100000 }, /* 29 29 30 29 30 29 30 29 30 30 30 29 354
+0972 */ { 02, 01, 24, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+0973 */ { 00, 02, 11, 0b1010001011100000 }, /* 30 29 30 29 29 29 30 29 30 30 30 29 354
+0974 */ { 10, 01, 31, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+0975 */ { 00, 02, 19, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+0976 */ { 00, 02, 08, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+0977 */ { 07, 01, 27, 0b1101101010010000 }, /* 30 30 29 30 30 29 30 29 30 29 29 30 29 384
+0978 */ { 00, 02, 15, 0b1011010110100000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 355
+0979 */ { 00, 02, 05, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+0980 */ { 03, 01, 26, 0b0010101011011000 }, /* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
+0981 */ { 00, 02, 13, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+0982 */ { 12, 02, 02, 0b1001001011011000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
+0983 */ { 00, 02, 21, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
+0984 */ { 00, 02, 10, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+0985 */ { 09, 01, 29, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+0986 */ { 00, 02, 17, 0b1010110010100000 }, /* 30 29 30 29 30 30 29 29 30 29 30 29 354
+0987 */ { 00, 02, 06, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+0988 */ { 05, 01, 27, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+0989 */ { 00, 02, 14, 0b0100101110110000 }, /* 29 30 29 29 30 29 30 30 30 29 30 30 355
+0990 */ { 00, 02, 04, 0b0010010110110000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 354
+0991 */ { 02, 01, 24, 0b1001001010111000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 30 384
+0992 */ { 00, 02, 12, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+0993 */ { 10, 01, 31, 0b0110100101011000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 30 384
+0994 */ { 00, 02, 19, 0b0101100101010000 }, /* 29 30 29 30 30 29 29 30 29 30 29 30 354
+0995 */ { 00, 02, 08, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+0996 */ { 07, 01, 28, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+0997 */ { 00, 02, 15, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+0998 */ { 00, 02, 05, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+0999 */ { 03, 01, 25, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1000 */ { 00, 02, 13, 0b0010010101110000 }, /* 29 29 30 29 29 30 29 30 29 30 30 30 354
+1001 */ { 12, 02, 03, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 29 383
+1002 */ { 00, 02, 21, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
+1003 */ { 00, 02, 10, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1004 */ { 09, 01, 31, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1005 */ { 00, 02, 18, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1006 */ { 00, 02, 07, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+1007 */ { 05, 01, 28, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1008 */ { 00, 02, 16, 0b0100101011010000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 354
+1009 */ { 00, 02, 04, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1010 */ { 02, 01, 24, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1011 */ { 00, 02, 12, 0b1011001001100000 }, /* 30 29 30 30 29 29 30 29 29 30 30 29 354
+1012 */ { 10, 02, 01, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1013 */ { 00, 02, 19, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+1014 */ { 00, 02, 09, 0b0011010110100000 }, /* 29 29 30 30 29 30 29 30 30 29 30 29 354
+1015 */ { 06, 01, 29, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
+1016 */ { 00, 02, 17, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1017 */ { 00, 02, 06, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1018 */ { 04, 01, 26, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1019 */ { 00, 02, 14, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1020 */ { 12, 02, 03, 0b1010101001011000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 30 384
+1021 */ { 00, 02, 21, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1022 */ { 00, 02, 10, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+1023 */ { 09, 01, 31, 0b0010110110101000 }, /* 29 29 30 29 30 30 29 30 30 29 30 29 30 384
+1024 */ { 00, 02, 19, 0b0010101101010000 }, /* 29 29 30 29 30 29 30 30 29 30 29 30 354
+1025 */ { 00, 02, 07, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 355
+1026 */ { 05, 01, 28, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
+1027 */ { 00, 02, 15, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 355
+1028 */ { 00, 02, 05, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1029 */ { 02, 01, 24, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1030 */ { 00, 02, 11, 0b1101101010010000 }, /* 30 30 29 30 30 29 30 29 30 29 29 30 355
+1031 */ { 10, 02, 01, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+1032 */ { 00, 02, 20, 0b0110011011010000 }, /* 29 30 30 29 29 30 30 29 30 30 29 30 355
+1033 */ { 00, 02, 09, 0b0010011011100000 }, /* 29 29 30 29 29 30 30 29 30 30 30 29 354
+1034 */ { 06, 01, 29, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1035 */ { 00, 02, 17, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1036 */ { 00, 02, 06, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+1037 */ { 04, 01, 25, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1038 */ { 00, 02, 13, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1039 */ { 12, 02, 02, 0b1101011010010000 }, /* 30 30 29 30 29 30 30 29 30 29 29 30 29 384
+1040 */ { 00, 02, 21, 0b1011010110000000 }, /* 30 29 30 30 29 30 29 30 30 29 29 29 354
+1041 */ { 00, 02, 09, 0b1101011010110000 }, /* 30 30 29 30 29 30 30 29 30 29 30 30 356
+1042 */ { 09, 01, 31, 0b0010011011011000 }, /* 29 29 30 29 29 30 30 29 30 30 29 30 30 384
+1043 */ { 00, 02, 19, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+1044 */ { 00, 02, 08, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
+1045 */ { 05, 01, 27, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1046 */ { 00, 02, 15, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1047 */ { 00, 02, 04, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+1048 */ { 01, 01, 24, 0b1011010101011000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 30 385
+1049 */ { 00, 02, 12, 0b0010110101010000 }, /* 29 29 30 29 30 30 29 30 29 30 29 30 354
+1050 */ { 11, 02, 01, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1051 */ { 00, 02, 20, 0b0100101110110000 }, /* 29 30 29 29 30 29 30 30 30 29 30 30 355
+1052 */ { 00, 02, 10, 0b0010010110110000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 354
+1053 */ { 07, 01, 29, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1054 */ { 00, 02, 17, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1055 */ { 00, 02, 06, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
+1056 */ { 03, 01, 26, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1057 */ { 00, 02, 13, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1058 */ { 12, 02, 02, 0b1010101101011000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 30 385
+1059 */ { 00, 02, 22, 0b0010011101010000 }, /* 29 29 30 29 29 30 30 30 29 30 29 30 354
+1060 */ { 00, 02, 11, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+1061 */ { 08, 01, 30, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1062 */ { 00, 02, 18, 0b1010010101100000 }, /* 30 29 30 29 29 30 29 30 29 30 30 29 354
+1063 */ { 00, 02, 07, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
+1064 */ { 05, 01, 27, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1065 */ { 00, 02, 14, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1066 */ { 00, 02, 04, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1067 */ { 01, 01, 24, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+1068 */ { 00, 02, 12, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+1069 */ { 11, 02, 01, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1070 */ { 00, 02, 20, 0b0100100111010000 }, /* 29 30 29 29 30 29 29 30 30 30 29 30 354
+1071 */ { 00, 02, 09, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1072 */ { 07, 01, 29, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1073 */ { 00, 02, 16, 0b1010101001100000 }, /* 30 29 30 29 30 29 30 29 29 30 30 29 354
+1074 */ { 00, 02, 05, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1075 */ { 04, 01, 26, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1076 */ { 00, 02, 14, 0b0011010110100000 }, /* 29 29 30 30 29 30 29 30 30 29 30 29 354
+1077 */ { 00, 02, 02, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
+1078 */ { 01, 01, 23, 0b0100101110011000 }, /* 29 30 29 29 30 29 30 30 30 29 29 30 30 384
+1079 */ { 00, 02, 11, 0b0100010110110000 }, /* 29 30 29 29 29 30 29 30 30 29 30 30 354
+1080 */ { 09, 01, 31, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1081 */ { 00, 02, 18, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1082 */ { 00, 02, 07, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
+1083 */ { 06, 01, 27, 0b1011010101001000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 30 384
+1084 */ { 00, 02, 15, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 355
+1085 */ { 00, 02, 04, 0b0010110110100000 }, /* 29 29 30 29 30 30 29 30 30 29 30 29 354
+1086 */ { 02, 01, 24, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
+1087 */ { 00, 02, 12, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
+1088 */ { 12, 02, 02, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
+1089 */ { 00, 02, 19, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 355
+1090 */ { 00, 02, 09, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1091 */ { 08, 01, 29, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1092 */ { 00, 02, 16, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
+1093 */ { 00, 02, 05, 0b0101101101000000 }, /* 29 30 29 30 30 29 30 30 29 30 29 29 354
+1094 */ { 04, 01, 25, 0b1010101101101000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 30 385
+1095 */ { 00, 02, 14, 0b0010101011100000 }, /* 29 29 30 29 30 29 30 29 30 30 30 29 354
+1096 */ { 00, 02, 03, 0b1110011000010000 }, /* 30 30 30 29 29 30 30 29 29 29 29 30 354
+1097 */ { 02, 01, 22, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
+1098 */ { 00, 02, 10, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+1099 */ { 09, 01, 30, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1100 */ { 00, 02, 18, 0b0101010010100000 }, /* 29 30 29 30 29 30 29 29 30 29 30 29 353
+1101 */ { 00, 02, 07, 0b1101011001010000 }, /* 30 30 29 30 29 30 30 29 29 30 29 30 355
+1102 */ { 06, 01, 28, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1103 */ { 00, 02, 16, 0b0101010111010000 }, /* 29 30 29 30 29 30 29 30 30 30 29 30 355
+1104 */ { 00, 02, 06, 0b0010011011010000 }, /* 29 29 30 29 29 30 30 29 30 30 29 30 354
+1105 */ { 02, 01, 25, 0b1001001011101000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
+1106 */ { 00, 02, 13, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
+1107 */ { 10, 02, 02, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1108 */ { 00, 02, 21, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1109 */ { 00, 02, 09, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+1110 */ { 08, 01, 29, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1111 */ { 00, 02, 17, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+1112 */ { 00, 02, 07, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
+1113 */ { 04, 01, 27, 0b0010010110111000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
+1114 */ { 00, 02, 15, 0b0100010101110000 }, /* 29 30 29 29 29 30 29 30 29 30 30 30 354
+1115 */ { 00, 02, 04, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1116 */ { 01, 01, 24, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1117 */ { 00, 02, 11, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
+1118 */ { 09, 01, 31, 0b0111001010101000 }, /* 29 30 30 30 29 29 30 29 30 29 30 29 30 384
+1119 */ { 00, 02, 19, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1120 */ { 00, 02, 08, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1121 */ { 05, 01, 28, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1122 */ { 00, 02, 16, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+1123 */ { 00, 02, 05, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1124 */ { 03, 01, 26, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
+1125 */ { 00, 02, 12, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
+1126 */ { 11, 02, 01, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1127 */ { 00, 02, 20, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1128 */ { 00, 02, 10, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1129 */ { 08, 01, 29, 0b1001101110010000 }, /* 30 29 29 30 30 29 30 30 30 29 29 30 29 384
+1130 */ { 00, 02, 17, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+1131 */ { 00, 02, 07, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1132 */ { 04, 01, 27, 0b1010010011101000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
+1133 */ { 00, 02, 14, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1134 */ { 00, 02, 03, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+1135 */ { 02, 01, 23, 0b1101100100101000 }, /* 30 30 29 30 30 29 29 30 29 29 30 29 30 384
+1136 */ { 00, 02, 11, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
+1137 */ { 10, 01, 30, 0b1101011010101000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 30 385
+1138 */ { 00, 02, 19, 0b0010110110100000 }, /* 29 29 30 29 30 30 29 30 30 29 30 29 354
+1139 */ { 00, 02, 08, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
+1140 */ { 06, 01, 29, 0b0100101011011000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+1141 */ { 00, 02, 16, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1142 */ { 00, 02, 05, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1143 */ { 04, 01, 25, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1144 */ { 00, 02, 13, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
+1145 */ { 11, 02, 01, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1146 */ { 00, 02, 20, 0b0110101101000000 }, /* 29 30 30 29 30 29 30 30 29 30 29 29 354
+1147 */ { 00, 02, 09, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+1148 */ { 08, 01, 30, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
+1149 */ { 00, 02, 17, 0b1001100101110000 }, /* 30 29 29 30 30 29 29 30 29 30 30 30 355
+1150 */ { 00, 02, 07, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1151 */ { 04, 01, 27, 0b0110010010111000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
+1152 */ { 00, 02, 15, 0b0101010010110000 }, /* 29 30 29 30 29 30 29 29 30 29 30 30 354
+1153 */ { 12, 02, 03, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1154 */ { 00, 02, 21, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
+1155 */ { 00, 02, 11, 0b0101101011000000 }, /* 29 30 29 30 30 29 30 29 30 30 29 29 354
+1156 */ { 10, 01, 31, 0b1010101101101000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 30 385
+1157 */ { 00, 02, 19, 0b0010011011100000 }, /* 29 29 30 29 29 30 30 29 30 30 30 29 354
+1158 */ { 00, 02, 08, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1159 */ { 06, 01, 28, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
+1160 */ { 00, 02, 16, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+1161 */ { 00, 02, 04, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1162 */ { 02, 01, 24, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1163 */ { 00, 02, 12, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1164 */ { 11, 02, 02, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1165 */ { 00, 02, 20, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
+1166 */ { 00, 02, 10, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+1167 */ { 07, 01, 30, 0b1001001011101000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
+1168 */ { 00, 02, 18, 0b1001001001110000 }, /* 30 29 29 30 29 29 30 29 29 30 30 30 354
+1169 */ { 00, 02, 06, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1170 */ { 05, 01, 26, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1171 */ { 00, 02, 14, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+1172 */ { 00, 02, 03, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1173 */ { 01, 01, 23, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1174 */ { 00, 02, 11, 0b0100110110110000 }, /* 29 30 29 29 30 30 29 30 30 29 30 30 355
+1175 */ { 09, 02, 01, 0b0010010110110000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 29 383
+1176 */ { 00, 02, 19, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1177 */ { 00, 02, 08, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1178 */ { 06, 01, 28, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1179 */ { 00, 02, 16, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
+1180 */ { 00, 02, 05, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1181 */ { 03, 01, 24, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1182 */ { 00, 02, 12, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1183 */ { 11, 02, 02, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1184 */ { 00, 02, 21, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1185 */ { 00, 02, 09, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1186 */ { 07, 01, 30, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
+1187 */ { 00, 02, 17, 0b1101000010010000 }, /* 30 30 29 30 29 29 29 29 30 29 29 30 353
+1188 */ { 00, 01, 08, 0b0111010010011000 }, /* 29 30 30 30 29 30 29 29 30 29 29 30 354
+1189 */ { 05, 01, 26, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1190 */ { 00, 02, 14, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1191 */ { 00, 02, 03, 0b1001101101010000 }, /* 30 29 29 30 30 29 30 30 29 30 29 30 355
+1192 */ { 02, 01, 24, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1193 */ { 00, 02, 11, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1194 */ { 10, 01, 31, 0b1010010011101000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
+1195 */ { 00, 02, 19, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1196 */ { 00, 02, 08, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
+1197 */ { 06, 01, 27, 0b1101010100101000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1198 */ { 00, 02, 15, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
+1199 */ { 00, 02, 04, 0b1101011010100000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 355
+1200 */ { 02, 01, 25, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1201 */ { 00, 02, 12, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
+1202 */ { 12, 02, 02, 0b0100100111011000 }, /* 29 30 29 29 30 29 29 30 30 30 29 30 30 384
+1203 */ { 00, 02, 21, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1204 */ { 00, 02, 10, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1205 */ { 08, 01, 29, 0b1010101001011000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 30 384
+1206 */ { 00, 02, 17, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
+1207 */ { 00, 02, 06, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
+1208 */ { 04, 01, 26, 0b1011010110100000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 29 384
+1209 */ { 00, 02, 13, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+1210 */ { 00, 02, 03, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1211 */ { 02, 01, 24, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1212 */ { 00, 02, 12, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1213 */ { 09, 01, 31, 0b0110010010111000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
+1214 */ { 00, 02, 19, 0b0101010010110000 }, /* 29 30 29 30 29 30 29 29 30 29 30 30 354
+1215 */ { 00, 02, 08, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
+1216 */ { 07, 01, 28, 0b0110110100101000 }, /* 29 30 30 29 30 30 29 30 29 29 30 29 30 384
+1217 */ { 00, 02, 15, 0b0101101011000000 }, /* 29 30 29 30 30 29 30 29 30 30 29 29 354
+1218 */ { 00, 02, 04, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+1219 */ { 03, 01, 25, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1220 */ { 00, 02, 13, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1221 */ { 12, 02, 01, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
+1222 */ { 00, 02, 20, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+1223 */ { 00, 02, 09, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1224 */ { 08, 01, 29, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1225 */ { 00, 02, 16, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1226 */ { 00, 02, 06, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1227 */ { 05, 01, 26, 0b1010101011011000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+1228 */ { 00, 02, 15, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+1229 */ { 00, 02, 03, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1230 */ { 02, 01, 23, 0b1100100101011000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+1231 */ { 00, 02, 11, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1232 */ { 09, 01, 31, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1233 */ { 00, 02, 18, 0b1011001010100000 }, /* 30 29 30 30 29 29 30 29 30 29 30 29 354
+1234 */ { 00, 02, 07, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1235 */ { 07, 01, 28, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1236 */ { 00, 02, 16, 0b0100110110100000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 354
+1237 */ { 00, 02, 04, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
+1238 */ { 04, 01, 25, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1239 */ { 00, 02, 13, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1240 */ { 12, 02, 02, 0b1010100100111000 }, /* 30 29 30 29 30 29 29 30 29 29 30 30 30 384
+1241 */ { 00, 02, 20, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 354
+1242 */ { 00, 02, 09, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1243 */ { 08, 01, 29, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1244 */ { 00, 02, 17, 0b1010111001010000 }, /* 30 29 30 29 30 30 30 29 29 30 29 30 355
+1245 */ { 00, 02, 06, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+1246 */ { 04, 01, 26, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1247 */ { 00, 02, 14, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1248 */ { 00, 02, 04, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 354
+1249 */ { 02, 01, 23, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
+1250 */ { 00, 02, 10, 0b1110010100110000 }, /* 30 30 30 29 29 30 29 30 29 29 30 30 355
+1251 */ { 10, 01, 31, 0b0110110010011000 }, /* 29 30 30 29 30 30 29 29 30 29 29 30 30 384
+1252 */ { 00, 02, 19, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1253 */ { 00, 02, 07, 0b0101101011010000 }, /* 29 30 29 30 30 29 30 29 30 30 29 30 355
+1254 */ { 06, 01, 28, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1255 */ { 00, 02, 16, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1256 */ { 00, 02, 05, 0b1010010011100000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 354
+1257 */ { 04, 01, 24, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1258 */ { 00, 02, 12, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
+1259 */ { 11, 02, 01, 0b1101010100101000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1260 */ { 00, 02, 20, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
+1261 */ { 00, 02, 08, 0b1011011010100000 }, /* 30 29 30 30 29 30 30 29 30 29 30 29 355
+1262 */ { 09, 01, 29, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1263 */ { 00, 02, 17, 0b0101010101110000 }, /* 29 30 29 30 29 30 29 30 29 30 30 30 355
+1264 */ { 00, 02, 07, 0b0100100111010000 }, /* 29 30 29 29 30 29 29 30 30 30 29 30 354
+1265 */ { 05, 01, 26, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1266 */ { 00, 02, 14, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1267 */ { 00, 02, 03, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
+1268 */ { 01, 01, 23, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1269 */ { 00, 02, 10, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
+1270 */ { 11, 01, 30, 0b1011010111000000 }, /* 30 29 30 30 29 30 29 30 30 30 29 29 29 384
+1271 */ { 00, 02, 18, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+1272 */ { 00, 02, 08, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1273 */ { 06, 01, 28, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1274 */ { 00, 02, 16, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1275 */ { 00, 02, 05, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1276 */ { 03, 01, 25, 0b0110101001011000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 30 384
+1277 */ { 00, 02, 12, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
+1278 */ { 11, 02, 01, 0b0110101100101000 }, /* 29 30 30 29 30 29 30 30 29 29 30 29 30 384
+1279 */ { 00, 02, 20, 0b0101101011000000 }, /* 29 30 29 30 30 29 30 29 30 30 29 29 354
+1280 */ { 00, 02, 09, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+1281 */ { 08, 01, 29, 0b0010101011101000 }, /* 29 29 30 29 30 29 30 29 30 30 30 29 30 384
+1282 */ { 00, 02, 17, 0b0100100111100000 }, /* 29 30 29 29 30 29 29 30 30 30 30 29 354
+1283 */ { 00, 02, 06, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1284 */ { 05, 01, 26, 0b1101001001011000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
+1285 */ { 00, 02, 13, 0b1011001001010000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 354
+1286 */ { 00, 02, 02, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
+1287 */ { 02, 01, 22, 0b1111001010010000 }, /* 30 30 30 30 29 29 30 29 30 29 29 30 29 384
+1288 */ { 00, 02, 10, 0b1011010110100000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 355
+1289 */ { 10, 01, 30, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
+1290 */ { 00, 02, 18, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1291 */ { 00, 02, 08, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1292 */ { 06, 01, 28, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1293 */ { 00, 02, 15, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1294 */ { 00, 02, 04, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
+1295 */ { 04, 01, 24, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1296 */ { 00, 02, 12, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
+1297 */ { 12, 01, 31, 0b1010110101100000 }, /* 30 29 30 29 30 30 29 30 29 30 30 29 29 384
+1298 */ { 00, 02, 19, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+1299 */ { 00, 02, 09, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
+1300 */ { 08, 01, 30, 0b0000100101111000 }, /* 29 29 29 29 30 29 29 30 29 30 30 30 30 383
+1301 */ { 00, 02, 18, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1302 */ { 00, 02, 07, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1303 */ { 05, 01, 27, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1304 */ { 00, 02, 14, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
+1305 */ { 00, 02, 03, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1306 */ { 01, 01, 23, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
+1307 */ { 00, 02, 11, 0b1010011011100000 }, /* 30 29 30 29 29 30 30 29 30 30 30 29 355
+1308 */ { 11, 02, 01, 0b1001001011101000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
+1309 */ { 00, 02, 19, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1310 */ { 00, 02, 08, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+1311 */ { 07, 01, 28, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1312 */ { 00, 02, 16, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1313 */ { 00, 02, 04, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1314 */ { 03, 01, 25, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1315 */ { 00, 02, 13, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1316 */ { 00, 02, 02, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 355
+1317 */ { 01, 01, 22, 0b1001001011101000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
+1318 */ { 00, 02, 10, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
+1319 */ { 08, 01, 30, 0b1010010101011000 }, /* 30 29 30 29 29 30 29 30 29 30 29 30 30 384
+1320 */ { 00, 02, 18, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1321 */ { 00, 02, 06, 0b1011001010100000 }, /* 30 29 30 30 29 29 30 29 30 29 30 29 354
+1322 */ { 05, 01, 26, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1323 */ { 00, 02, 14, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+1324 */ { 00, 02, 04, 0b0100110110100000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 354
+1325 */ { 01, 01, 23, 0b1010010111010000 }, /* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
+1326 */ { 00, 02, 11, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1327 */ { 09, 02, 01, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1328 */ { 00, 02, 20, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 354
+1329 */ { 00, 02, 08, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 354
+1330 */ { 07, 01, 28, 0b0110101010011000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
+1331 */ { 00, 02, 16, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1332 */ { 00, 02, 05, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1333 */ { 03, 01, 25, 0b0100101110101000 }, /* 29 30 29 29 30 29 30 30 30 29 30 29 30 384
+1334 */ { 00, 02, 13, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+1335 */ { 12, 02, 02, 0b1010011001110000 }, /* 30 29 30 29 29 30 30 29 29 30 30 30 29 384
+1336 */ { 00, 02, 21, 0b1010001011100000 }, /* 30 29 30 29 29 29 30 29 30 30 30 29 354
+1337 */ { 00, 02, 09, 0b1101000101100000 }, /* 30 30 29 30 29 29 29 30 29 30 30 29 354
+1338 */ { 08, 01, 29, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1339 */ { 00, 02, 17, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1340 */ { 00, 02, 06, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 355
+1341 */ { 05, 01, 26, 0b0101101101010000 }, /* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
+1342 */ { 00, 02, 14, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+1343 */ { 00, 02, 04, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1344 */ { 02, 01, 24, 0b1010001011101000 }, /* 30 29 30 29 29 29 30 29 30 30 30 29 30 384
+1345 */ { 00, 02, 11, 0b1010001011010000 }, /* 30 29 30 29 29 29 30 29 30 30 29 30 354
+1346 */ { 10, 01, 31, 0b1101000101011000 }, /* 30 30 29 30 29 29 29 30 29 30 29 30 30 384
+1347 */ { 00, 02, 19, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
+1348 */ { 00, 02, 08, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
+1349 */ { 07, 01, 27, 0b1101011010100000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 29 384
+1350 */ { 00, 02, 15, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
+1351 */ { 00, 02, 05, 0b0101010111010000 }, /* 29 30 29 30 29 30 29 30 30 30 29 30 355
+1352 */ { 03, 01, 26, 0b0100100111011000 }, /* 29 30 29 29 30 29 29 30 30 30 29 30 30 384
+1353 */ { 00, 02, 13, 0b0100010110110000 }, /* 29 30 29 29 29 30 29 30 30 29 30 30 354
+1354 */ { 00, 02, 02, 0b1010001010110000 }, /* 30 29 30 29 29 29 30 29 30 29 30 30 354
+1355 */ { 01, 01, 22, 0b1101000101011000 }, /* 30 30 29 30 29 29 29 30 29 30 29 30 30 384
+1356 */ { 00, 02, 10, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
+1357 */ { 09, 01, 29, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1358 */ { 00, 02, 17, 0b0110101100100000 }, /* 29 30 30 29 30 29 30 30 29 29 30 29 354
+1359 */ { 00, 02, 06, 0b1010110101100000 }, /* 30 29 30 29 30 30 29 30 29 30 30 29 355
+1360 */ { 05, 01, 27, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1361 */ { 00, 02, 14, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
+1362 */ { 00, 02, 04, 0b0100010101110000 }, /* 29 30 29 29 29 30 29 30 29 30 30 30 354
+1363 */ { 03, 01, 24, 0b1010001010111000 }, /* 30 29 30 29 29 29 30 29 30 29 30 30 30 384
+1364 */ { 00, 02, 12, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1365 */ { 10, 01, 31, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 29 383
+1366 */ { 00, 02, 18, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
+1367 */ { 00, 02, 08, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1368 */ { 07, 01, 28, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
+1369 */ { 00, 02, 15, 0b1010011011100000 }, /* 30 29 30 29 29 30 30 29 30 30 30 29 355
+1370 */ { 00, 02, 05, 0b0101001011100000 }, /* 29 30 29 30 29 29 30 29 30 30 30 29 354
+1371 */ { 03, 01, 25, 0b1100010101110000 }, /* 30 30 29 29 29 30 29 30 29 30 30 30 29 384
+1372 */ { 00, 02, 13, 0b1010010101100000 }, /* 30 29 30 29 29 30 29 30 29 30 30 29 354
+1373 */ { 11, 02, 01, 0b1101001010101000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
+1374 */ { 00, 02, 20, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
+1375 */ { 00, 02, 09, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1376 */ { 09, 01, 30, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1377 */ { 00, 02, 17, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1378 */ { 00, 02, 06, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 355
+1379 */ { 05, 01, 27, 0b0101001011101000 }, /* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
+1380 */ { 00, 02, 15, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1381 */ { 00, 02, 03, 0b1010100011010000 }, /* 30 29 30 29 30 29 29 29 30 30 29 30 354
+1382 */ { 02, 01, 23, 0b1101001010101000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
+1383 */ { 00, 02, 11, 0b1011001010100000 }, /* 30 29 30 30 29 29 30 29 30 29 30 29 354
+1384 */ { 10, 01, 31, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1385 */ { 00, 02, 18, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+1386 */ { 00, 02, 08, 0b0100110110100000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 354
+1387 */ { 06, 01, 28, 0b1010010111010000 }, /* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
+1388 */ { 00, 02, 16, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1389 */ { 00, 02, 05, 0b0101000110110000 }, /* 29 30 29 30 29 29 29 30 30 29 30 30 354
+1390 */ { 04, 01, 25, 0b1010100010111000 }, /* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
+1391 */ { 00, 02, 13, 0b0110010100110000 }, /* 29 30 30 29 29 30 29 30 29 29 30 30 354
+1392 */ { 12, 02, 02, 0b0110101010011000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
+1393 */ { 00, 02, 20, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1394 */ { 00, 02, 09, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1395 */ { 09, 01, 30, 0b0010101110101000 }, /* 29 29 30 29 30 29 30 30 30 29 30 29 30 384
+1396 */ { 00, 02, 18, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1397 */ { 00, 02, 06, 0b1100001101110000 }, /* 30 30 29 29 29 29 30 30 29 30 30 30 355
+1398 */ { 05, 01, 27, 0b0101000101110000 }, /* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
+1399 */ { 00, 02, 14, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+1400 */ { 00, 02, 03, 0b1110010010110000 }, /* 30 30 30 29 29 30 29 29 30 29 30 30 355
+1401 */ { 03, 01, 24, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
+1402 */ { 00, 02, 11, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 355
+1403 */ { 11, 02, 01, 0b0101101101010000 }, /* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
+1404 */ { 00, 02, 20, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+1405 */ { 00, 02, 09, 0b0010101011100000 }, /* 29 29 30 29 30 29 30 29 30 30 30 29 354
+1406 */ { 07, 01, 29, 0b1010001011101000 }, /* 30 29 30 29 29 29 30 29 30 30 30 29 30 384
+1407 */ { 00, 02, 17, 0b1010001011010000 }, /* 30 29 30 29 29 29 30 29 30 30 29 30 354
+1408 */ { 00, 02, 06, 0b1101000101010000 }, /* 30 30 29 30 29 29 29 30 29 30 29 30 354
+1409 */ { 04, 01, 25, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1410 */ { 00, 02, 13, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
+1411 */ { 12, 02, 02, 0b1011011010010000 }, /* 30 29 30 30 29 30 30 29 30 29 29 30 29 384
+1412 */ { 00, 02, 21, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
+1413 */ { 00, 02, 10, 0b0101010111010000 }, /* 29 30 29 30 29 30 29 30 30 30 29 30 355
+1414 */ { 09, 01, 31, 0b0010010111011000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 30 384
+1415 */ { 00, 02, 19, 0b0100010110110000 }, /* 29 30 29 29 29 30 29 30 30 29 30 30 354
+1416 */ { 00, 02, 08, 0b1010001010110000 }, /* 30 29 30 29 29 29 30 29 30 29 30 30 354
+1417 */ { 05, 01, 27, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1418 */ { 00, 02, 15, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1419 */ { 00, 02, 04, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
+1420 */ { 01, 01, 24, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1421 */ { 00, 02, 11, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+1422 */ { 12, 02, 01, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1423 */ { 00, 02, 20, 0b0100101101110000 }, /* 29 30 29 29 30 29 30 30 29 30 30 30 355
+1424 */ { 00, 02, 10, 0b0100010101110000 }, /* 29 30 29 29 29 30 29 30 29 30 30 30 354
+1425 */ { 07, 01, 29, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1426 */ { 00, 02, 17, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1427 */ { 00, 02, 06, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
+1428 */ { 04, 01, 26, 0b0110110010101000 }, /* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
+1429 */ { 00, 02, 13, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1430 */ { 12, 02, 02, 0b1001101101010000 }, /* 30 29 29 30 30 29 30 30 29 30 29 30 29 384
+1431 */ { 00, 02, 21, 0b1010011011100000 }, /* 30 29 30 29 29 30 30 29 30 30 30 29 355
+1432 */ { 00, 02, 11, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1433 */ { 08, 01, 30, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1434 */ { 00, 02, 18, 0b1010010101100000 }, /* 30 29 30 29 29 30 29 30 29 30 30 29 354
+1435 */ { 00, 02, 07, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
+1436 */ { 06, 01, 27, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
+1437 */ { 00, 02, 14, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1438 */ { 00, 02, 04, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1439 */ { 02, 01, 24, 0b1010101011010000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 29 384
+1440 */ { 00, 02, 12, 0b1001010111100000 }, /* 30 29 29 30 29 30 29 30 30 30 30 29 355
+1441 */ { 11, 02, 01, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1442 */ { 00, 02, 20, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1443 */ { 00, 02, 09, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1444 */ { 07, 01, 29, 0b1101001001110000 }, /* 30 30 29 30 29 29 30 29 29 30 30 30 29 384
+1445 */ { 00, 02, 16, 0b1011001010100000 }, /* 30 29 30 30 29 29 30 29 30 29 30 29 354
+1446 */ { 00, 02, 05, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1447 */ { 04, 01, 26, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1448 */ { 00, 02, 14, 0b0010110110100000 }, /* 29 29 30 29 30 30 29 30 30 29 30 29 354
+1449 */ { 00, 02, 02, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1450 */ { 01, 01, 23, 0b0100101010111000 }, /* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
+1451 */ { 00, 02, 11, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1452 */ { 09, 01, 31, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1453 */ { 00, 02, 18, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1454 */ { 00, 02, 07, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 354
+1455 */ { 06, 01, 27, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1456 */ { 00, 02, 15, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 355
+1457 */ { 00, 02, 04, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1458 */ { 02, 01, 24, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
+1459 */ { 00, 02, 12, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
+1460 */ { 11, 02, 02, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
+1461 */ { 00, 02, 19, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+1462 */ { 00, 02, 08, 0b1110010010110000 }, /* 30 30 30 29 29 30 29 29 30 29 30 30 355
+1463 */ { 07, 01, 29, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
+1464 */ { 00, 02, 16, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 355
+1465 */ { 00, 02, 05, 0b0101101011010000 }, /* 29 30 29 30 30 29 30 29 30 30 29 30 355
+1466 */ { 03, 01, 26, 0b0010101101101000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
+1467 */ { 00, 02, 14, 0b0010011011100000 }, /* 29 29 30 29 29 30 30 29 30 30 30 29 354
+1468 */ { 00, 02, 03, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1469 */ { 02, 01, 22, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1470 */ { 00, 02, 10, 0b1100100101010000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 354
+1471 */ { 09, 01, 30, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1472 */ { 00, 02, 18, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+1473 */ { 00, 02, 06, 0b1011011010010000 }, /* 30 29 30 30 29 30 30 29 30 29 29 30 355
+1474 */ { 06, 01, 27, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1475 */ { 00, 02, 15, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
+1476 */ { 00, 02, 05, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+1477 */ { 02, 01, 24, 0b1001001011011000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
+1478 */ { 00, 02, 12, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
+1479 */ { 10, 02, 01, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1480 */ { 00, 02, 20, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
+1481 */ { 00, 02, 08, 0b0111010010100000 }, /* 29 30 30 30 29 30 29 29 30 29 30 29 354
+1482 */ { 08, 01, 28, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1483 */ { 00, 02, 16, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 355
+1484 */ { 00, 02, 06, 0b0101001110110000 }, /* 29 30 29 30 29 29 30 30 30 29 30 30 355
+1485 */ { 04, 01, 26, 0b0010010110111000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
+1486 */ { 00, 02, 14, 0b0010010101110000 }, /* 29 29 30 29 29 30 29 30 29 30 30 30 354
+1487 */ { 00, 02, 03, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1488 */ { 01, 01, 23, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1489 */ { 00, 02, 10, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
+1490 */ { 09, 01, 30, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1491 */ { 00, 02, 18, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1492 */ { 00, 02, 07, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1493 */ { 05, 01, 27, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1494 */ { 00, 02, 15, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1495 */ { 00, 02, 04, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1496 */ { 03, 01, 25, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
+1497 */ { 00, 02, 11, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
+1498 */ { 11, 01, 31, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 29 384
+1499 */ { 00, 02, 19, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1500 */ { 00, 02, 09, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1501 */ { 07, 01, 29, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1502 */ { 00, 02, 17, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
+1503 */ { 00, 02, 07, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1504 */ { 04, 01, 27, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1505 */ { 00, 02, 14, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1506 */ { 00, 02, 03, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+1507 */ { 01, 01, 23, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 29 384
+1508 */ { 00, 02, 11, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1509 */ { 09, 01, 31, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1510 */ { 00, 02, 19, 0b0010110110100000 }, /* 29 29 30 29 30 30 29 30 30 29 30 29 354
+1511 */ { 00, 02, 08, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1512 */ { 05, 01, 29, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1513 */ { 00, 02, 16, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1514 */ { 00, 02, 05, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1515 */ { 04, 01, 25, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1516 */ { 00, 02, 13, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 354
+1517 */ { 12, 02, 01, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1518 */ { 00, 02, 20, 0b0101101101010000 }, /* 29 30 29 30 30 29 30 30 29 30 29 30 355
+1519 */ { 00, 02, 10, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1520 */ { 08, 01, 30, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
+1521 */ { 00, 02, 17, 0b1001001011110000 }, /* 30 29 29 30 29 29 30 29 30 30 30 30 355
+1522 */ { 00, 02, 07, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1523 */ { 04, 01, 27, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1524 */ { 00, 02, 14, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1525 */ { 12, 02, 02, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 29 384
+1526 */ { 00, 02, 21, 0b1101011010010000 }, /* 30 30 29 30 29 30 30 29 30 29 29 30 355
+1527 */ { 00, 02, 11, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+1528 */ { 10, 02, 01, 0b0010101101101000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
+1529 */ { 00, 02, 19, 0b0010011011100000 }, /* 29 29 30 29 29 30 30 29 30 30 30 29 354
+1530 */ { 00, 02, 08, 0b0101001011100000 }, /* 29 30 29 30 29 29 30 29 30 30 30 29 354
+1531 */ { 06, 01, 28, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1532 */ { 00, 02, 16, 0b1100100101010000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 354
+1533 */ { 00, 02, 04, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1534 */ { 02, 01, 24, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1535 */ { 00, 02, 12, 0b1011010110010000 }, /* 30 29 30 30 29 30 29 30 30 29 29 30 355
+1536 */ { 12, 02, 02, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1537 */ { 00, 02, 20, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
+1538 */ { 00, 02, 10, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+1539 */ { 07, 01, 30, 0b1001001011011000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
+1540 */ { 00, 02, 18, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
+1541 */ { 00, 02, 06, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1542 */ { 05, 01, 26, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+1543 */ { 00, 02, 14, 0b0110110010100000 }, /* 29 30 30 29 30 30 29 29 30 29 30 29 354
+1544 */ { 00, 02, 03, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+1545 */ { 01, 01, 23, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1546 */ { 00, 02, 11, 0b0100101110110000 }, /* 29 30 29 29 30 29 30 30 30 29 30 30 355
+1547 */ { 09, 02, 01, 0b0010010110111000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
+1548 */ { 00, 02, 20, 0b0010010101110000 }, /* 29 29 30 29 29 30 29 30 29 30 30 30 354
+1549 */ { 00, 02, 08, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1550 */ { 06, 01, 28, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
+1551 */ { 00, 02, 15, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 355
+1552 */ { 00, 02, 05, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1553 */ { 03, 01, 24, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1554 */ { 00, 02, 12, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1555 */ { 11, 02, 02, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1556 */ { 00, 02, 21, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1557 */ { 00, 02, 09, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1558 */ { 07, 01, 30, 0b0101001001101000 }, /* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
+1559 */ { 00, 02, 17, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
+1560 */ { 00, 02, 06, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
+1561 */ { 05, 01, 26, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1562 */ { 00, 02, 14, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1563 */ { 00, 02, 03, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+1564 */ { 02, 01, 24, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1565 */ { 00, 02, 11, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1566 */ { 10, 01, 31, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1567 */ { 00, 02, 19, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1568 */ { 00, 02, 08, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+1569 */ { 06, 01, 27, 0b1101010101001000 }, /* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
+1570 */ { 00, 02, 15, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1571 */ { 00, 02, 05, 0b0011010110100000 }, /* 29 29 30 30 29 30 29 30 30 29 30 29 354
+1572 */ { 02, 01, 25, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
+1573 */ { 00, 02, 12, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1574 */ { 12, 02, 02, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1575 */ { 00, 02, 21, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1576 */ { 00, 02, 10, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1577 */ { 08, 01, 29, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1578 */ { 00, 02, 17, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
+1579 */ { 00, 02, 06, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
+1580 */ { 04, 01, 26, 0b1010110110101000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
+1581 */ { 00, 02, 14, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1582 */ { 00, 02, 03, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
+1583 */ { 02, 01, 24, 0b0100100101111000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+1584 */ { 00, 02, 12, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1585 */ { 09, 01, 31, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1586 */ { 00, 02, 18, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1587 */ { 00, 02, 07, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
+1588 */ { 06, 01, 28, 0b0110101101001000 }, /* 29 30 30 29 30 29 30 30 29 30 29 29 30 384
+1589 */ { 00, 02, 15, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+1590 */ { 00, 02, 05, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1591 */ { 03, 01, 25, 0b1001001011110000 }, /* 30 29 29 30 29 29 30 29 30 30 30 30 29 384
+1592 */ { 00, 02, 13, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1593 */ { 11, 02, 01, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1594 */ { 00, 02, 20, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1595 */ { 00, 02, 09, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1596 */ { 08, 01, 29, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1597 */ { 00, 02, 16, 0b1011010011010000 }, /* 30 29 30 30 29 30 29 29 30 30 29 30 355
+1598 */ { 00, 02, 06, 0b0101011010110000 }, /* 29 30 29 30 29 30 30 29 30 29 30 30 355
+1599 */ { 04, 01, 27, 0b0010011011011000 }, /* 29 29 30 29 29 30 30 29 30 30 29 30 30 384
+1600 */ { 00, 02, 15, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+1601 */ { 00, 02, 03, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
+1602 */ { 02, 01, 23, 0b1100100110011000 }, /* 30 30 29 29 30 29 29 30 30 29 29 30 30 384
+1603 */ { 00, 02, 11, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1604 */ { 09, 01, 31, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+1605 */ { 00, 02, 18, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1606 */ { 00, 02, 07, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+1607 */ { 06, 01, 28, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+1608 */ { 00, 02, 16, 0b0100101110110000 }, /* 29 30 29 29 30 29 30 30 30 29 30 30 355
+1609 */ { 00, 02, 05, 0b0010010110110000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 354
+1610 */ { 03, 01, 25, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1611 */ { 00, 02, 13, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1612 */ { 11, 02, 02, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
+1613 */ { 00, 02, 19, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 355
+1614 */ { 00, 02, 09, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1615 */ { 08, 01, 29, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1616 */ { 00, 02, 17, 0b1001101101010000 }, /* 30 29 29 30 30 29 30 30 29 30 29 30 355
+1617 */ { 00, 02, 06, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+1618 */ { 04, 01, 26, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1619 */ { 00, 02, 14, 0b1010010011110000 }, /* 30 29 30 29 29 30 29 29 30 30 30 30 355
+1620 */ { 00, 02, 04, 0b0101001001100000 }, /* 29 30 29 30 29 29 30 29 29 30 30 29 353
+1621 */ { 02, 01, 22, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1622 */ { 00, 02, 10, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1623 */ { 10, 01, 31, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1624 */ { 00, 02, 19, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1625 */ { 00, 02, 07, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+1626 */ { 06, 01, 28, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1627 */ { 00, 02, 16, 0b0100100111100000 }, /* 29 30 29 29 30 29 29 30 30 30 30 29 354
+1628 */ { 00, 02, 05, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1629 */ { 04, 01, 24, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1630 */ { 00, 02, 12, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+1631 */ { 11, 02, 01, 0b1101010100101000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1632 */ { 00, 02, 20, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
+1633 */ { 00, 02, 08, 0b1011010110100000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 355
+1634 */ { 08, 01, 29, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
+1635 */ { 00, 02, 17, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1636 */ { 00, 02, 07, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1637 */ { 04, 01, 26, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1638 */ { 00, 02, 14, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1639 */ { 00, 02, 03, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
+1640 */ { 01, 01, 23, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1641 */ { 00, 02, 10, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
+1642 */ { 11, 01, 30, 0b1010110110101000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
+1643 */ { 00, 02, 19, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1644 */ { 00, 02, 08, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
+1645 */ { 06, 01, 28, 0b0100100101111000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+1646 */ { 00, 02, 16, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1647 */ { 00, 02, 05, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1648 */ { 03, 01, 25, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1649 */ { 00, 02, 11, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
+1650 */ { 11, 02, 01, 0b0110101101001000 }, /* 29 30 30 29 30 29 30 30 29 30 29 29 30 384
+1651 */ { 00, 02, 20, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+1652 */ { 00, 02, 10, 0b0010101110100000 }, /* 29 29 30 29 30 29 30 30 30 29 30 29 354
+1653 */ { 07, 01, 29, 0b1001001011110000 }, /* 30 29 29 30 29 29 30 29 30 30 30 30 29 384
+1654 */ { 00, 02, 17, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1655 */ { 00, 02, 06, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+1656 */ { 05, 01, 26, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1657 */ { 00, 02, 13, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1658 */ { 00, 02, 02, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
+1659 */ { 03, 01, 23, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1660 */ { 00, 02, 11, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1661 */ { 07, 01, 30, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 29 384
+1662 */ { 00, 02, 18, 0b1010010111010000 }, /* 30 29 30 29 29 30 29 30 30 30 29 30 355
+1663 */ { 00, 02, 08, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
+1664 */ { 06, 01, 28, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1665 */ { 00, 02, 15, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1666 */ { 00, 02, 04, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+1667 */ { 04, 01, 24, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1668 */ { 00, 02, 12, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+1669 */ { 00, 02, 01, 0b0101010110100000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 354
+1670 */ { 02, 01, 21, 0b1010010111010000 }, /* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
+1671 */ { 00, 02, 09, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
+1672 */ { 07, 01, 30, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1673 */ { 00, 02, 17, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1674 */ { 00, 02, 06, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 354
+1675 */ { 05, 01, 26, 0b0111010010101000 }, /* 29 30 30 30 29 30 29 29 30 29 30 29 30 384
+1676 */ { 00, 02, 14, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1677 */ { 00, 02, 02, 0b1010110110010000 }, /* 30 29 30 29 30 30 29 30 30 29 29 30 355
+1678 */ { 03, 01, 23, 0b0100110110101000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+1679 */ { 00, 02, 11, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+1680 */ { 08, 01, 31, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1681 */ { 00, 02, 18, 0b1010010011100000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 354
+1682 */ { 00, 02, 07, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
+1683 */ { 06, 01, 27, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1684 */ { 00, 02, 15, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
+1685 */ { 00, 02, 03, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 355
+1686 */ { 04, 01, 24, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+1687 */ { 00, 02, 12, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+1688 */ { 00, 02, 02, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1689 */ { 03, 01, 21, 0b1010010011101000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
+1690 */ { 00, 02, 09, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1691 */ { 07, 01, 29, 0b1101001001011000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
+1692 */ { 00, 02, 17, 0b1011001001010000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 354
+1693 */ { 00, 02, 05, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
+1694 */ { 05, 01, 25, 0b1101011010100000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 29 384
+1695 */ { 00, 02, 13, 0b1011010110100000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 355
+1696 */ { 00, 02, 03, 0b0101010111010000 }, /* 29 30 29 30 29 30 29 30 30 30 29 30 355
+1697 */ { 03, 01, 23, 0b0100101011011000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+1698 */ { 00, 02, 11, 0b0100100111010000 }, /* 29 30 29 29 30 29 29 30 30 30 29 30 354
+1699 */ { 07, 01, 31, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1700 */ { 00, 02, 19, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1701 */ { 00, 02, 08, 0b1010101001010000 }, /* 30 29 30 29 30 29 30 29 29 30 29 30 354
+1702 */ { 06, 01, 28, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1703 */ { 00, 02, 16, 0b0110110100100000 }, /* 29 30 30 29 30 30 29 30 29 29 30 29 354
+1704 */ { 00, 02, 05, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
+1705 */ { 04, 01, 25, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1706 */ { 00, 02, 13, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
+1707 */ { 00, 02, 03, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1708 */ { 03, 01, 23, 0b0110010010111000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
+1709 */ { 00, 02, 10, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1710 */ { 07, 01, 30, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1711 */ { 00, 02, 17, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
+1712 */ { 00, 02, 07, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1713 */ { 05, 01, 26, 0b1010101101100000 }, /* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
+1714 */ { 00, 02, 14, 0b1010101011100000 }, /* 30 29 30 29 30 29 30 29 30 30 30 29 355
+1715 */ { 00, 02, 04, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1716 */ { 03, 01, 24, 0b1100100101110000 }, /* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
+1717 */ { 00, 02, 11, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+1718 */ { 08, 01, 31, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1719 */ { 00, 02, 19, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1720 */ { 00, 02, 08, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1721 */ { 06, 01, 28, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1722 */ { 00, 02, 16, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1723 */ { 00, 02, 05, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 355
+1724 */ { 04, 01, 26, 0b0101001011101000 }, /* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
+1725 */ { 00, 02, 13, 0b0101001011010000 }, /* 29 30 29 30 29 29 30 29 30 30 29 30 354
+1726 */ { 00, 02, 02, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1727 */ { 03, 01, 22, 0b1110010010101000 }, /* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
+1728 */ { 00, 02, 10, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+1729 */ { 07, 01, 29, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1730 */ { 00, 02, 17, 0b1001110101010000 }, /* 30 29 29 30 30 30 29 30 29 30 29 30 355
+1731 */ { 00, 02, 07, 0b0101010110100000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 354
+1732 */ { 05, 01, 27, 0b1010010111010000 }, /* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
+1733 */ { 00, 02, 14, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
+1734 */ { 00, 02, 04, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1735 */ { 04, 01, 24, 0b1010100010111000 }, /* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
+1736 */ { 00, 02, 12, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 354
+1737 */ { 09, 01, 31, 0b0110101010011000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
+1738 */ { 00, 02, 19, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1739 */ { 00, 02, 08, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1740 */ { 06, 01, 29, 0b0100110110101000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+1741 */ { 00, 02, 16, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+1742 */ { 00, 02, 05, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1743 */ { 04, 01, 26, 0b0101000101110000 }, /* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
+1744 */ { 00, 02, 13, 0b1101000101100000 }, /* 30 30 29 30 29 29 29 30 29 30 30 29 354
+1745 */ { 00, 02, 01, 0b1110100100110000 }, /* 30 30 30 29 30 29 29 30 29 29 30 30 355
+1746 */ { 03, 01, 22, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
+1747 */ { 00, 02, 09, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 355
+1748 */ { 07, 01, 30, 0b0101101101010000 }, /* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
+1749 */ { 00, 02, 17, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+1750 */ { 00, 02, 07, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1751 */ { 05, 01, 27, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1752 */ { 00, 02, 15, 0b1010001011010000 }, /* 30 29 30 29 29 29 30 29 30 30 29 30 354
+1753 */ { 00, 02, 03, 0b1101000101010000 }, /* 30 30 29 30 29 29 29 30 29 30 29 30 354
+1754 */ { 04, 01, 23, 0b1101010100101000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1755 */ { 00, 02, 11, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
+1756 */ { 09, 01, 31, 0b1101011010010000 }, /* 30 30 29 30 29 30 30 29 30 29 29 30 29 384
+1757 */ { 00, 02, 18, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
+1758 */ { 00, 02, 08, 0b0101010111010000 }, /* 29 30 29 30 29 30 29 30 30 30 29 30 355
+1759 */ { 06, 01, 29, 0b0010101011011000 }, /* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
+1760 */ { 00, 02, 17, 0b0100010110110000 }, /* 29 30 29 29 29 30 29 30 30 29 30 30 354
+1761 */ { 00, 02, 05, 0b1010001010110000 }, /* 30 29 30 29 29 29 30 29 30 29 30 30 354
+1762 */ { 05, 01, 25, 0b1011000101011000 }, /* 30 29 30 30 29 29 29 30 29 30 29 30 30 384
+1763 */ { 00, 02, 13, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1764 */ { 00, 02, 02, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
+1765 */ { 02, 01, 21, 0b1011010110010000 }, /* 30 29 30 30 29 30 29 30 30 29 29 30 29 384
+1766 */ { 00, 02, 09, 0b1010110101100000 }, /* 30 29 30 29 30 30 29 30 29 30 30 29 355
+1767 */ { 07, 01, 30, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1768 */ { 00, 02, 18, 0b0101001101110000 }, /* 29 30 29 30 29 29 30 30 29 30 30 30 355
+1769 */ { 00, 02, 07, 0b0100010101110000 }, /* 29 30 29 29 29 30 29 30 29 30 30 30 354
+1770 */ { 05, 01, 27, 0b0110001010111000 }, /* 29 30 30 29 29 29 30 29 30 29 30 30 30 384
+1771 */ { 00, 02, 15, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1772 */ { 00, 02, 04, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
+1773 */ { 03, 01, 23, 0b0110110010101000 }, /* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
+1774 */ { 00, 02, 11, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1775 */ { 10, 01, 31, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+1776 */ { 00, 02, 19, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 355
+1777 */ { 00, 02, 08, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1778 */ { 06, 01, 28, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
+1779 */ { 00, 02, 16, 0b1010010101100000 }, /* 30 29 30 29 29 30 29 30 29 30 30 29 354
+1780 */ { 00, 02, 05, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
+1781 */ { 05, 01, 24, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
+1782 */ { 00, 02, 12, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1783 */ { 00, 02, 02, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1784 */ { 03, 01, 22, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+1785 */ { 00, 02, 09, 0b1010011011010000 }, /* 30 29 30 29 29 30 30 29 30 30 29 30 355
+1786 */ { 07, 01, 30, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1787 */ { 00, 02, 18, 0b0100101010110000 }, /* 29 30 29 29 30 29 30 29 30 29 30 30 354
+1788 */ { 00, 02, 07, 0b1010100011010000 }, /* 30 29 30 29 30 29 29 29 30 30 29 30 354
+1789 */ { 05, 01, 26, 0b1101001010101000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
+1790 */ { 00, 02, 14, 0b1011001010100000 }, /* 30 29 30 30 29 29 30 29 30 29 30 29 354
+1791 */ { 00, 02, 03, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1792 */ { 04, 01, 24, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1793 */ { 00, 02, 11, 0b0100110110100000 }, /* 29 30 29 29 30 30 29 30 30 29 30 29 354
+1794 */ { 00, 01, 31, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
+1795 */ { 02, 01, 21, 0b0100101010111000 }, /* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
+1796 */ { 00, 02, 09, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1797 */ { 06, 01, 28, 0b1010100010111000 }, /* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
+1798 */ { 00, 02, 16, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1799 */ { 00, 02, 05, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 354
+1800 */ { 04, 01, 25, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1801 */ { 00, 02, 13, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 355
+1802 */ { 00, 02, 03, 0b0010101110100000 }, /* 29 29 30 29 30 29 30 30 30 29 30 29 354
+1803 */ { 02, 01, 23, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
+1804 */ { 00, 02, 11, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
+1805 */ { 06, 01, 31, 0b0101000101110000 }, /* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
+1806 */ { 00, 02, 18, 0b1101000101100000 }, /* 30 30 29 30 29 29 29 30 29 30 30 29 354
+1807 */ { 00, 02, 07, 0b1110010010110000 }, /* 30 30 30 29 29 30 29 29 30 29 30 30 355
+1808 */ { 05, 01, 28, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
+1809 */ { 00, 02, 14, 0b1101101010010000 }, /* 30 30 29 30 30 29 30 29 30 29 29 30 355
+1810 */ { 00, 02, 04, 0b0101101101010000 }, /* 29 30 29 30 30 29 30 30 29 30 29 30 355
+1811 */ { 03, 01, 25, 0b0010101101101000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
+1812 */ { 00, 02, 13, 0b0010101011100000 }, /* 29 29 30 29 30 29 30 29 30 30 30 29 354
+1813 */ { 00, 02, 01, 0b1010001011100000 }, /* 30 29 30 29 29 29 30 29 30 30 30 29 354
+1814 */ { 02, 01, 21, 0b1101000101101000 }, /* 30 30 29 30 29 29 29 30 29 30 30 29 30 384
+1815 */ { 00, 02, 09, 0b1100100101010000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 354
+1816 */ { 06, 01, 29, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1817 */ { 00, 02, 16, 0b1011010100100000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 354
+1818 */ { 00, 02, 05, 0b1011011010010000 }, /* 30 29 30 30 29 30 30 29 30 29 29 30 355
+1819 */ { 04, 01, 26, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1820 */ { 00, 02, 14, 0b0101010111010000 }, /* 29 30 29 30 29 30 29 30 30 30 29 30 355
+1821 */ { 00, 02, 03, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+1822 */ { 03, 01, 23, 0b1010001011011000 }, /* 30 29 30 29 29 29 30 29 30 30 29 30 30 384
+1823 */ { 00, 02, 11, 0b1010001010110000 }, /* 30 29 30 29 29 29 30 29 30 29 30 30 354
+1824 */ { 07, 01, 31, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1825 */ { 00, 02, 18, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1826 */ { 00, 02, 07, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+1827 */ { 05, 01, 27, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1828 */ { 00, 02, 15, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+1829 */ { 00, 02, 04, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
+1830 */ { 04, 01, 25, 0b0010010110111000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
+1831 */ { 00, 02, 13, 0b0010010101110000 }, /* 29 29 30 29 29 30 29 30 29 30 30 30 354
+1832 */ { 09, 02, 02, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1833 */ { 00, 02, 20, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1834 */ { 00, 02, 09, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
+1835 */ { 06, 01, 29, 0b0110110010101000 }, /* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
+1836 */ { 00, 02, 17, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1837 */ { 00, 02, 05, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1838 */ { 04, 01, 26, 0b0101001101101000 }, /* 29 30 29 30 29 29 30 30 29 30 30 29 30 384
+1839 */ { 00, 02, 14, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1840 */ { 00, 02, 03, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1841 */ { 03, 01, 23, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 29 383
+1842 */ { 00, 02, 10, 0b1101001010100000 }, /* 30 30 29 30 29 29 30 29 30 29 30 29 354
+1843 */ { 07, 01, 30, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
+1844 */ { 00, 02, 18, 0b1101010101010000 }, /* 30 30 29 30 29 30 29 30 29 30 29 30 355
+1845 */ { 00, 02, 07, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+1846 */ { 05, 01, 27, 0b1010101011010000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 29 384
+1847 */ { 00, 02, 15, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
+1848 */ { 00, 02, 05, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1849 */ { 04, 01, 24, 0b1010010101011000 }, /* 30 29 30 29 29 30 29 30 29 30 29 30 30 384
+1850 */ { 00, 02, 12, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1851 */ { 08, 02, 01, 0b1101001001011000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
+1852 */ { 00, 02, 20, 0b1011001010010000 }, /* 30 29 30 30 29 29 30 29 30 29 29 30 354
+1853 */ { 00, 02, 08, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1854 */ { 07, 01, 29, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1855 */ { 00, 02, 17, 0b0010110110100000 }, /* 29 29 30 29 30 30 29 30 30 29 30 29 354
+1856 */ { 00, 02, 06, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
+1857 */ { 05, 01, 26, 0b0100101010111000 }, /* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
+1858 */ { 00, 02, 14, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1859 */ { 00, 02, 03, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1860 */ { 03, 01, 23, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1861 */ { 00, 02, 10, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 354
+1862 */ { 08, 01, 30, 0b1010110101001000 }, /* 30 29 30 29 30 30 29 30 29 30 29 29 30 384
+1863 */ { 00, 02, 18, 0b0110101101010000 }, /* 29 30 30 29 30 29 30 30 29 30 29 30 355
+1864 */ { 00, 02, 08, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1865 */ { 05, 01, 27, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
+1866 */ { 00, 02, 15, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 355
+1867 */ { 00, 02, 05, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1868 */ { 04, 01, 25, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1869 */ { 00, 02, 11, 0b1110010010100000 }, /* 30 30 30 29 29 30 29 29 30 29 30 29 354
+1870 */ { 10, 01, 31, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 29 384
+1871 */ { 00, 02, 19, 0b1101101010010000 }, /* 30 30 29 30 30 29 30 29 30 29 29 30 355
+1872 */ { 00, 02, 09, 0b0101101011010000 }, /* 29 30 29 30 30 29 30 29 30 30 29 30 355
+1873 */ { 06, 01, 29, 0b0010101101101000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
+1874 */ { 00, 02, 17, 0b0010101011100000 }, /* 29 29 30 29 30 29 30 29 30 30 30 29 354
+1875 */ { 00, 02, 06, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1876 */ { 05, 01, 26, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1877 */ { 00, 02, 13, 0b1100100101010000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 354
+1878 */ { 00, 02, 02, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1879 */ { 03, 01, 22, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1880 */ { 00, 02, 10, 0b1011011010010000 }, /* 30 29 30 30 29 30 30 29 30 29 29 30 355
+1881 */ { 07, 01, 30, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1882 */ { 00, 02, 18, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
+1883 */ { 00, 02, 08, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+1884 */ { 05, 01, 28, 0b1001001011011000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
+1885 */ { 00, 02, 15, 0b1001001010110000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 354
+1886 */ { 00, 02, 04, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1887 */ { 04, 01, 24, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1888 */ { 00, 02, 12, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+1889 */ { 00, 01, 31, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1890 */ { 02, 01, 21, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1891 */ { 00, 02, 09, 0b0101010110110000 }, /* 29 30 29 30 29 30 29 30 30 29 30 30 355
+1892 */ { 06, 01, 30, 0b0010010110111000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
+1893 */ { 00, 02, 17, 0b0010010101110000 }, /* 29 29 30 29 29 30 29 30 29 30 30 30 354
+1894 */ { 00, 02, 06, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1895 */ { 05, 01, 26, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
+1896 */ { 00, 02, 13, 0b1110100101010000 }, /* 30 30 30 29 30 29 29 30 29 30 29 30 355
+1897 */ { 00, 02, 02, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1898 */ { 03, 01, 22, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1899 */ { 00, 02, 10, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1900 */ { 08, 01, 31, 0b0100101101101000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1901 */ { 00, 02, 19, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1902 */ { 00, 02, 08, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1903 */ { 05, 01, 29, 0b0101001001101000 }, /* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
+1904 */ { 00, 02, 16, 0b1101001001100000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 354
+1905 */ { 00, 02, 04, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
+1906 */ { 04, 01, 25, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1907 */ { 00, 02, 13, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1908 */ { 00, 02, 02, 0b1001101011010000 }, /* 30 29 29 30 30 29 30 29 30 30 29 30 355
+1909 */ { 02, 01, 22, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1910 */ { 00, 02, 10, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1911 */ { 06, 01, 30, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1912 */ { 00, 02, 18, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+1913 */ { 00, 02, 06, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+1914 */ { 05, 01, 26, 0b1101100101001000 }, /* 30 30 29 30 30 29 29 30 29 30 29 29 30 384
+1915 */ { 00, 02, 14, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1916 */ { 00, 02, 04, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1917 */ { 02, 01, 23, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1918 */ { 00, 02, 11, 0b1001010111010000 }, /* 30 29 29 30 29 30 29 30 30 30 29 30 355
+1919 */ { 07, 02, 01, 0b0100101011011000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+1920 */ { 00, 02, 20, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1921 */ { 00, 02, 08, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1922 */ { 05, 01, 28, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1923 */ { 00, 02, 16, 0b0110101010010000 }, /* 29 30 30 29 30 29 30 29 30 29 29 30 354
+1924 */ { 00, 02, 05, 0b1010110101000000 }, /* 30 29 30 29 30 30 29 30 29 30 29 29 354
+1925 */ { 04, 01, 24, 0b1011010110101000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
+1926 */ { 00, 02, 13, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1927 */ { 00, 02, 02, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1928 */ { 02, 01, 23, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1929 */ { 00, 02, 10, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1930 */ { 06, 01, 30, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1931 */ { 00, 02, 17, 0b1110010010100000 }, /* 30 30 30 29 29 30 29 29 30 29 30 29 354
+1932 */ { 00, 02, 06, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
+1933 */ { 05, 01, 26, 0b0110110101001000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
+1934 */ { 00, 02, 14, 0b0101101101010000 }, /* 29 30 29 30 30 29 30 30 29 30 29 30 355
+1935 */ { 00, 02, 04, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1936 */ { 03, 01, 24, 0b1001010101110000 }, /* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
+1937 */ { 00, 02, 11, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+1938 */ { 07, 01, 31, 0b1100100101101000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1939 */ { 00, 02, 19, 0b1100100101010000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 354
+1940 */ { 00, 02, 08, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+1941 */ { 06, 01, 27, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1942 */ { 00, 02, 15, 0b1011011010010000 }, /* 30 29 30 30 29 30 30 29 30 29 29 30 355
+1943 */ { 00, 02, 05, 0b0101011011010000 }, /* 29 30 29 30 29 30 30 29 30 30 29 30 355
+1944 */ { 04, 01, 26, 0b0010101011011000 }, /* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
+1945 */ { 00, 02, 13, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+1946 */ { 00, 02, 02, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
+1947 */ { 02, 01, 22, 0b1100100101011000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+1948 */ { 00, 02, 10, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+1949 */ { 07, 01, 29, 0b1101010010101000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1950 */ { 00, 02, 17, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+1951 */ { 00, 02, 06, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+1952 */ { 05, 01, 27, 0b0101011010101000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1953 */ { 00, 02, 14, 0b0100110110110000 }, /* 29 30 29 29 30 30 29 30 30 29 30 30 355
+1954 */ { 00, 02, 04, 0b0010010110110000 }, /* 29 29 30 29 29 30 29 30 30 29 30 30 354
+1955 */ { 03, 01, 24, 0b1001001010111000 }, /* 30 29 29 30 29 29 30 29 30 29 30 30 30 384
+1956 */ { 00, 02, 12, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+1957 */ { 08, 01, 31, 0b1010100101011000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1958 */ { 00, 02, 19, 0b0110100101010000 }, /* 29 30 30 29 30 29 29 30 29 30 29 30 354
+1959 */ { 00, 02, 08, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+1960 */ { 06, 01, 28, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1961 */ { 00, 02, 15, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 355
+1962 */ { 00, 02, 05, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+1963 */ { 04, 01, 25, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1964 */ { 00, 02, 13, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+1965 */ { 00, 02, 02, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 354
+1966 */ { 03, 01, 22, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
+1967 */ { 00, 02, 09, 0b1101100101010000 }, /* 30 30 29 30 30 29 29 30 29 30 29 30 355
+1968 */ { 07, 01, 30, 0b0110101010101000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1969 */ { 00, 02, 17, 0b0101011010100000 }, /* 29 30 29 30 29 30 30 29 30 29 30 29 354
+1970 */ { 00, 02, 06, 0b1001101011010000 }, /* 30 29 29 30 30 29 30 29 30 30 29 30 355
+1971 */ { 05, 01, 27, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1972 */ { 00, 02, 15, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+1973 */ { 00, 02, 03, 0b1010010011100000 }, /* 30 29 30 29 29 30 29 29 30 30 30 29 354
+1974 */ { 04, 01, 23, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1975 */ { 00, 02, 11, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+1976 */ { 08, 01, 31, 0b1101010101001000 }, /* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
+1977 */ { 00, 02, 18, 0b1011010101000000 }, /* 30 29 30 30 29 30 29 30 29 30 29 29 354
+1978 */ { 00, 02, 07, 0b1101011010100000 }, /* 30 30 29 30 29 30 30 29 30 29 30 29 355
+1979 */ { 06, 01, 28, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1980 */ { 00, 02, 16, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1981 */ { 00, 02, 05, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+1982 */ { 04, 01, 25, 0b1010010011011000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1983 */ { 00, 02, 13, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+1984 */ { 10, 02, 02, 0b1011001001011000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1985 */ { 00, 02, 20, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 354
+1986 */ { 00, 02, 09, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
+1987 */ { 06, 01, 29, 0b1011010110101000 }, /* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
+1988 */ { 00, 02, 18, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1989 */ { 00, 02, 06, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 355
+1990 */ { 05, 01, 27, 0b0100100110111000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1991 */ { 00, 02, 15, 0b0100100101110000 }, /* 29 30 29 29 30 29 29 30 29 30 30 30 354
+1992 */ { 00, 02, 04, 0b0110010010110000 }, /* 29 30 30 29 29 30 29 29 30 29 30 30 354
+1993 */ { 03, 01, 23, 0b0110101001010000 }, /* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1994 */ { 00, 02, 10, 0b1110101001010000 }, /* 30 30 30 29 30 29 30 29 29 30 29 30 355
+1995 */ { 08, 01, 31, 0b0110110101001000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
+1996 */ { 00, 02, 19, 0b0101101011010000 }, /* 29 30 29 30 30 29 30 29 30 30 29 30 355
+1997 */ { 00, 02, 08, 0b0010101101100000 }, /* 29 29 30 29 30 29 30 30 29 30 30 29 354
+1998 */ { 05, 01, 28, 0b1001001101110000 }, /* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1999 */ { 00, 02, 16, 0b1001001011100000 }, /* 30 29 29 30 29 29 30 29 30 30 30 29 354
+2000 */ { 00, 02, 05, 0b1100100101100000 }, /* 30 30 29 29 30 29 29 30 29 30 30 29 354
+2001 */ { 04, 01, 24, 0b1110010010101000 }, /* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
+2002 */ { 00, 02, 12, 0b1101010010100000 }, /* 30 30 29 30 29 30 29 29 30 29 30 29 354
+2003 */ { 00, 02, 01, 0b1101101001010000 }, /* 30 30 29 30 30 29 30 29 29 30 29 30 355
+2004 */ { 02, 01, 22, 0b0101101010101000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+2005 */ { 00, 02, 09, 0b0101011011000000 }, /* 29 30 29 30 29 30 30 29 30 30 29 29 354
+2006 */ { 07, 01, 29, 0b1010101011011000 }, /* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+2007 */ { 00, 02, 18, 0b0010010111010000 }, /* 29 29 30 29 29 30 29 30 30 30 29 30 354
+2008 */ { 00, 02, 07, 0b1001001011010000 }, /* 30 29 29 30 29 29 30 29 30 30 29 30 354
+2009 */ { 05, 01, 26, 0b1100100101011000 }, /* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+2010 */ { 00, 02, 14, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+2011 */ { 00, 02, 03, 0b1011010010100000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 354
+2012 */ { 03, 01, 23, 0b1011101001010000 }, /* 30 29 30 30 30 29 30 29 29 30 29 30 29 384
+2013 */ { 00, 02, 10, 0b1011010101010000 }, /* 30 29 30 30 29 30 29 30 29 30 29 30 355
+2014 */ { 09, 01, 31, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2015 */ { 00, 02, 19, 0b0100101110100000 }, /* 29 30 29 29 30 29 30 30 30 29 30 29 354
+2016 */ { 00, 02, 08, 0b1010010110110000 }, /* 30 29 30 29 29 30 29 30 30 29 30 30 355
+2017 */ { 05, 01, 28, 0b0101001010111000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+2018 */ { 00, 02, 16, 0b0101001010110000 }, /* 29 30 29 30 29 29 30 29 30 29 30 30 354
+2019 */ { 00, 02, 05, 0b1010100101010000 }, /* 30 29 30 29 30 29 29 30 29 30 29 30 354
+2020 */ { 04, 01, 25, 0b1011010010101000 }, /* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+2021 */ { 00, 02, 12, 0b0110101010100000 }, /* 29 30 30 29 30 29 30 29 30 29 30 29 354
+2022 */ { 00, 02, 01, 0b1010110101010000 }, /* 30 29 30 29 30 30 29 30 29 30 29 30 355
+2023 */ { 02, 01, 22, 0b0101010110101000 }, /* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2024 */ { 00, 02, 10, 0b0100101101100000 }, /* 29 30 29 29 30 29 30 30 29 30 30 29 354
+2025 */ { 06, 01, 29, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+2026 */ { 00, 02, 17, 0b1010010101110000 }, /* 30 29 30 29 29 30 29 30 29 30 30 30 355
+2027 */ { 00, 02, 07, 0b0101001001110000 }, /* 29 30 29 30 29 29 30 29 29 30 30 30 354
+2028 */ { 05, 01, 27, 0b0110100100110000 }, /* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
+2029 */ { 00, 02, 13, 0b1101100100110000 }, /* 30 30 29 30 30 29 29 30 29 29 30 30 355
+2030 */ { 00, 02, 03, 0b0101101010100000 }, /* 29 30 29 30 30 29 30 29 30 29 30 29 354
+2031 */ { 03, 01, 23, 0b1010101101010000 }, /* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+2032 */ { 00, 02, 11, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+2033 */ { 11, 01, 31, 0b0100101011101000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+2034 */ { 00, 02, 19, 0b0100101011100000 }, /* 29 30 29 29 30 29 30 29 30 30 30 29 354
+2035 */ { 00, 02, 08, 0b1010010011010000 }, /* 30 29 30 29 29 30 29 29 30 30 29 30 354
+2036 */ { 06, 01, 28, 0b1101001001101000 }, /* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+2037 */ { 00, 02, 15, 0b1101001001010000 }, /* 30 30 29 30 29 29 30 29 29 30 29 30 354
+2038 */ { 00, 02, 04, 0b1101010100100000 }, /* 30 30 29 30 29 30 29 30 29 29 30 29 354
+2039 */ { 05, 01, 24, 0b1101101010100000 }, /* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
+2040 */ { 00, 02, 12, 0b1011011010100000 }, /* 30 29 30 30 29 30 30 29 30 29 30 29 355
+2041 */ { 00, 02, 01, 0b1001011011010000 }, /* 30 29 29 30 29 30 30 29 30 30 29 30 355
+2042 */ { 02, 01, 22, 0b0100101011011000 }, /* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+2043 */ { 00, 02, 10, 0b0100100110110000 }, /* 29 30 29 29 30 29 29 30 30 29 30 30 354
+2044 */ { 07, 01, 30, 0b1010010010111000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+2045 */ { 00, 02, 17, 0b1010010010110000 }, /* 30 29 30 29 29 30 29 29 30 29 30 30 354
+2046 */ { 00, 02, 06, 0b1011001001010000 }, /* 30 29 30 30 29 29 30 29 29 30 29 30 354
+2047 */ { 05, 01, 26, 0b1011010100101000 }, /* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+2048 */ { 00, 02, 14, 0b0110110101000000 }, /* 29 30 30 29 30 30 29 30 29 30 29 29 354
+2049 */ { 00, 02, 02, 0b1010110110100000 }, /* 30 29 30 29 30 30 29 30 30 29 30 29 355
+2050 */ { 03, 01, 23, 0b1001010110110000 }, /* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
+ */ };
internal override int MinCalendarYear
{
@@ -1249,7 +1248,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"year",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
MIN_LUNISOLAR_YEAR,
@@ -1272,7 +1271,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range, MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR));
}
@@ -1306,8 +1305,6 @@ namespace System.Globalization
}
}
-
-
public override int[] Eras
{
get
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/NumberFormatInfo.cs b/src/System.Private.CoreLib/shared/System/Globalization/NumberFormatInfo.cs
index a98023dc9..7afe09474 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/NumberFormatInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/NumberFormatInfo.cs
@@ -52,23 +52,23 @@ namespace System.Globalization
internal int[] numberGroupSizes = new int[] { 3 };
internal int[] currencyGroupSizes = new int[] { 3 };
internal int[] percentGroupSizes = new int[] { 3 };
- internal String positiveSign = "+";
- internal String negativeSign = "-";
- internal String numberDecimalSeparator = ".";
- internal String numberGroupSeparator = ",";
- internal String currencyGroupSeparator = ",";
- internal String currencyDecimalSeparator = ".";
- internal String currencySymbol = "\x00a4"; // U+00a4 is the symbol for International Monetary Fund.
- internal String nanSymbol = "NaN";
- internal String positiveInfinitySymbol = "Infinity";
- internal String negativeInfinitySymbol = "-Infinity";
- internal String percentDecimalSeparator = ".";
- internal String percentGroupSeparator = ",";
- internal String percentSymbol = "%";
- internal String perMilleSymbol = "\u2030";
-
-
- internal String[] nativeDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+ internal string positiveSign = "+";
+ internal string negativeSign = "-";
+ internal string numberDecimalSeparator = ".";
+ internal string numberGroupSeparator = ",";
+ internal string currencyGroupSeparator = ",";
+ internal string currencyDecimalSeparator = ".";
+ internal string currencySymbol = "\x00a4"; // U+00a4 is the symbol for International Monetary Fund.
+ internal string nanSymbol = "NaN";
+ internal string positiveInfinitySymbol = "Infinity";
+ internal string negativeInfinitySymbol = "-Infinity";
+ internal string percentDecimalSeparator = ".";
+ internal string percentGroupSeparator = ",";
+ internal string percentSymbol = "%";
+ internal string perMilleSymbol = "\u2030";
+
+
+ internal string[] nativeDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
internal int numberDecimalDigits = 2;
internal int currencyDecimalDigits = 2;
@@ -90,7 +90,7 @@ namespace System.Globalization
{
}
- private static void VerifyDecimalSeparator(String decSep, String propertyName)
+ private static void VerifyDecimalSeparator(string decSep, string propertyName)
{
if (decSep == null)
{
@@ -104,7 +104,7 @@ namespace System.Globalization
}
}
- private static void VerifyGroupSeparator(String groupSep, String propertyName)
+ private static void VerifyGroupSeparator(string groupSep, string propertyName)
{
if (groupSep == null)
{
@@ -237,7 +237,7 @@ namespace System.Globalization
}
}
- public Object Clone()
+ public object Clone()
{
NumberFormatInfo n = (NumberFormatInfo)MemberwiseClone();
n.isReadOnly = false;
@@ -254,7 +254,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(CurrencyDecimalDigits),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
0,
@@ -266,7 +266,7 @@ namespace System.Globalization
}
- public String CurrencyDecimalSeparator
+ public string CurrencyDecimalSeparator
{
get { return currencyDecimalSeparator; }
set
@@ -292,7 +292,7 @@ namespace System.Globalization
// Every element in the groupSize array should be between 1 and 9
// excpet the last element could be zero.
//
- internal static void CheckGroupSize(String propName, int[] groupSize)
+ internal static void CheckGroupSize(string propName, int[] groupSize)
{
for (int i = 0; i < groupSize.Length; i++)
{
@@ -325,7 +325,7 @@ namespace System.Globalization
}
VerifyWritable();
- Int32[] inputSizes = (Int32[])value.Clone();
+ int[] inputSizes = (int[])value.Clone();
CheckGroupSize(nameof(CurrencyGroupSizes), inputSizes);
currencyGroupSizes = inputSizes;
}
@@ -348,7 +348,7 @@ namespace System.Globalization
}
VerifyWritable();
- Int32[] inputSizes = (Int32[])value.Clone();
+ int[] inputSizes = (int[])value.Clone();
CheckGroupSize(nameof(NumberGroupSizes), inputSizes);
numberGroupSizes = inputSizes;
}
@@ -369,14 +369,14 @@ namespace System.Globalization
SR.ArgumentNull_Obj);
}
VerifyWritable();
- Int32[] inputSizes = (Int32[])value.Clone();
+ int[] inputSizes = (int[])value.Clone();
CheckGroupSize(nameof(PercentGroupSizes), inputSizes);
percentGroupSizes = inputSizes;
}
}
- public String CurrencyGroupSeparator
+ public string CurrencyGroupSeparator
{
get { return currencyGroupSeparator; }
set
@@ -388,7 +388,7 @@ namespace System.Globalization
}
- public String CurrencySymbol
+ public string CurrencySymbol
{
get { return currencySymbol; }
set
@@ -424,7 +424,7 @@ namespace System.Globalization
}
- public String NaNSymbol
+ public string NaNSymbol
{
get
{
@@ -453,7 +453,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(CurrencyNegativePattern),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
0,
@@ -477,7 +477,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(NumberNegativePattern),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
0,
@@ -501,7 +501,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(PercentPositivePattern),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
0,
@@ -525,7 +525,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(PercentNegativePattern),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
0,
@@ -537,7 +537,7 @@ namespace System.Globalization
}
- public String NegativeInfinitySymbol
+ public string NegativeInfinitySymbol
{
get
{
@@ -556,7 +556,7 @@ namespace System.Globalization
}
- public String NegativeSign
+ public string NegativeSign
{
get { return negativeSign; }
set
@@ -581,7 +581,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(NumberDecimalDigits),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
0,
@@ -593,7 +593,7 @@ namespace System.Globalization
}
- public String NumberDecimalSeparator
+ public string NumberDecimalSeparator
{
get { return numberDecimalSeparator; }
set
@@ -605,7 +605,7 @@ namespace System.Globalization
}
- public String NumberGroupSeparator
+ public string NumberGroupSeparator
{
get { return numberGroupSeparator; }
set
@@ -626,7 +626,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(CurrencyPositivePattern),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
0,
@@ -638,7 +638,7 @@ namespace System.Globalization
}
- public String PositiveInfinitySymbol
+ public string PositiveInfinitySymbol
{
get
{
@@ -657,7 +657,7 @@ namespace System.Globalization
}
- public String PositiveSign
+ public string PositiveSign
{
get { return positiveSign; }
set
@@ -682,7 +682,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(PercentDecimalDigits),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
0,
@@ -694,7 +694,7 @@ namespace System.Globalization
}
- public String PercentDecimalSeparator
+ public string PercentDecimalSeparator
{
get { return percentDecimalSeparator; }
set
@@ -706,7 +706,7 @@ namespace System.Globalization
}
- public String PercentGroupSeparator
+ public string PercentGroupSeparator
{
get { return percentGroupSeparator; }
set
@@ -718,7 +718,7 @@ namespace System.Globalization
}
- public String PercentSymbol
+ public string PercentSymbol
{
get
{
@@ -737,7 +737,7 @@ namespace System.Globalization
}
- public String PerMilleSymbol
+ public string PerMilleSymbol
{
get { return perMilleSymbol; }
set
@@ -754,7 +754,7 @@ namespace System.Globalization
public string[] NativeDigits
{
- get { return (String[])nativeDigits.Clone(); }
+ get { return (string[])nativeDigits.Clone(); }
set
{
VerifyWritable();
@@ -774,7 +774,7 @@ namespace System.Globalization
}
}
- public Object GetFormat(Type formatType)
+ public object GetFormat(Type formatType)
{
return formatType == typeof(NumberFormatInfo) ? this : null;
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/PersianCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/PersianCalendar.cs
index 10912f85b..a6f964d34 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/PersianCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/PersianCalendar.cs
@@ -117,7 +117,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"time",
- String.Format(
+ string.Format(
CultureInfo.InvariantCulture,
SR.ArgumentOutOfRange_CalendarRange,
minDate,
@@ -140,7 +140,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -157,7 +157,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(month),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
@@ -282,7 +282,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(months),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
-120000,
@@ -462,7 +462,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(day),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Day,
daysInMonth,
@@ -521,7 +521,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(day),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Day,
daysInMonth,
@@ -560,7 +560,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(value),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
99,
@@ -589,7 +589,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/RegionInfo.cs b/src/System.Private.CoreLib/shared/System/Globalization/RegionInfo.cs
index 2cad7bb31..8416257d9 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/RegionInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/RegionInfo.cs
@@ -31,7 +31,7 @@ namespace System.Globalization
//
// Name of this region (ie: es-US): serialized, the field used for deserialization
//
- internal String _name;
+ internal string _name;
//
// The CultureData instance that we are going to read data from.
@@ -54,7 +54,7 @@ namespace System.Globalization
// In Silverlight we enforce that RegionInfos must be created with a full culture name
//
////////////////////////////////////////////////////////////////////////
- public RegionInfo(String name)
+ public RegionInfo(string name)
{
if (name == null)
throw new ArgumentNullException(nameof(name));
@@ -71,7 +71,7 @@ namespace System.Globalization
_cultureData = CultureData.GetCultureDataForRegion(name, true);
if (_cultureData == null)
throw new ArgumentException(
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.Argument_InvalidCultureName, name), nameof(name));
@@ -157,7 +157,7 @@ namespace System.Globalization
// Returns the name of the region (ie: en-US)
//
////////////////////////////////////////////////////////////////////////
- public virtual String Name
+ public virtual string Name
{
get
{
@@ -173,7 +173,7 @@ namespace System.Globalization
// Returns the name of the region in English. (ie: United States)
//
////////////////////////////////////////////////////////////////////////
- public virtual String EnglishName
+ public virtual string EnglishName
{
get
{
@@ -190,7 +190,7 @@ namespace System.Globalization
// if the current UI language is en-US)
//
////////////////////////////////////////////////////////////////////////
- public virtual String DisplayName
+ public virtual string DisplayName
{
get
{
@@ -207,7 +207,7 @@ namespace System.Globalization
// WARNING: You need a full locale name for this to make sense.
//
////////////////////////////////////////////////////////////////////////
- public virtual String NativeName
+ public virtual string NativeName
{
get
{
@@ -222,7 +222,7 @@ namespace System.Globalization
// Returns the two letter ISO region name (ie: US)
//
////////////////////////////////////////////////////////////////////////
- public virtual String TwoLetterISORegionName
+ public virtual string TwoLetterISORegionName
{
get
{
@@ -237,7 +237,7 @@ namespace System.Globalization
// Returns the three letter ISO region name (ie: USA)
//
////////////////////////////////////////////////////////////////////////
- public virtual String ThreeLetterISORegionName
+ public virtual string ThreeLetterISORegionName
{
get
{
@@ -252,7 +252,7 @@ namespace System.Globalization
// Returns the three letter windows region name (ie: USA)
//
////////////////////////////////////////////////////////////////////////
- public virtual String ThreeLetterWindowsRegionName
+ public virtual string ThreeLetterWindowsRegionName
{
get
{
@@ -324,7 +324,7 @@ namespace System.Globalization
// Currency Symbol for this locale, ie: Fr. or $
//
////////////////////////////////////////////////////////////////////////
- public virtual String CurrencySymbol
+ public virtual string CurrencySymbol
{
get
{
@@ -339,7 +339,7 @@ namespace System.Globalization
// ISO Currency Symbol for this locale, ie: CHF
//
////////////////////////////////////////////////////////////////////////
- public virtual String ISOCurrencySymbol
+ public virtual string ISOCurrencySymbol
{
get
{
@@ -358,7 +358,7 @@ namespace System.Globalization
// (ie: en-US)
//
////////////////////////////////////////////////////////////////////////
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
RegionInfo that = value as RegionInfo;
if (that != null)
@@ -391,7 +391,7 @@ namespace System.Globalization
// Implements Object.ToString(). Returns the name of the Region, ie: es-US
//
////////////////////////////////////////////////////////////////////////
- public override String ToString()
+ public override string ToString()
{
return (Name);
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/SortKey.cs b/src/System.Private.CoreLib/shared/System/Globalization/SortKey.cs
index 647db75b6..962494625 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/SortKey.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/SortKey.cs
@@ -33,7 +33,7 @@ namespace System.Globalization
// The following constructor is designed to be called from CompareInfo to get the
// the sort key of specific string for synthetic culture
//
- internal SortKey(String localeName, String str, CompareOptions options, byte[] keyData)
+ internal SortKey(string localeName, string str, CompareOptions options, byte[] keyData)
{
_keyData = keyData;
_localeName = localeName;
@@ -49,7 +49,7 @@ namespace System.Globalization
// of SortKey.
//
////////////////////////////////////////////////////////////////////////
- public virtual String OriginalString
+ public virtual string OriginalString
{
get
{
@@ -133,7 +133,7 @@ namespace System.Globalization
// or not object refers to the same SortKey as the current instance.
//
////////////////////////////////////////////////////////////////////////
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
SortKey that = value as SortKey;
@@ -167,7 +167,7 @@ namespace System.Globalization
// SortKey.
//
////////////////////////////////////////////////////////////////////////
- public override String ToString()
+ public override string ToString()
{
return ("SortKey - " + _localeName + ", " + _options + ", " + _string);
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/StringInfo.cs b/src/System.Private.CoreLib/shared/System/Globalization/StringInfo.cs
index aa62b2c47..f7be252bf 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/StringInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/StringInfo.cs
@@ -32,7 +32,7 @@ namespace System.Globalization
this.String = value;
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
StringInfo that = value as StringInfo;
if (that != null)
@@ -266,7 +266,7 @@ namespace System.Globalization
{
if (index == len)
{
- return (String.Empty);
+ return (string.Empty);
}
throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index);
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/TaiwanCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/TaiwanCalendar.cs
index c5161138d..e2455cd5e 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/TaiwanCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/TaiwanCalendar.cs
@@ -243,7 +243,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"year",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
99,
@@ -268,7 +268,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
1,
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/TaiwanLunisolarCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/TaiwanLunisolarCalendar.cs
index 60e84f7f3..451fc3074 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/TaiwanLunisolarCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/TaiwanLunisolarCalendar.cs
@@ -263,7 +263,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"year",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
MIN_LUNISOLAR_YEAR,
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/TextElementEnumerator.cs b/src/System.Private.CoreLib/shared/System/Globalization/TextElementEnumerator.cs
index 8b0f102a7..7d8ff64a3 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/TextElementEnumerator.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/TextElementEnumerator.cs
@@ -21,7 +21,7 @@ namespace System.Globalization
public class TextElementEnumerator : IEnumerator
{
- private String _str;
+ private string _str;
private int _index;
private int _startIndex;
@@ -33,7 +33,7 @@ namespace System.Globalization
private int _charLen; // The next abstract char to look at after MoveNext() is called. It could be 1 or 2, depending on if it is a surrogate or not.
- internal TextElementEnumerator(String str, int startIndex, int strLen)
+ internal TextElementEnumerator(string str, int startIndex, int strLen)
{
Debug.Assert(str != null, "TextElementEnumerator(): str != null");
Debug.Assert(startIndex >= 0 && strLen >= 0, "TextElementEnumerator(): startIndex >= 0 && strLen >= 0");
@@ -61,7 +61,7 @@ namespace System.Globalization
// Get the current text element.
//
- public Object Current
+ public object Current
{
get
{
@@ -73,7 +73,7 @@ namespace System.Globalization
// Get the current text element.
//
- public String GetTextElement()
+ public string GetTextElement()
{
if (_index == _startIndex)
{
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.Unix.cs b/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.Unix.cs
index d13d3e8ce..c431e462b 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.Unix.cs
@@ -13,116 +13,7 @@ namespace System.Globalization
{
private Tristate _needsTurkishCasing = Tristate.NotInitialized;
- private void FinishInitialization()
- {
- }
-
- private unsafe string ChangeCase(string s, bool toUpper)
- {
- Debug.Assert(!_invariantMode);
-
- Debug.Assert(s != null);
-
- if (s.Length == 0)
- {
- return string.Empty;
- }
-
- string result = string.FastAllocateString(s.Length);
-
- fixed (char* pSource = s)
- {
- fixed (char* pResult = result)
- {
-#if CORECLR
- if (IsAsciiCasingSameAsInvariant && s.IsAscii())
- {
- int length = s.Length;
- char* a = pSource, b = pResult;
- if (toUpper)
- {
- while (length-- != 0)
- {
- *b++ = ToUpperAsciiInvariant(*a++);
- }
- }
- else
- {
- while (length-- != 0)
- {
- *b++ = ToLowerAsciiInvariant(*a++);
- }
- }
- }
- else
-#endif
- {
- ChangeCase(pSource, s.Length, pResult, result.Length, toUpper);
- }
- }
- }
-
- return result;
- }
-
- internal unsafe void ChangeCase(ReadOnlySpan<char> source, Span<char> destination, bool toUpper)
- {
- Debug.Assert(!_invariantMode);
- Debug.Assert(destination.Length >= source.Length);
-
- if (source.IsEmpty)
- {
- return;
- }
-
- fixed (char* pSource = &MemoryMarshal.GetReference(source))
- {
- fixed (char* pResult = &MemoryMarshal.GetReference(destination))
- {
- if (IsAsciiCasingSameAsInvariant)
- {
- int length = 0;
- char* a = pSource, b = pResult;
- if (toUpper)
- {
- while (length < source.Length && *a < 0x80)
- {
- *b++ = ToUpperAsciiInvariant(*a++);
- length++;
- }
- }
- else
- {
- while (length < source.Length && *a < 0x80)
- {
- *b++ = ToLowerAsciiInvariant(*a++);
- length++;
- }
- }
-
- if (length != source.Length)
- {
- ChangeCase(a, source.Length - length, b, destination.Length - length, toUpper);
- }
- }
- else
- {
- ChangeCase(pSource, source.Length, pResult, destination.Length, toUpper);
- }
- }
- }
- }
-
- private unsafe char ChangeCase(char c, bool toUpper)
- {
- Debug.Assert(!_invariantMode);
-
- char dst = default(char);
-
- ChangeCase(&c, 1, &dst, 1, toUpper);
-
- return dst;
- }
+ private void FinishInitialization() { }
// -----------------------------
// ---- PAL layer ends here ----
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.Windows.cs b/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.Windows.cs
index 015b37fcc..6e5e32100 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.Windows.cs
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
-using System.Runtime.InteropServices;
namespace System.Globalization
{
@@ -24,115 +23,33 @@ namespace System.Globalization
_sortHandle = ret > 0 ? handle : IntPtr.Zero;
}
- private unsafe string ChangeCase(string s, bool toUpper)
+ private unsafe void ChangeCase(char* pSource, int pSourceLen, char* pResult, int pResultLen, bool toUpper)
{
Debug.Assert(!_invariantMode);
-
- Debug.Assert(s != null);
-
- //
- // Get the length of the string.
- //
- int nLengthInput = s.Length;
-
- //
- // Check if we have the empty string.
- //
- if (nLengthInput == 0)
- {
- return s;
- }
-
- int ret;
+ Debug.Assert(pSource != null);
+ Debug.Assert(pResult != null);
+ Debug.Assert(pSourceLen >= 0);
+ Debug.Assert(pResultLen >= 0);
+ Debug.Assert(pSourceLen <= pResultLen);
// Check for Invariant to avoid A/V in LCMapStringEx
uint linguisticCasing = IsInvariantLocale(_textInfoName) ? 0 : LCMAP_LINGUISTIC_CASING;
- //
- // Create the result string.
- //
- string result = string.FastAllocateString(nLengthInput);
-
- fixed (char* pSource = s)
- fixed (char* pResult = result)
- {
- ret = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _textInfoName,
- linguisticCasing | (toUpper ? LCMAP_UPPERCASE : LCMAP_LOWERCASE),
- pSource,
- nLengthInput,
- pResult,
- nLengthInput,
- null,
- null,
- _sortHandle);
- }
-
+ int ret = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _textInfoName,
+ linguisticCasing | (toUpper ? LCMAP_UPPERCASE : LCMAP_LOWERCASE),
+ pSource,
+ pSourceLen,
+ pResult,
+ pSourceLen,
+ null,
+ null,
+ _sortHandle);
if (ret == 0)
{
throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
}
- Debug.Assert(ret == nLengthInput, "Expected getting the same length of the original string");
- return result;
- }
-
- internal unsafe void ChangeCase(ReadOnlySpan<char> source, Span<char> destination, bool toUpper)
- {
- Debug.Assert(!_invariantMode);
- Debug.Assert(destination.Length >= source.Length);
-
- if (source.IsEmpty)
- {
- return;
- }
-
- int ret;
-
- // Check for Invariant to avoid A/V in LCMapStringEx
- uint linguisticCasing = IsInvariantLocale(_textInfoName) ? 0 : LCMAP_LINGUISTIC_CASING;
-
- fixed (char* pSource = &MemoryMarshal.GetReference(source))
- fixed (char* pResult = &MemoryMarshal.GetReference(destination))
- {
- ret = Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _textInfoName,
- linguisticCasing | (toUpper ? LCMAP_UPPERCASE : LCMAP_LOWERCASE),
- pSource,
- source.Length,
- pResult,
- source.Length,
- null,
- null,
- _sortHandle);
- }
-
- if (ret == 0)
- {
- throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
- }
-
- Debug.Assert(ret == source.Length, "Expected getting the same length of the original span");
- }
-
- private unsafe char ChangeCase(char c, bool toUpper)
- {
- Debug.Assert(!_invariantMode);
-
- char retVal = '\0';
-
- // Check for Invariant to avoid A/V in LCMapStringEx
- uint linguisticCasing = IsInvariantLocale(_textInfoName) ? 0 : LCMAP_LINGUISTIC_CASING;
-
- Interop.Kernel32.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _textInfoName,
- toUpper ? LCMAP_UPPERCASE | linguisticCasing : LCMAP_LOWERCASE | linguisticCasing,
- &c,
- 1,
- &retVal,
- 1,
- null,
- null,
- _sortHandle);
-
- return retVal;
+ Debug.Assert(ret == pSourceLen, "Expected getting the same length of the original string");
}
// PAL Ends here
@@ -143,9 +60,6 @@ namespace System.Globalization
private const uint LCMAP_LOWERCASE = 0x00000100;
private const uint LCMAP_UPPERCASE = 0x00000200;
- private static bool IsInvariantLocale(string localeName)
- {
- return localeName == "";
- }
+ private static bool IsInvariantLocale(string localeName) => localeName == "";
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.cs b/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.cs
index 631c8c0f1..8073b4b56 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/TextInfo.cs
@@ -13,6 +13,7 @@
////////////////////////////////////////////////////////////////////////////
using System.Diagnostics;
+using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Text;
@@ -75,22 +76,11 @@ namespace System.Globalization
FinishInitialization();
}
- void IDeserializationCallback.OnDeserialization(Object sender)
+ void IDeserializationCallback.OnDeserialization(object sender)
{
throw new PlatformNotSupportedException();
}
- //
- // Internal ordinal comparison functions
- //
-
- internal static int GetHashCodeOrdinalIgnoreCase(string s)
- {
- // This is the same as an case insensitive hash for Invariant
- // (not necessarily true for sorting, but OK for casing & then we apply normal hash code rules)
- return Invariant.GetCaseInsensitiveHashCode(s);
- }
-
public virtual int ANSICodePage => _cultureData.IDEFAULTANSICODEPAGE;
public virtual int OEMCodePage => _cultureData.IDEFAULTOEMCODEPAGE;
@@ -212,7 +202,224 @@ namespace System.Globalization
return ChangeCase(str, toUpper: false);
}
- private unsafe string ToLowerAsciiInvariant(string s)
+ private unsafe char ChangeCase(char c, bool toUpper)
+ {
+ Debug.Assert(!_invariantMode);
+
+ char dst = default;
+ ChangeCase(&c, 1, &dst, 1, toUpper);
+ return dst;
+ }
+
+ private unsafe string ChangeCase(string source, bool toUpper)
+ {
+ Debug.Assert(!_invariantMode);
+ Debug.Assert(source != null);
+
+ // If the string is empty, we're done.
+ if (source.Length == 0)
+ {
+ return string.Empty;
+ }
+
+ int sourcePos = 0;
+ string result = null;
+
+ // If this culture's casing for ASCII is the same as invariant, try to take
+ // a fast path that'll work in managed code and ASCII rather than calling out
+ // to the OS for culture-aware casing.
+ if (IsAsciiCasingSameAsInvariant)
+ {
+ if (toUpper)
+ {
+ // Loop through each character.
+ for (sourcePos = 0; sourcePos < source.Length; sourcePos++)
+ {
+ // If the character is lower-case, we're going to need to allocate a string.
+ char c = source[sourcePos];
+ if ((uint)(c - 'a') <= 'z' - 'a')
+ {
+ // Allocate the result string.
+ result = string.FastAllocateString(source.Length);
+ fixed (char* pResult = result)
+ {
+ // Store all of characters examined thus far.
+ if (sourcePos > 0)
+ {
+ source.AsSpan(0, sourcePos).CopyTo(new Span<char>(pResult, sourcePos));
+ }
+
+ // And store the current character, upper-cased.
+ char* d = pResult + sourcePos;
+ *d++ = (char)(c & ~0x20);
+ sourcePos++;
+
+ // Then continue looping through the remainder of the characters. If we hit
+ // a non-ASCII character, bail to fall back to culture-aware casing.
+ for (; sourcePos < source.Length; sourcePos++)
+ {
+ c = source[sourcePos];
+ if ((uint)(c - 'a') <= 'z' - 'a')
+ {
+ *d++ = (char)(c & ~0x20);
+ }
+ else if (!IsAscii(c))
+ {
+ break;
+ }
+ else
+ {
+ *d++ = c;
+ }
+ }
+ }
+
+ break;
+ }
+ else if (!IsAscii(c))
+ {
+ // The character isn't ASCII; bail to fall back to a culture-aware casing.
+ break;
+ }
+ }
+ }
+ else // toUpper == false
+ {
+ // Loop through each character.
+ for (sourcePos = 0; sourcePos < source.Length; sourcePos++)
+ {
+ // If the character is upper-case, we're going to need to allocate a string.
+ char c = source[sourcePos];
+ if ((uint)(c - 'A') <= 'Z' - 'A')
+ {
+ // Allocate the result string.
+ result = string.FastAllocateString(source.Length);
+ fixed (char* pResult = result)
+ {
+ // Store all of characters examined thus far.
+ if (sourcePos > 0)
+ {
+ source.AsSpan(0, sourcePos).CopyTo(new Span<char>(pResult, sourcePos));
+ }
+
+ // And store the current character, lower-cased.
+ char* d = pResult + sourcePos;
+ *d++ = (char)(c | 0x20);
+ sourcePos++;
+
+ // Then continue looping through the remainder of the characters. If we hit
+ // a non-ASCII character, bail to fall back to culture-aware casing.
+ for (; sourcePos < source.Length; sourcePos++)
+ {
+ c = source[sourcePos];
+ if ((uint)(c - 'A') <= 'Z' - 'A')
+ {
+ *d++ = (char)(c | 0x20);
+ }
+ else if (!IsAscii(c))
+ {
+ break;
+ }
+ else
+ {
+ *d++ = c;
+ }
+ }
+ }
+
+ break;
+ }
+ else if (!IsAscii(c))
+ {
+ // The character isn't ASCII; bail to fall back to a culture-aware casing.
+ break;
+ }
+ }
+ }
+
+ // If we successfully iterated through all of the characters, we didn't need to fall back
+ // to culture-aware casing. In that case, if we allocated a result string, use it, otherwise
+ // just return the original string, as no modifications were necessary.
+ if (sourcePos == source.Length)
+ {
+ return result ?? source;
+ }
+ }
+
+ // Falling back to culture-aware casing. Make sure we have a result string to write into.
+ // If we need to allocate the result string, we'll also need to copy over to it any
+ // characters already examined.
+ if (result == null)
+ {
+ result = string.FastAllocateString(source.Length);
+ if (sourcePos > 0)
+ {
+ fixed (char* pResult = result)
+ {
+ source.AsSpan(0, sourcePos).CopyTo(new Span<char>(pResult, sourcePos));
+ }
+ }
+ }
+
+ // Do the casing operation on everything after what we already processed.
+ fixed (char* pSource = source)
+ {
+ fixed (char* pResult = result)
+ {
+ ChangeCase(pSource + sourcePos, source.Length - sourcePos, pResult + sourcePos, result.Length - sourcePos, toUpper);
+ }
+ }
+
+ return result;
+ }
+
+ internal unsafe void ChangeCase(ReadOnlySpan<char> source, Span<char> destination, bool toUpper)
+ {
+ Debug.Assert(!_invariantMode);
+ Debug.Assert(destination.Length >= source.Length);
+
+ if (source.IsEmpty)
+ {
+ return;
+ }
+
+ fixed (char* pSource = &MemoryMarshal.GetReference(source))
+ fixed (char* pResult = &MemoryMarshal.GetReference(destination))
+ {
+ if (IsAsciiCasingSameAsInvariant)
+ {
+ int length = 0;
+ char* a = pSource, b = pResult;
+ if (toUpper)
+ {
+ while (length < source.Length && *a < 0x80)
+ {
+ *b++ = ToUpperAsciiInvariant(*a++);
+ length++;
+ }
+ }
+ else
+ {
+ while (length < source.Length && *a < 0x80)
+ {
+ *b++ = ToLowerAsciiInvariant(*a++);
+ length++;
+ }
+ }
+
+ if (length != source.Length)
+ {
+ ChangeCase(a, source.Length - length, b, destination.Length - length, toUpper);
+ }
+ }
+ else
+ {
+ ChangeCase(pSource, source.Length, pResult, destination.Length, toUpper);
+ }
+ }
+ }
+
+ private static unsafe string ToLowerAsciiInvariant(string s)
{
if (s.Length == 0)
{
@@ -258,7 +465,7 @@ namespace System.Globalization
}
}
- internal void ToLowerAsciiInvariant(ReadOnlySpan<char> source, Span<char> destination)
+ internal static void ToLowerAsciiInvariant(ReadOnlySpan<char> source, Span<char> destination)
{
Debug.Assert(destination.Length >= source.Length);
@@ -268,7 +475,7 @@ namespace System.Globalization
}
}
- private unsafe string ToUpperAsciiInvariant(string s)
+ private static unsafe string ToUpperAsciiInvariant(string s)
{
if (s.Length == 0)
{
@@ -314,7 +521,7 @@ namespace System.Globalization
}
}
- internal void ToUpperAsciiInvariant(ReadOnlySpan<char> source, Span<char> destination)
+ internal static void ToUpperAsciiInvariant(ReadOnlySpan<char> source, Span<char> destination)
{
Debug.Assert(destination.Length >= source.Length);
@@ -405,7 +612,7 @@ namespace System.Globalization
// or not object refers to the same CultureInfo as the current instance.
//
////////////////////////////////////////////////////////////////////////
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
TextInfo that = obj as TextInfo;
@@ -602,11 +809,20 @@ namespace System.Globalization
{
Debug.Assert(charLen == 1 || charLen == 2, "[TextInfo.AddTitlecaseLetter] CharUnicodeInfo.InternalGetUnicodeCategory returned an unexpected charLen!");
- // for surrogate pairs do a simple ToUpper operation on the substring
if (charLen == 2)
{
- // Surrogate pair
- result.Append(ToUpper(input.Substring(inputIndex, charLen)));
+ // for surrogate pairs do a ToUpper operation on the substring
+ ReadOnlySpan<char> src = input.AsSpan(inputIndex, 2);
+ if (_invariantMode)
+ {
+ result.Append(src); // surrogate pair in invariant mode, so changing case is a nop
+ }
+ else
+ {
+ Span<char> dst = stackalloc char[2];
+ ChangeCase(src, dst, toUpper: true);
+ result.Append(dst);
+ }
inputIndex++;
}
else
@@ -693,64 +909,5 @@ namespace System.Globalization
|| uc == UnicodeCategory.ModifierLetter
|| uc == UnicodeCategory.OtherLetter);
}
-
- //
- // Get case-insensitive hash code for the specified string.
- //
- internal unsafe int GetCaseInsensitiveHashCode(string str)
- {
- // Validate inputs
- if (str == null)
- {
- throw new ArgumentNullException(nameof(str));
- }
-
- // This code assumes that ASCII casing is safe for whatever context is passed in.
- // this is true today, because we only ever call these methods on Invariant. It would be ideal to refactor
- // these methods so they were correct by construction and we could only ever use Invariant.
-
- uint hash = 5381;
- uint c;
-
- // Note: We assume that str contains only ASCII characters until
- // we hit a non-ASCII character to optimize the common case.
- for (int i = 0; i < str.Length; i++)
- {
- c = str[i];
- if (c >= 0x80)
- {
- return GetCaseInsensitiveHashCodeSlow(str);
- }
-
- // If we have a lowercase character, ANDing off 0x20
- // will make it an uppercase character.
- if ((c - 'a') <= ('z' - 'a'))
- {
- c = (uint)((int)c & ~0x20);
- }
-
- hash = ((hash << 5) + hash) ^ c;
- }
-
- return (int)hash;
- }
-
- private unsafe int GetCaseInsensitiveHashCodeSlow(string str)
- {
- Debug.Assert(str != null);
-
- string upper = ToUpper(str);
-
- uint hash = 5381;
- uint c;
-
- for (int i = 0; i < upper.Length; i++)
- {
- c = upper[i];
- hash = ((hash << 5) + hash) ^ c;
- }
-
- return (int)hash;
- }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/ThaiBuddhistCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/ThaiBuddhistCalendar.cs
index 4f8fd8f01..1175185dd 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/ThaiBuddhistCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/ThaiBuddhistCalendar.cs
@@ -206,7 +206,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"year",
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
99,
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanFormat.cs b/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanFormat.cs
index a66e4600a..5e553d56b 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanFormat.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanFormat.cs
@@ -2,9 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Text;
+using System.Buffers.Text;
using System.Diagnostics;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Text;
namespace System.Globalization
{
@@ -35,159 +37,300 @@ namespace System.Globalization
internal static readonly FormatLiterals PositiveInvariantFormatLiterals = TimeSpanFormat.FormatLiterals.InitInvariant(isNegative: false);
internal static readonly FormatLiterals NegativeInvariantFormatLiterals = TimeSpanFormat.FormatLiterals.InitInvariant(isNegative: true);
- internal enum Pattern
- {
- None = 0,
- Minimum = 1,
- Full = 2,
- }
/// <summary>Main method called from TimeSpan.ToString.</summary>
- internal static string Format(TimeSpan value, string format, IFormatProvider formatProvider) =>
- StringBuilderCache.GetStringAndRelease(FormatToBuilder(value, format, formatProvider));
-
- /// <summary>Main method called from TimeSpan.TryFormat.</summary>
- internal static bool TryFormat(TimeSpan value, Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider formatProvider)
+ internal static string Format(TimeSpan value, string format, IFormatProvider formatProvider)
{
- StringBuilder sb = FormatToBuilder(value, format, formatProvider);
- if (sb.Length <= destination.Length)
+ if (string.IsNullOrEmpty(format))
{
- charsWritten = sb.Length;
- sb.CopyTo(0, destination, sb.Length);
- StringBuilderCache.Release(sb);
- return true;
+ return FormatC(value); // formatProvider ignored, as "c" is invariant
}
- else
+
+ if (format.Length == 1)
{
- StringBuilderCache.Release(sb);
- charsWritten = 0;
- return false;
+ char c = format[0];
+
+ if (c == 'c' || (c | 0x20) == 't') // special-case to optimize the default TimeSpan format
+ {
+ return FormatC(value); // formatProvider ignored, as "c" is invariant
+ }
+
+ if ((c | 0x20) == 'g') // special-case to optimize the remaining 'g'/'G' standard formats
+ {
+ return FormatG(value, DateTimeFormatInfo.GetInstance(formatProvider), c == 'G' ? StandardFormat.G : StandardFormat.g);
+ }
+
+ throw new FormatException(SR.Format_InvalidString);
}
+
+ return StringBuilderCache.GetStringAndRelease(FormatCustomized(value, format, DateTimeFormatInfo.GetInstance(formatProvider), result: null));
}
- private static StringBuilder FormatToBuilder(TimeSpan value, ReadOnlySpan<char> format, IFormatProvider formatProvider)
+ /// <summary>Main method called from TimeSpan.TryFormat.</summary>
+ internal static bool TryFormat(TimeSpan value, Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider formatProvider)
{
if (format.Length == 0)
{
- format = "c";
+ return TryFormatStandard(value, StandardFormat.C, null, destination, out charsWritten);
}
- // Standard formats
if (format.Length == 1)
{
- char f = format[0];
- switch (f)
+ char c = format[0];
+ if (c == 'c' || ((c | 0x20) == 't'))
{
- case 'c':
- case 't':
- case 'T':
- return FormatStandard(
- value,
- isInvariant: true,
- format: format,
- pattern: Pattern.Minimum);
-
- case 'g':
- case 'G':
- DateTimeFormatInfo dtfi = DateTimeFormatInfo.GetInstance(formatProvider);
- return FormatStandard(
- value,
- isInvariant: false,
- format: value.Ticks < 0 ? dtfi.FullTimeSpanNegativePattern : dtfi.FullTimeSpanPositivePattern,
- pattern: f == 'g' ? Pattern.Minimum : Pattern.Full);
-
- default:
+ return TryFormatStandard(value, StandardFormat.C, null, destination, out charsWritten);
+ }
+ else
+ {
+ StandardFormat sf =
+ c == 'g' ? StandardFormat.g :
+ c == 'G' ? StandardFormat.G :
throw new FormatException(SR.Format_InvalidString);
+ return TryFormatStandard(value, sf, DateTimeFormatInfo.GetInstance(formatProvider).DecimalSeparator, destination, out charsWritten);
}
}
- // Custom formats
- return FormatCustomized(value, format, DateTimeFormatInfo.GetInstance(formatProvider), result: null);
+ StringBuilder sb = FormatCustomized(value, format, DateTimeFormatInfo.GetInstance(formatProvider), result: null);
+
+ if (sb.Length <= destination.Length)
+ {
+ sb.CopyTo(0, destination, sb.Length);
+ charsWritten = sb.Length;
+ StringBuilderCache.Release(sb);
+ return true;
+ }
+
+ charsWritten = 0;
+ StringBuilderCache.Release(sb);
+ return false;
}
- /// <summary>Format the TimeSpan instance using the specified format.</summary>
- private static StringBuilder FormatStandard(TimeSpan value, bool isInvariant, ReadOnlySpan<char> format, Pattern pattern)
+ internal static string FormatC(TimeSpan value)
{
- StringBuilder sb = StringBuilderCache.Acquire(InternalGlobalizationHelper.StringBuilderDefaultCapacity);
- int day = (int)(value.Ticks / TimeSpan.TicksPerDay);
- long time = value.Ticks % TimeSpan.TicksPerDay;
+ Span<char> destination = stackalloc char[26]; // large enough for any "c" TimeSpan
+ TryFormatStandard(value, StandardFormat.C, null, destination, out int charsWritten);
+ return new string(destination.Slice(0, charsWritten));
+ }
- if (value.Ticks < 0)
+ private static string FormatG(TimeSpan value, DateTimeFormatInfo dtfi, StandardFormat format)
+ {
+ string decimalSeparator = dtfi.DecimalSeparator;
+ int maxLength = 25 + decimalSeparator.Length; // large enough for any "g"/"G" TimeSpan
+ Span<char> destination = maxLength < 128 ?
+ stackalloc char[maxLength] :
+ new char[maxLength]; // the chances of needing this case are almost 0, as DecimalSeparator.Length will basically always == 1
+ TryFormatStandard(value, format, decimalSeparator, destination, out int charsWritten);
+ return new string(destination.Slice(0, charsWritten));
+ }
+
+ private enum StandardFormat { C, G, g }
+
+ private static bool TryFormatStandard(TimeSpan value, StandardFormat format, string decimalSeparator, Span<char> destination, out int charsWritten)
+ {
+ Debug.Assert(format == StandardFormat.C || format == StandardFormat.G || format == StandardFormat.g);
+
+ // First, calculate how large an output buffer is needed to hold the entire output.
+ int requiredOutputLength = 8; // start with "hh:mm:ss" and adjust as necessary
+
+ uint fraction;
+ ulong totalSecondsRemaining;
{
- day = -day;
- time = -time;
+ // Turn this into a non-negative TimeSpan if possible.
+ long ticks = value.Ticks;
+ if (ticks < 0)
+ {
+ requiredOutputLength = 9; // requiredOutputLength + 1 for the leading '-' sign
+ ticks = -ticks;
+ if (ticks < 0)
+ {
+ Debug.Assert(ticks == long.MinValue /* -9223372036854775808 */);
+
+ // We computed these ahead of time; they're straight from the decimal representation of Int64.MinValue.
+ fraction = 4775808;
+ totalSecondsRemaining = 922337203685;
+ goto AfterComputeFraction;
+ }
+ }
+
+ totalSecondsRemaining = Math.DivRem((ulong)ticks, TimeSpan.TicksPerSecond, out ulong fraction64);
+ fraction = (uint)fraction64;
}
- int hours = (int)(time / TimeSpan.TicksPerHour % 24);
- int minutes = (int)(time / TimeSpan.TicksPerMinute % 60);
- int seconds = (int)(time / TimeSpan.TicksPerSecond % 60);
- int fraction = (int)(time % TimeSpan.TicksPerSecond);
- FormatLiterals literal;
- if (isInvariant)
+ AfterComputeFraction:
+ // Only write out the fraction if it's non-zero, and in that
+ // case write out the entire fraction (all digits).
+ Debug.Assert(fraction < 10_000_000);
+ int fractionDigits = 0;
+ switch (format)
{
- literal = value.Ticks < 0 ?
- NegativeInvariantFormatLiterals :
- PositiveInvariantFormatLiterals;
+ case StandardFormat.C:
+ // "c": Write out a fraction only if it's non-zero, and write out all 7 digits of it.
+ if (fraction != 0)
+ {
+ fractionDigits = DateTimeFormat.MaxSecondsFractionDigits;
+ requiredOutputLength += fractionDigits + 1; // digits plus leading decimal separator
+ }
+ break;
+
+ case StandardFormat.G:
+ // "G": Write out a fraction regardless of whether it's 0, and write out all 7 digits of it.
+ fractionDigits = DateTimeFormat.MaxSecondsFractionDigits;
+ requiredOutputLength += fractionDigits + 1; // digits plus leading decimal separator
+ break;
+
+ default:
+ // "g": Write out a fraction only if it's non-zero, and write out only the most significant digits.
+ Debug.Assert(format == StandardFormat.g);
+ if (fraction != 0)
+ {
+ fractionDigits = DateTimeFormat.MaxSecondsFractionDigits - FormattingHelpers.CountDecimalTrailingZeros(fraction, out fraction);
+ requiredOutputLength += fractionDigits + 1; // digits plus leading decimal separator
+ }
+ break;
}
- else
+
+ ulong totalMinutesRemaining = 0, seconds = 0;
+ if (totalSecondsRemaining > 0)
{
- literal = new FormatLiterals();
- literal.Init(format, pattern == Pattern.Full);
+ // Only compute minutes if the TimeSpan has an absolute value of >= 1 minute.
+ totalMinutesRemaining = Math.DivRem(totalSecondsRemaining, 60 /* seconds per minute */, out seconds);
+ Debug.Assert(seconds < 60);
}
- if (fraction != 0)
+ ulong totalHoursRemaining = 0, minutes = 0;
+ if (totalMinutesRemaining > 0)
{
- // truncate the partial second to the specified length
- fraction = (int)(fraction / TimeSpanParse.Pow10(DateTimeFormat.MaxSecondsFractionDigits - literal.ff));
+ // Only compute hours if the TimeSpan has an absolute value of >= 1 hour.
+ totalHoursRemaining = Math.DivRem(totalMinutesRemaining, 60 /* minutes per hour */, out minutes);
+ Debug.Assert(minutes < 60);
}
- // Pattern.Full: [-]dd.hh:mm:ss.fffffff
- // Pattern.Minimum: [-][d.]hh:mm:ss[.fffffff]
+ // At this point, we can switch over to 32-bit DivRem since the data has shrunk far enough.
+ Debug.Assert(totalHoursRemaining <= uint.MaxValue);
- sb.Append(literal.Start); // [-]
- if (pattern == Pattern.Full || day != 0)
+ uint days = 0, hours = 0;
+ if (totalHoursRemaining > 0)
{
- sb.Append(day); // [dd]
- sb.Append(literal.DayHourSep); // [.]
- } //
- AppendNonNegativeInt32(sb, hours, literal.hh); // hh
- sb.Append(literal.HourMinuteSep); // :
- AppendNonNegativeInt32(sb, minutes, literal.mm); // mm
- sb.Append(literal.MinuteSecondSep); // :
- AppendNonNegativeInt32(sb, seconds, literal.ss); // ss
- if (!isInvariant && pattern == Pattern.Minimum)
+ // Only compute days if the TimeSpan has an absolute value of >= 1 day.
+ days = Math.DivRem((uint)totalHoursRemaining, 24 /* hours per day */, out hours);
+ Debug.Assert(hours < 24);
+ }
+
+ int hourDigits = 2;
+ if (format == StandardFormat.g && hours < 10)
+ {
+ // "g": Only writing a one-digit hour, rather than expected two-digit hour
+ hourDigits = 1;
+ requiredOutputLength--;
+ }
+
+ int dayDigits = 0;
+ if (days > 0)
+ {
+ dayDigits = FormattingHelpers.CountDigits(days);
+ Debug.Assert(dayDigits <= 8);
+ requiredOutputLength += dayDigits + 1; // for the leading "d."
+ }
+ else if (format == StandardFormat.G)
+ {
+ // "G": has a leading "0:" if days is 0
+ requiredOutputLength += 2;
+ dayDigits = 1;
+ }
+
+ if (destination.Length < requiredOutputLength)
{
- int effectiveDigits = literal.ff;
- while (effectiveDigits > 0)
+ charsWritten = 0;
+ return false;
+ }
+
+ // Write leading '-' if necessary
+ int idx = 0;
+ if (value.Ticks < 0)
+ {
+ destination[idx++] = '-';
+ }
+
+ // Write day and separator, if necessary
+ if (dayDigits != 0)
+ {
+ WriteDigits(days, destination.Slice(idx, dayDigits));
+ idx += dayDigits;
+ destination[idx++] = format == StandardFormat.C ? '.' : ':';
+ }
+
+ // Write "[h]h:mm:ss
+ Debug.Assert(hourDigits == 1 || hourDigits == 2);
+ if (hourDigits == 2)
+ {
+ WriteTwoDigits(hours, destination.Slice(idx));
+ idx += 2;
+ }
+ else
+ {
+ destination[idx++] = (char)('0' + hours);
+ }
+ destination[idx++] = ':';
+ WriteTwoDigits((uint)minutes, destination.Slice(idx));
+ idx += 2;
+ destination[idx++] = ':';
+ WriteTwoDigits((uint)seconds, destination.Slice(idx));
+ idx += 2;
+
+ // Write fraction and separator, if necessary
+ if (fractionDigits != 0)
+ {
+ if (format == StandardFormat.C)
{
- if (fraction % 10 == 0)
- {
- fraction = fraction / 10;
- effectiveDigits--;
- }
- else
- {
- break;
- }
+ destination[idx++] = '.';
}
- if (effectiveDigits > 0)
+ else if (decimalSeparator.Length == 1)
{
- sb.Append(literal.SecondFractionSep); // [.FFFFFFF]
- sb.Append((fraction).ToString(DateTimeFormat.fixedNumberFormats[effectiveDigits - 1], CultureInfo.InvariantCulture));
+ destination[idx++] = decimalSeparator[0];
}
+ else
+ {
+ decimalSeparator.AsSpan().CopyTo(destination);
+ idx += decimalSeparator.Length;
+ }
+ WriteDigits(fraction, destination.Slice(idx, fractionDigits));
+ idx += fractionDigits;
}
- else if (pattern == Pattern.Full || fraction != 0)
+
+ Debug.Assert(idx == requiredOutputLength);
+ charsWritten = requiredOutputLength;
+ return true;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void WriteTwoDigits(uint value, Span<char> buffer)
+ {
+ Debug.Assert(buffer.Length >= 2);
+ uint temp = '0' + value;
+ value /= 10;
+ buffer[1] = (char)(temp - (value * 10));
+ buffer[0] = (char)('0' + value);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void WriteDigits(uint value, Span<char> buffer)
+ {
+ Debug.Assert(buffer.Length > 0);
+
+ for (int i = buffer.Length - 1; i >= 1; i--)
{
- sb.Append(literal.SecondFractionSep); // [.]
- AppendNonNegativeInt32(sb, fraction, literal.ff); // [fffffff]
+ uint temp = '0' + value;
+ value /= 10;
+ buffer[i] = (char)(temp - (value * 10));
}
- sb.Append(literal.End);
- return sb;
+ Debug.Assert(value < 10);
+ buffer[0] = (char)('0' + value);
}
/// <summary>Format the TimeSpan instance using the specified format.</summary>
- private static StringBuilder FormatCustomized(TimeSpan value, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, StringBuilder result)
+ private static StringBuilder FormatCustomized(TimeSpan value, ReadOnlySpan<char> format, DateTimeFormatInfo dtfi, StringBuilder result = null)
{
Debug.Assert(dtfi != null);
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanParse.cs b/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanParse.cs
index ae77957ce..1bf81742a 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanParse.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/TimeSpanParse.cs
@@ -62,15 +62,6 @@ namespace System.Globalization
private const int MaxSeconds = 59;
private const int MaxFraction = 9999999;
- private enum ParseFailureKind : byte
- {
- None = 0,
- ArgumentNull = 1,
- Format = 2,
- FormatWithParameter = 3,
- Overflow = 4,
- }
-
[Flags]
private enum TimeSpanStandardStyles : byte
{
@@ -99,11 +90,11 @@ namespace System.Globalization
internal int _zeroes; // Store the number of leading zeroes (if any)
internal ReadOnlySpan<char> _sep; // Store the literal that we are parsing (if any)
- public TimeSpanToken(TTT type) : this(type, 0, 0, default(ReadOnlySpan<char>)) { }
+ public TimeSpanToken(TTT type) : this(type, 0, 0, default) { }
- public TimeSpanToken(int number) : this(TTT.Num, number, 0, default(ReadOnlySpan<char>)) { }
+ public TimeSpanToken(int number) : this(TTT.Num, number, 0, default) { }
- public TimeSpanToken(int number, int leadingZeroes) : this(TTT.Num, number, leadingZeroes, default(ReadOnlySpan<char>)) { }
+ public TimeSpanToken(int number, int leadingZeroes) : this(TTT.Num, number, leadingZeroes, default) { }
public TimeSpanToken(TTT type, int number, int leadingZeroes, ReadOnlySpan<char> separator)
{
@@ -169,7 +160,7 @@ namespace System.Globalization
int digit;
if (++_pos >= _value.Length || (uint)(digit = _value[_pos] - '0') > 9)
{
- return new TimeSpanToken(TTT.Num, 0, zeroes, default(ReadOnlySpan<char>));
+ return new TimeSpanToken(TTT.Num, 0, zeroes, default);
}
if (digit == 0)
@@ -199,7 +190,7 @@ namespace System.Globalization
}
}
- return new TimeSpanToken(TTT.Num, num, zeroes, default(ReadOnlySpan<char>));
+ return new TimeSpanToken(TTT.Num, num, zeroes, default);
}
// Otherwise, we're processing a separator, and we've already processed the first
@@ -274,83 +265,83 @@ namespace System.Globalization
internal bool FullAppCompatMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 5
&& _numCount == 4
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.DayHourSep)
- && StringSpanHelpers.Equals(_literals2, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals3, pattern.AppCompatLiteral)
- && StringSpanHelpers.Equals(_literals4, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.DayHourSep)
+ && _literals2.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals3.EqualsOrdinal(pattern.AppCompatLiteral)
+ && _literals4.EqualsOrdinal(pattern.End);
internal bool PartialAppCompatMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 4
&& _numCount == 3
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals2, pattern.AppCompatLiteral)
- && StringSpanHelpers.Equals(_literals3, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals2.EqualsOrdinal(pattern.AppCompatLiteral)
+ && _literals3.EqualsOrdinal(pattern.End);
/// <summary>DHMSF (all values matched)</summary>
internal bool FullMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == MaxLiteralTokens
&& _numCount == MaxNumericTokens
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.DayHourSep)
- && StringSpanHelpers.Equals(_literals2, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals3, pattern.MinuteSecondSep)
- && StringSpanHelpers.Equals(_literals4, pattern.SecondFractionSep)
- && StringSpanHelpers.Equals(_literals5, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.DayHourSep)
+ && _literals2.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals3.EqualsOrdinal(pattern.MinuteSecondSep)
+ && _literals4.EqualsOrdinal(pattern.SecondFractionSep)
+ && _literals5.EqualsOrdinal(pattern.End);
/// <summary>D (no hours, minutes, seconds, or fractions)</summary>
internal bool FullDMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 2
&& _numCount == 1
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.End);
/// <summary>HM (no days, seconds, or fractions)</summary>
internal bool FullHMMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 3
&& _numCount == 2
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals2, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals2.EqualsOrdinal(pattern.End);
/// <summary>DHM (no seconds or fraction)</summary>
internal bool FullDHMMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 4
&& _numCount == 3
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.DayHourSep)
- && StringSpanHelpers.Equals(_literals2, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals3, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.DayHourSep)
+ && _literals2.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals3.EqualsOrdinal(pattern.End);
/// <summary>HMS (no days or fraction)</summary>
internal bool FullHMSMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 4
&& _numCount == 3
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals2, pattern.MinuteSecondSep)
- && StringSpanHelpers.Equals(_literals3, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals2.EqualsOrdinal(pattern.MinuteSecondSep)
+ && _literals3.EqualsOrdinal(pattern.End);
/// <summary>DHMS (no fraction)</summary>
internal bool FullDHMSMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 5
&& _numCount == 4
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.DayHourSep)
- && StringSpanHelpers.Equals(_literals2, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals3, pattern.MinuteSecondSep)
- && StringSpanHelpers.Equals(_literals4, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.DayHourSep)
+ && _literals2.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals3.EqualsOrdinal(pattern.MinuteSecondSep)
+ && _literals4.EqualsOrdinal(pattern.End);
/// <summary>HMSF (no days)</summary>
internal bool FullHMSFMatch(TimeSpanFormat.FormatLiterals pattern) =>
_sepCount == 5
&& _numCount == 4
- && StringSpanHelpers.Equals(_literals0, pattern.Start)
- && StringSpanHelpers.Equals(_literals1, pattern.HourMinuteSep)
- && StringSpanHelpers.Equals(_literals2, pattern.MinuteSecondSep)
- && StringSpanHelpers.Equals(_literals3, pattern.SecondFractionSep)
- && StringSpanHelpers.Equals(_literals4, pattern.End);
+ && _literals0.EqualsOrdinal(pattern.Start)
+ && _literals1.EqualsOrdinal(pattern.HourMinuteSep)
+ && _literals2.EqualsOrdinal(pattern.MinuteSecondSep)
+ && _literals3.EqualsOrdinal(pattern.SecondFractionSep)
+ && _literals4.EqualsOrdinal(pattern.End);
internal TTT _lastSeenTTT;
internal int _tokenCount;
@@ -391,7 +382,7 @@ namespace System.Globalization
switch (tok._ttt)
{
case TTT.Num:
- if ((_tokenCount == 0 && !AddSep(default(ReadOnlySpan<char>), ref result)) || !AddNum(tok, ref result))
+ if ((_tokenCount == 0 && !AddSep(default, ref result)) || !AddNum(tok, ref result))
{
return false;
}
@@ -405,11 +396,11 @@ namespace System.Globalization
break;
case TTT.NumOverflow:
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
default:
// Some unknown token or a repeat token type in the input
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
_lastSeenTTT = tok._ttt;
@@ -421,7 +412,7 @@ namespace System.Globalization
{
if (_sepCount >= MaxLiteralTokens || _tokenCount >= MaxTokens)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
switch (_sepCount++)
@@ -441,7 +432,7 @@ namespace System.Globalization
{
if (_numCount >= MaxNumericTokens || _tokenCount >= MaxTokens)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
switch (_numCount++)
@@ -459,41 +450,88 @@ namespace System.Globalization
}
/// <summary>Store the result of the parsing.</summary>
- private struct TimeSpanResult
+ private ref struct TimeSpanResult
{
internal TimeSpan parsedTimeSpan;
private readonly bool _throwOnFailure;
+ private readonly ReadOnlySpan<char> _originalTimeSpanString;
- internal TimeSpanResult(bool throwOnFailure)
+ internal TimeSpanResult(bool throwOnFailure, ReadOnlySpan<char> originalTimeSpanString)
{
- parsedTimeSpan = default(TimeSpan);
+ parsedTimeSpan = default;
_throwOnFailure = throwOnFailure;
+ _originalTimeSpanString = originalTimeSpanString;
}
- internal bool SetFailure(ParseFailureKind kind, string resourceKey, object messageArgument = null, string argumentName = null)
+ internal bool SetNoFormatSpecifierFailure()
{
if (!_throwOnFailure)
{
return false;
}
- string message = SR.GetResourceString(resourceKey);
- switch (kind)
+ throw new FormatException(SR.Format_NoFormatSpecifier);
+ }
+
+ internal bool SetBadQuoteFailure(char failingCharacter)
+ {
+ if (!_throwOnFailure)
{
- case ParseFailureKind.ArgumentNull:
- Debug.Assert(argumentName != null);
- throw new ArgumentNullException(argumentName, message);
+ return false;
+ }
- case ParseFailureKind.FormatWithParameter:
- throw new FormatException(SR.Format(message, messageArgument));
+ throw new FormatException(SR.Format(SR.Format_BadQuote, failingCharacter));
+ }
+
+ internal bool SetInvalidStringFailure()
+ {
+ if (!_throwOnFailure)
+ {
+ return false;
+ }
- case ParseFailureKind.Overflow:
- throw new OverflowException(message);
+ throw new FormatException(SR.Format_InvalidString);
+ }
- default:
- Debug.Assert(kind == ParseFailureKind.Format, $"Unexpected failure {kind}");
- throw new FormatException(message);
+ internal bool SetArgumentNullFailure(string argumentName)
+ {
+ if (!_throwOnFailure)
+ {
+ return false;
}
+
+ Debug.Assert(argumentName != null);
+ throw new ArgumentNullException(argumentName, SR.ArgumentNull_String);
+ }
+
+ internal bool SetOverflowFailure()
+ {
+ if (!_throwOnFailure)
+ {
+ return false;
+ }
+
+ throw new OverflowException(SR.Format(SR.Overflow_TimeSpanElementTooLarge, new string(_originalTimeSpanString)));
+ }
+
+ internal bool SetBadTimeSpanFailure()
+ {
+ if (!_throwOnFailure)
+ {
+ return false;
+ }
+
+ throw new FormatException(SR.Format(SR.Format_BadTimeSpan, new string(_originalTimeSpanString)));
+ }
+
+ internal bool SetBadFormatSpecifierFailure(char? formatSpecifierCharacter = null)
+ {
+ if (!_throwOnFailure)
+ {
+ return false;
+ }
+
+ throw new FormatException(SR.Format(SR.Format_BadFormatSpecifier, formatSpecifierCharacter));
}
}
@@ -568,7 +606,7 @@ namespace System.Globalization
internal static TimeSpan Parse(ReadOnlySpan<char> input, IFormatProvider formatProvider)
{
- var parseResult = new TimeSpanResult(throwOnFailure: true);
+ var parseResult = new TimeSpanResult(throwOnFailure: true, originalTimeSpanString: input);
bool success = TryParseTimeSpan(input, TimeSpanStandardStyles.Any, formatProvider, ref parseResult);
Debug.Assert(success, "Should have thrown on failure");
return parseResult.parsedTimeSpan;
@@ -576,7 +614,7 @@ namespace System.Globalization
internal static bool TryParse(ReadOnlySpan<char> input, IFormatProvider formatProvider, out TimeSpan result)
{
- var parseResult = new TimeSpanResult(throwOnFailure: false);
+ var parseResult = new TimeSpanResult(throwOnFailure: false, originalTimeSpanString: input);
if (TryParseTimeSpan(input, TimeSpanStandardStyles.Any, formatProvider, ref parseResult))
{
@@ -584,13 +622,13 @@ namespace System.Globalization
return true;
}
- result = default(TimeSpan);
+ result = default;
return false;
}
internal static TimeSpan ParseExact(ReadOnlySpan<char> input, ReadOnlySpan<char> format, IFormatProvider formatProvider, TimeSpanStyles styles)
{
- var parseResult = new TimeSpanResult(throwOnFailure: true);
+ var parseResult = new TimeSpanResult(throwOnFailure: true, originalTimeSpanString: input);
bool success = TryParseExactTimeSpan(input, format, formatProvider, styles, ref parseResult);
Debug.Assert(success, "Should have thrown on failure");
return parseResult.parsedTimeSpan;
@@ -598,7 +636,7 @@ namespace System.Globalization
internal static bool TryParseExact(ReadOnlySpan<char> input, ReadOnlySpan<char> format, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result)
{
- var parseResult = new TimeSpanResult(throwOnFailure: false);
+ var parseResult = new TimeSpanResult(throwOnFailure: false, originalTimeSpanString: input);
if (TryParseExactTimeSpan(input, format, formatProvider, styles, ref parseResult))
{
@@ -606,13 +644,13 @@ namespace System.Globalization
return true;
}
- result = default(TimeSpan);
+ result = default;
return false;
}
internal static TimeSpan ParseExactMultiple(ReadOnlySpan<char> input, string[] formats, IFormatProvider formatProvider, TimeSpanStyles styles)
{
- var parseResult = new TimeSpanResult(throwOnFailure: true);
+ var parseResult = new TimeSpanResult(throwOnFailure: true, originalTimeSpanString: input);
bool success = TryParseExactMultipleTimeSpan(input, formats, formatProvider, styles, ref parseResult);
Debug.Assert(success, "Should have thrown on failure");
return parseResult.parsedTimeSpan;
@@ -620,7 +658,7 @@ namespace System.Globalization
internal static bool TryParseExactMultiple(ReadOnlySpan<char> input, string[] formats, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result)
{
- var parseResult = new TimeSpanResult(throwOnFailure: false);
+ var parseResult = new TimeSpanResult(throwOnFailure: false, originalTimeSpanString: input);
if (TryParseExactMultipleTimeSpan(input, formats, formatProvider, styles, ref parseResult))
{
@@ -628,7 +666,7 @@ namespace System.Globalization
return true;
}
- result = default(TimeSpan);
+ result = default;
return false;
}
@@ -638,7 +676,7 @@ namespace System.Globalization
input = input.Trim();
if (input.IsEmpty)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
var tokenizer = new TimeSpanTokenizer(input);
@@ -654,7 +692,7 @@ namespace System.Globalization
{
if (!raw.ProcessToken(ref tok, ref result))
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
tok = tokenizer.GetNextToken();
}
@@ -662,7 +700,7 @@ namespace System.Globalization
if (!ProcessTerminalState(ref raw, style, ref result))
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
return true;
@@ -691,7 +729,7 @@ namespace System.Globalization
tok._ttt = TTT.Sep;
if (!raw.ProcessToken(ref tok, ref result))
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
}
@@ -702,7 +740,7 @@ namespace System.Globalization
case 3: return ProcessTerminal_HM_S_D(ref raw, style, ref result);
case 4: return ProcessTerminal_HMS_F_D(ref raw, style, ref result);
case 5: return ProcessTerminal_DHMSF(ref raw, style, ref result);
- default: return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ default: return result.SetBadTimeSpanFailure();
}
}
@@ -711,7 +749,7 @@ namespace System.Globalization
{
if (raw._sepCount != 6)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
Debug.Assert(raw._numCount == 5);
@@ -754,7 +792,7 @@ namespace System.Globalization
if (!TryTimeToTicks(positive, raw._numbers0, raw._numbers1, raw._numbers2, raw._numbers3, raw._numbers4, out ticks))
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
if (!positive)
@@ -762,15 +800,15 @@ namespace System.Globalization
ticks = -ticks;
if (ticks > 0)
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
}
- result.parsedTimeSpan._ticks = ticks;
+ result.parsedTimeSpan = new TimeSpan(ticks);
return true;
}
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
@@ -782,7 +820,7 @@ namespace System.Globalization
{
if (raw._sepCount != 5 || (style & TimeSpanStandardStyles.RequireFull) != 0)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
Debug.Assert(raw._numCount == 4);
@@ -890,17 +928,17 @@ namespace System.Globalization
ticks = -ticks;
if (ticks > 0)
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
}
- result.parsedTimeSpan._ticks = ticks;
+ result.parsedTimeSpan = new TimeSpan(ticks);
return true;
}
return overflow ?
- result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge)) : // we found at least one literal pattern match but the numbers just didn't fit
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan)); // we couldn't find a thing
+ result.SetOverflowFailure() : // we found at least one literal pattern match but the numbers just didn't fit
+ result.SetBadTimeSpanFailure(); // we couldn't find a thing
}
/// <summary>Validate the ambiguous 3-number "Hours:Minutes:Seconds", "Days.Hours:Minutes", or "Hours:Minutes:.Fraction" terminal case.</summary>
@@ -908,7 +946,7 @@ namespace System.Globalization
{
if (raw._sepCount != 4 || (style & TimeSpanStandardStyles.RequireFull) != 0)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
Debug.Assert(raw._numCount == 3);
@@ -1016,17 +1054,17 @@ namespace System.Globalization
ticks = -ticks;
if (ticks > 0)
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
}
- result.parsedTimeSpan._ticks = ticks;
+ result.parsedTimeSpan = new TimeSpan(ticks);
return true;
}
return overflow ?
- result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge)) : // we found at least one literal pattern match but the numbers just didn't fit
- result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan)); // we couldn't find a thing
+ result.SetOverflowFailure() : // we found at least one literal pattern match but the numbers just didn't fit
+ result.SetBadTimeSpanFailure(); // we couldn't find a thing
}
/// <summary>Validate the 2-number "Hours:Minutes" terminal case.</summary>
@@ -1034,7 +1072,7 @@ namespace System.Globalization
{
if (raw._sepCount != 3 || (style & TimeSpanStandardStyles.RequireFull) != 0)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
Debug.Assert(raw._numCount == 2);
@@ -1080,7 +1118,7 @@ namespace System.Globalization
if (!TryTimeToTicks(positive, zero, raw._numbers0, raw._numbers1, zero, zero, out ticks))
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
if (!positive)
@@ -1088,15 +1126,15 @@ namespace System.Globalization
ticks = -ticks;
if (ticks > 0)
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
}
- result.parsedTimeSpan._ticks = ticks;
+ result.parsedTimeSpan = new TimeSpan(ticks);
return true;
}
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
/// <summary>Validate the 1-number "Days" terminal case.</summary>
@@ -1104,7 +1142,7 @@ namespace System.Globalization
{
if (raw._sepCount != 2 || (style & TimeSpanStandardStyles.RequireFull) != 0)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
Debug.Assert(raw._numCount == 1);
@@ -1150,7 +1188,7 @@ namespace System.Globalization
if (!TryTimeToTicks(positive, raw._numbers0, zero, zero, zero, zero, out ticks))
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
if (!positive)
@@ -1158,15 +1196,15 @@ namespace System.Globalization
ticks = -ticks;
if (ticks > 0)
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
}
- result.parsedTimeSpan._ticks = ticks;
+ result.parsedTimeSpan = new TimeSpan(ticks);
return true;
}
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
/// <summary>Common private ParseExact method called by both ParseExact and TryParseExact.</summary>
@@ -1174,7 +1212,7 @@ namespace System.Globalization
{
if (format.Length == 0)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier));
+ return result.SetBadFormatSpecifierFailure();
}
if (format.Length == 1)
@@ -1193,7 +1231,7 @@ namespace System.Globalization
return TryParseTimeSpan(input, TimeSpanStandardStyles.Localized | TimeSpanStandardStyles.RequireFull, formatProvider, ref result);
default:
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier));
+ return result.SetBadFormatSpecifierFailure(format[0]);
}
}
@@ -1230,7 +1268,7 @@ namespace System.Globalization
tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
if (tokenLen > 2 || seenHH || !ParseExactDigits(ref tokenizer, tokenLen, out hh))
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ return result.SetInvalidStringFailure();
}
seenHH = true;
break;
@@ -1239,7 +1277,7 @@ namespace System.Globalization
tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
if (tokenLen > 2 || seenMM || !ParseExactDigits(ref tokenizer, tokenLen, out mm))
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ return result.SetInvalidStringFailure();
}
seenMM = true;
break;
@@ -1248,7 +1286,7 @@ namespace System.Globalization
tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
if (tokenLen > 2 || seenSS || !ParseExactDigits(ref tokenizer, tokenLen, out ss))
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ return result.SetInvalidStringFailure();
}
seenSS = true;
break;
@@ -1257,7 +1295,7 @@ namespace System.Globalization
tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
if (tokenLen > DateTimeFormat.MaxSecondsFractionDigits || seenFF || !ParseExactDigits(ref tokenizer, tokenLen, tokenLen, out leadingZeroes, out ff))
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ return result.SetInvalidStringFailure();
}
seenFF = true;
break;
@@ -1266,7 +1304,7 @@ namespace System.Globalization
tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
if (tokenLen > DateTimeFormat.MaxSecondsFractionDigits || seenFF)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ return result.SetInvalidStringFailure();
}
ParseExactDigits(ref tokenizer, tokenLen, tokenLen, out leadingZeroes, out ff);
seenFF = true;
@@ -1277,7 +1315,7 @@ namespace System.Globalization
int tmp = 0;
if (tokenLen > 8 || seenDD || !ParseExactDigits(ref tokenizer, (tokenLen < 2) ? 1 : tokenLen, (tokenLen < 2) ? 8 : tokenLen, out tmp, out dd))
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ return result.SetInvalidStringFailure();
}
seenDD = true;
break;
@@ -1288,12 +1326,12 @@ namespace System.Globalization
if (!DateTimeParse.TryParseQuoteString(format, i, enquotedString, out tokenLen))
{
StringBuilderCache.Release(enquotedString);
- return result.SetFailure(ParseFailureKind.FormatWithParameter, nameof(SR.Format_BadQuote), ch);
+ return result.SetBadQuoteFailure(ch);
}
if (!ParseExactLiteral(ref tokenizer, enquotedString))
{
StringBuilderCache.Release(enquotedString);
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ return result.SetInvalidStringFailure();
}
StringBuilderCache.Release(enquotedString);
break;
@@ -1315,7 +1353,7 @@ namespace System.Globalization
{
// This means that '%' is at the end of the format string or
// "%%" appears in the format string.
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ return result.SetInvalidStringFailure();
}
case '\\':
@@ -1330,12 +1368,12 @@ namespace System.Globalization
else
{
// This means that '\' is at the end of the format string or the literal match failed.
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ return result.SetInvalidStringFailure();
}
break;
default:
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_InvalidString));
+ return result.SetInvalidStringFailure();
}
i += tokenLen;
@@ -1345,7 +1383,7 @@ namespace System.Globalization
if (!tokenizer.EOL)
{
// the custom format didn't consume the entire input
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
bool positive = (styles & TimeSpanStyles.AssumeNegative) == 0;
@@ -1361,12 +1399,12 @@ namespace System.Globalization
ticks = -ticks;
}
- result.parsedTimeSpan._ticks = ticks;
+ result.parsedTimeSpan = new TimeSpan(ticks);
return true;
}
else
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
}
@@ -1456,7 +1494,7 @@ namespace System.Globalization
internal bool TryParse(ReadOnlySpan<char> input, ref TimeSpanResult result)
{
- result.parsedTimeSpan._ticks = 0;
+ result.parsedTimeSpan = default;
_str = input;
_len = input.Length;
@@ -1507,14 +1545,14 @@ namespace System.Globalization
// Allow -0 as well
if (time > 0)
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
}
else
{
if (time < 0)
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
}
@@ -1522,10 +1560,10 @@ namespace System.Globalization
if (_pos < _len)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
- result.parsedTimeSpan._ticks = time;
+ result.parsedTimeSpan = new TimeSpan(time);
return true;
}
@@ -1537,13 +1575,13 @@ namespace System.Globalization
{
if ((i & 0xF0000000) != 0)
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
i = i * 10 + _ch - '0';
if (i < 0)
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
NextChar();
@@ -1551,12 +1589,12 @@ namespace System.Globalization
if (p == _pos)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
if (i > max)
{
- return result.SetFailure(ParseFailureKind.Overflow, nameof(SR.Overflow_TimeSpanElementTooLarge));
+ return result.SetOverflowFailure();
}
return true;
@@ -1575,7 +1613,7 @@ namespace System.Globalization
time = unit * TimeSpan.TicksPerHour;
if (_ch != ':')
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
NextChar();
@@ -1628,17 +1666,17 @@ namespace System.Globalization
{
if (formats == null)
{
- return result.SetFailure(ParseFailureKind.ArgumentNull, nameof(SR.ArgumentNull_String), argumentName: nameof(formats));
+ return result.SetArgumentNullFailure(nameof(formats));
}
if (input.Length == 0)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
if (formats.Length == 0)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier));
+ return result.SetNoFormatSpecifierFailure();
}
// Do a loop through the provided formats and see if we can parse succesfully in
@@ -1647,11 +1685,11 @@ namespace System.Globalization
{
if (formats[i] == null || formats[i].Length == 0)
{
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadFormatSpecifier));
+ return result.SetBadFormatSpecifierFailure();
}
// Create a new non-throwing result each time to ensure the runs are independent.
- TimeSpanResult innerResult = new TimeSpanResult(throwOnFailure: false);
+ TimeSpanResult innerResult = new TimeSpanResult(throwOnFailure: false, originalTimeSpanString: input);
if (TryParseExactTimeSpan(input, formats[i], formatProvider, styles, ref innerResult))
{
@@ -1660,7 +1698,7 @@ namespace System.Globalization
}
}
- return result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_BadTimeSpan));
+ return result.SetBadTimeSpanFailure();
}
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Globalization/UmAlQuraCalendar.cs b/src/System.Private.CoreLib/shared/System/Globalization/UmAlQuraCalendar.cs
index 21a938f8f..777af1800 100644
--- a/src/System.Private.CoreLib/shared/System/Globalization/UmAlQuraCalendar.cs
+++ b/src/System.Private.CoreLib/shared/System/Globalization/UmAlQuraCalendar.cs
@@ -355,7 +355,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
"time",
- String.Format(
+ string.Format(
CultureInfo.InvariantCulture,
SR.ArgumentOutOfRange_CalendarRange,
minDate,
@@ -378,7 +378,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
MinCalendarYear,
@@ -510,7 +510,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(months),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
-120000,
@@ -710,7 +710,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(day),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Day,
daysInMonth,
@@ -774,7 +774,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(day),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Day,
daysInMonth,
@@ -814,7 +814,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(value),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
MinCalendarYear,
@@ -845,7 +845,7 @@ namespace System.Globalization
{
throw new ArgumentOutOfRangeException(
nameof(year),
- String.Format(
+ string.Format(
CultureInfo.CurrentCulture,
SR.ArgumentOutOfRange_Range,
MinCalendarYear,
diff --git a/src/System.Private.CoreLib/shared/System/Guid.Unix.cs b/src/System.Private.CoreLib/shared/System/Guid.Unix.cs
new file mode 100644
index 000000000..442e7f883
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Guid.Unix.cs
@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace System
+{
+ partial struct Guid
+ {
+ // This will create a new random guid based on the https://www.ietf.org/rfc/rfc4122.txt
+ public static unsafe Guid NewGuid()
+ {
+ Guid g;
+ Interop.GetRandomBytes((byte*)&g, sizeof(Guid));
+
+ const ushort VersionMask = 0xF000;
+ const ushort RandomGuidVersion = 0x4000;
+
+ const byte ClockSeqHiAndReservedMask = 0xC0;
+ const byte ClockSeqHiAndReservedValue = 0x80;
+
+ // Modify bits indicating the type of the GUID
+
+ unchecked
+ {
+ // time_hi_and_version
+ g._c = (short)((g._c & ~VersionMask) | RandomGuidVersion);
+ // clock_seq_hi_and_reserved
+ g._d = (byte)((g._d & ~ClockSeqHiAndReservedMask) | ClockSeqHiAndReservedValue);
+ }
+
+ return g;
+ }
+ }
+}
+
diff --git a/src/System.Private.CoreLib/src/System/Guid.Windows.cs b/src/System.Private.CoreLib/shared/System/Guid.Windows.cs
index f21dfbd6b..6a275084f 100644
--- a/src/System.Private.CoreLib/src/System/Guid.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/Guid.Windows.cs
@@ -6,26 +6,24 @@ namespace System
{
partial struct Guid
{
- // This will create a new guid. Since we've now decided that constructors should 0-init,
- // we need a method that allows users to create a guid.
public static Guid NewGuid()
{
// CoCreateGuid should never return Guid.Empty, since it attempts to maintain some
- // uniqueness guarantees. It should also never return a known GUID, but it's unclear
- // how extensively it checks for known values.
+ // uniqueness guarantees.
Guid g;
- int hr = Interop.mincore.CoCreateGuid(out g);
+ int hr = Interop.Ole32.CoCreateGuid(out g);
// We don't expect that this will ever throw an error, none are even documented, and so we don't want to pull
// in the HR to ComException mappings into the core library just for this so we will try a generic exception if
// we ever hit this condition.
if (hr != 0)
{
Exception ex = new Exception();
- ex.SetErrorCode(hr);
+ ex.HResult = hr;
throw ex;
}
return g;
}
}
}
+
diff --git a/src/System.Private.CoreLib/shared/System/Guid.cs b/src/System.Private.CoreLib/shared/System/Guid.cs
index 423d5bc78..6e6ec067a 100644
--- a/src/System.Private.CoreLib/shared/System/Guid.cs
+++ b/src/System.Private.CoreLib/shared/System/Guid.cs
@@ -279,7 +279,7 @@ namespace System
{
if (input == null)
{
- result = default(Guid);
+ result = default;
return false;
}
@@ -297,7 +297,7 @@ namespace System
}
else
{
- result = default(Guid);
+ result = default;
return false;
}
}
@@ -358,7 +358,7 @@ namespace System
{
if (input == null)
{
- result = default(Guid);
+ result = default;
return false;
}
@@ -369,7 +369,7 @@ namespace System
{
if (format.Length != 1)
{
- result = default(Guid);
+ result = default;
return false;
}
@@ -398,7 +398,7 @@ namespace System
break;
default:
// invalid guid format specification
- result = default(Guid);
+ result = default;
return false;
}
@@ -411,7 +411,7 @@ namespace System
}
else
{
- result = default(Guid);
+ result = default;
return false;
}
}
@@ -427,7 +427,7 @@ namespace System
}
// Check for dashes
- bool dashesExistInString = guidString.IndexOf('-') >= 0;
+ bool dashesExistInString = guidString.Contains('-');
if (dashesExistInString)
{
@@ -449,7 +449,7 @@ namespace System
}
// Check for braces
- bool bracesExistInString = (guidString.IndexOf('{', 0) >= 0);
+ bool bracesExistInString = guidString.Contains('{');
if (bracesExistInString)
{
@@ -471,7 +471,7 @@ namespace System
}
// Check for parenthesis
- bool parenthesisExistInString = (guidString.IndexOf('(', 0) >= 0);
+ bool parenthesisExistInString = guidString.Contains('(');
if (parenthesisExistInString)
{
@@ -548,7 +548,7 @@ namespace System
// Find the end of this hex number (since it is not fixed length)
numStart = 3;
- numLen = guidString.IndexOf(',', numStart) - numStart;
+ numLen = guidString.Slice(numStart).IndexOf(',');
if (numLen <= 0)
{
result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_GuidComma));
@@ -566,7 +566,7 @@ namespace System
}
// +3 to get by ',0x'
numStart = numStart + numLen + 3;
- numLen = guidString.IndexOf(',', numStart) - numStart;
+ numLen = guidString.Slice(numStart).IndexOf(',');
if (numLen <= 0)
{
result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_GuidComma));
@@ -584,7 +584,7 @@ namespace System
}
// +3 to get by ',0x'
numStart = numStart + numLen + 3;
- numLen = guidString.IndexOf(',', numStart) - numStart;
+ numLen = guidString.Slice(numStart).IndexOf(',');
if (numLen <= 0)
{
result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_GuidComma));
@@ -621,7 +621,7 @@ namespace System
// Calculate number length
if (i < 7) // first 7 cases
{
- numLen = guidString.IndexOf(',', numStart) - numStart;
+ numLen = guidString.Slice(numStart).IndexOf(',');
if (numLen <= 0)
{
result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_GuidComma));
@@ -630,7 +630,7 @@ namespace System
}
else // last case ends with '}', not ','
{
- numLen = guidString.IndexOf('}', numStart) - numStart;
+ numLen = guidString.Slice(numStart).IndexOf('}');
if (numLen <= 0)
{
result.SetFailure(ParseFailureKind.Format, nameof(SR.Format_GuidBraceAfterLastNumber));
@@ -1232,7 +1232,7 @@ namespace System
return (char)((a > 9) ? a - 10 + 0x61 : a + 0x30);
}
- unsafe private static int HexsToChars(char* guidChars, int a, int b)
+ private static unsafe int HexsToChars(char* guidChars, int a, int b)
{
guidChars[0] = HexToChar(a >> 4);
guidChars[1] = HexToChar(a);
@@ -1243,7 +1243,7 @@ namespace System
return 4;
}
- unsafe private static int HexsToCharsHexOutput(char* guidChars, int a, int b)
+ private static unsafe int HexsToCharsHexOutput(char* guidChars, int a, int b)
{
guidChars[0] = '0';
guidChars[1] = 'x';
diff --git a/src/System.Private.CoreLib/shared/System/HResults.cs b/src/System.Private.CoreLib/shared/System/HResults.cs
index ffc47d85b..4a5ec0d63 100644
--- a/src/System.Private.CoreLib/shared/System/HResults.cs
+++ b/src/System.Private.CoreLib/shared/System/HResults.cs
@@ -25,6 +25,7 @@ namespace System
{
internal static partial class HResults
{
+ internal const int S_OK = unchecked((int)0x00000000);
internal const int COR_E_ABANDONEDMUTEX = unchecked((int)0x8013152D);
internal const int COR_E_AMBIGUOUSMATCH = unchecked((int)0x8000211D);
internal const int COR_E_APPDOMAINUNLOADED = unchecked((int)0x80131014);
@@ -122,5 +123,7 @@ namespace System
internal const int ERROR_MRM_MAP_NOT_FOUND = unchecked((int)0x80073B1F);
internal const int RO_E_CLOSED = unchecked((int)0x80000013);
internal const int TYPE_E_TYPEMISMATCH = unchecked((int)0x80028CA0);
+ internal const int CO_E_NOTINITIALIZED = unchecked((int)0x800401F0);
+ internal const int RPC_E_CHANGED_MODE = unchecked((int)0x80010106);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/IAsyncResult.cs b/src/System.Private.CoreLib/shared/System/IAsyncResult.cs
index 0abeaca52..56ebcdb2f 100644
--- a/src/System.Private.CoreLib/shared/System/IAsyncResult.cs
+++ b/src/System.Private.CoreLib/shared/System/IAsyncResult.cs
@@ -23,7 +23,7 @@ namespace System
WaitHandle AsyncWaitHandle { get; }
- Object AsyncState { get; }
+ object AsyncState { get; }
bool CompletedSynchronously { get; }
}
diff --git a/src/System.Private.CoreLib/shared/System/IComparable.cs b/src/System.Private.CoreLib/shared/System/IComparable.cs
index 72aeeb027..cf71953e2 100644
--- a/src/System.Private.CoreLib/shared/System/IComparable.cs
+++ b/src/System.Private.CoreLib/shared/System/IComparable.cs
@@ -18,7 +18,7 @@ namespace System
// if this is equal to object, or a value greater than zero
// if this is greater than object.
//
- int CompareTo(Object obj);
+ int CompareTo(object obj);
}
// Generic version of IComparable.
diff --git a/src/System.Private.CoreLib/shared/System/IConvertible.cs b/src/System.Private.CoreLib/shared/System/IConvertible.cs
index 87351127f..7abd0c45c 100644
--- a/src/System.Private.CoreLib/shared/System/IConvertible.cs
+++ b/src/System.Private.CoreLib/shared/System/IConvertible.cs
@@ -54,10 +54,10 @@ namespace System
ulong ToUInt64(IFormatProvider provider);
float ToSingle(IFormatProvider provider);
double ToDouble(IFormatProvider provider);
- Decimal ToDecimal(IFormatProvider provider);
+ decimal ToDecimal(IFormatProvider provider);
DateTime ToDateTime(IFormatProvider provider);
- String ToString(IFormatProvider provider);
- Object ToType(Type conversionType, IFormatProvider provider);
+ string ToString(IFormatProvider provider);
+ object ToType(Type conversionType, IFormatProvider provider);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/ICustomFormatter.cs b/src/System.Private.CoreLib/shared/System/ICustomFormatter.cs
index 47340f309..cd798b4a1 100644
--- a/src/System.Private.CoreLib/shared/System/ICustomFormatter.cs
+++ b/src/System.Private.CoreLib/shared/System/ICustomFormatter.cs
@@ -19,6 +19,6 @@ namespace System
public interface ICustomFormatter
{
// Interface does not need to be marked with the serializable attribute
- String Format(String format, Object arg, IFormatProvider formatProvider);
+ string Format(string format, object arg, IFormatProvider formatProvider);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/IFormatProvider.cs b/src/System.Private.CoreLib/shared/System/IFormatProvider.cs
index 0c17354af..9369b074f 100644
--- a/src/System.Private.CoreLib/shared/System/IFormatProvider.cs
+++ b/src/System.Private.CoreLib/shared/System/IFormatProvider.cs
@@ -18,6 +18,6 @@ namespace System
public interface IFormatProvider
{
// Interface does not need to be marked with the serializable attribute
- Object GetFormat(Type formatType);
+ object GetFormat(Type formatType);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/IFormattable.cs b/src/System.Private.CoreLib/shared/System/IFormattable.cs
index 1f2f7022c..b5ed9bb45 100644
--- a/src/System.Private.CoreLib/shared/System/IFormattable.cs
+++ b/src/System.Private.CoreLib/shared/System/IFormattable.cs
@@ -8,6 +8,6 @@ namespace System
{
public interface IFormattable
{
- String ToString(String format, IFormatProvider formatProvider);
+ string ToString(string format, IFormatProvider formatProvider);
}
}
diff --git a/src/System.Private.CoreLib/src/System/IO/BinaryReader.cs b/src/System.Private.CoreLib/shared/System/IO/BinaryReader.cs
index 314d01cc7..1f1b9218f 100644
--- a/src/System.Private.CoreLib/src/System/IO/BinaryReader.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/BinaryReader.cs
@@ -2,11 +2,21 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using Internal.Runtime.CompilerServices;
-using System;
-using System.Text;
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Wraps a stream and provides convenient read functionality
+** for strings and primitive types.
+**
+**
+============================================================*/
+
using System.Diagnostics;
using System.Runtime.InteropServices;
+using System.Text;
namespace System.IO
{
@@ -89,7 +99,7 @@ namespace System.IO
_stream = null;
if (copyOfStream != null && !_leaveOpen)
{
- copyOfStream.Dispose();
+ copyOfStream.Close();
}
}
_stream = null;
@@ -117,7 +127,7 @@ namespace System.IO
{
if (_stream == null)
{
- throw new ObjectDisposedException(null, SR.ObjectDisposed_FileClosed);
+ throw Error.GetFileNotOpen();
}
if (!_stream.CanSeek)
@@ -135,9 +145,79 @@ namespace System.IO
{
if (_stream == null)
{
- throw new ObjectDisposedException(null, SR.ObjectDisposed_FileClosed);
+ throw Error.GetFileNotOpen();
+ }
+
+ int charsRead = 0;
+ int numBytes = 0;
+ long posSav = posSav = 0;
+
+ if (_stream.CanSeek)
+ {
+ posSav = _stream.Position;
+ }
+
+ if (_charBytes == null)
+ {
+ _charBytes = new byte[MaxCharBytesSize]; //REVIEW: We need at most 2 bytes/char here?
}
- return InternalReadOneChar();
+ if (_singleChar == null)
+ {
+ _singleChar = new char[1];
+ }
+
+ while (charsRead == 0)
+ {
+ // We really want to know what the minimum number of bytes per char
+ // is for our encoding. Otherwise for UnicodeEncoding we'd have to
+ // do ~1+log(n) reads to read n characters.
+ // Assume 1 byte can be 1 char unless _2BytesPerChar is true.
+ numBytes = _2BytesPerChar ? 2 : 1;
+
+ int r = _stream.ReadByte();
+ _charBytes[0] = (byte)r;
+ if (r == -1)
+ {
+ numBytes = 0;
+ }
+ if (numBytes == 2)
+ {
+ r = _stream.ReadByte();
+ _charBytes[1] = (byte)r;
+ if (r == -1)
+ {
+ numBytes = 1;
+ }
+ }
+
+ if (numBytes == 0)
+ {
+ return -1;
+ }
+
+ Debug.Assert(numBytes == 1 || numBytes == 2, "BinaryReader::ReadOneChar assumes it's reading one or 2 bytes only.");
+
+ try
+ {
+ charsRead = _decoder.GetChars(_charBytes, 0, numBytes, _singleChar, 0);
+ }
+ catch
+ {
+ // Handle surrogate char
+
+ if (_stream.CanSeek)
+ {
+ _stream.Seek((posSav - _stream.Position), SeekOrigin.Current);
+ }
+ // else - we can't do much here
+
+ throw;
+ }
+
+ Debug.Assert(charsRead < 2, "BinaryReader::ReadOneChar - assuming we only got 0 or 1 char, not 2!");
+ }
+ Debug.Assert(charsRead > 0);
+ return _singleChar[0];
}
public virtual bool ReadBoolean()
@@ -151,13 +231,13 @@ namespace System.IO
// Inlined to avoid some method call overhead with FillBuffer.
if (_stream == null)
{
- throw new ObjectDisposedException(null, SR.ObjectDisposed_FileClosed);
+ throw Error.GetFileNotOpen();
}
int b = _stream.ReadByte();
if (b == -1)
{
- throw new EndOfStreamException(SR.IO_EOF_ReadBeyondEOF);
+ throw Error.GetEndOfFile();
}
return (byte)b;
@@ -175,7 +255,7 @@ namespace System.IO
int value = Read();
if (value == -1)
{
- throw new EndOfStreamException(SR.IO_EOF_ReadBeyondEOF);
+ throw Error.GetEndOfFile();
}
return (char)value;
}
@@ -199,7 +279,7 @@ namespace System.IO
{
if (_stream == null)
{
- throw new ObjectDisposedException(null, SR.ObjectDisposed_FileClosed);
+ throw Error.GetFileNotOpen();
}
// read directly from MemoryStream buffer
@@ -265,11 +345,9 @@ namespace System.IO
public virtual decimal ReadDecimal()
{
FillBuffer(16);
- int[] ints = new int[4];
- Buffer.BlockCopy(_buffer, 0, ints, 0, 16);
try
{
- return new decimal(ints);
+ return decimal.ToDecimal(_buffer);
}
catch (ArgumentException e)
{
@@ -282,7 +360,7 @@ namespace System.IO
{
if (_stream == null)
{
- throw new ObjectDisposedException(null, SR.ObjectDisposed_FileClosed);
+ throw Error.GetFileNotOpen();
}
int currPos = 0;
@@ -321,7 +399,7 @@ namespace System.IO
n = _stream.Read(_charBytes, 0, readLength);
if (n == 0)
{
- throw new EndOfStreamException(SR.IO_EOF_ReadBeyondEOF);
+ throw Error.GetEndOfFile();
}
charsRead = _decoder.GetChars(_charBytes, 0, n, _charBuffer, 0);
@@ -363,7 +441,7 @@ namespace System.IO
}
if (_stream == null)
{
- throw new ObjectDisposedException(null, SR.ObjectDisposed_FileClosed);
+ throw Error.GetFileNotOpen();
}
// SafeCritical: index and count have already been verified to be a valid range for the buffer
@@ -374,7 +452,7 @@ namespace System.IO
{
if (_stream == null)
{
- throw new ObjectDisposedException(null, SR.ObjectDisposed_FileClosed);
+ throw Error.GetFileNotOpen();
}
return InternalReadChars(buffer);
@@ -465,88 +543,6 @@ namespace System.IO
return (buffer.Length - charsRemaining);
}
- private int InternalReadOneChar()
- {
- // I know having a separate InternalReadOneChar method seems a little
- // redundant, but this makes a scenario like the security parser code
- // 20% faster, in addition to the optimizations for UnicodeEncoding I
- // put in InternalReadChars.
- int charsRead = 0;
- int numBytes = 0;
- long posSav = posSav = 0;
-
- if (_stream.CanSeek)
- {
- posSav = _stream.Position;
- }
-
- if (_charBytes == null)
- {
- _charBytes = new byte[MaxCharBytesSize]; //REVIEW: We need at most 2 bytes/char here?
- }
- if (_singleChar == null)
- {
- _singleChar = new char[1];
- }
-
- while (charsRead == 0)
- {
- // We really want to know what the minimum number of bytes per char
- // is for our encoding. Otherwise for UnicodeEncoding we'd have to
- // do ~1+log(n) reads to read n characters.
- // Assume 1 byte can be 1 char unless _2BytesPerChar is true.
- numBytes = _2BytesPerChar ? 2 : 1;
-
- int r = _stream.ReadByte();
- _charBytes[0] = (byte)r;
- if (r == -1)
- {
- numBytes = 0;
- }
- if (numBytes == 2)
- {
- r = _stream.ReadByte();
- _charBytes[1] = (byte)r;
- if (r == -1)
- {
- numBytes = 1;
- }
- }
-
- if (numBytes == 0)
- {
- // Console.WriteLine("Found no bytes. We're outta here.");
- return -1;
- }
-
- Debug.Assert(numBytes == 1 || numBytes == 2, "BinaryReader::InternalReadOneChar assumes it's reading one or 2 bytes only.");
-
- try
- {
- charsRead = _decoder.GetChars(_charBytes, 0, numBytes, _singleChar, 0);
- }
- catch
- {
- // Handle surrogate char
-
- if (_stream.CanSeek)
- {
- _stream.Seek((posSav - _stream.Position), SeekOrigin.Current);
- }
- // else - we can't do much here
-
- throw;
- }
-
- Debug.Assert(charsRead < 2, "InternalReadOneChar - assuming we only got 0 or 1 char, not 2!");
- // Console.WriteLine("That became: " + charsRead + " characters.");
- }
-
- Debug.Assert(charsRead != 0);
-
- return _singleChar[0];
- }
-
public virtual char[] ReadChars(int count)
{
if (count < 0)
@@ -555,7 +551,7 @@ namespace System.IO
}
if (_stream == null)
{
- throw new ObjectDisposedException(null, SR.ObjectDisposed_FileClosed);
+ throw Error.GetFileNotOpen();
}
if (count == 0)
@@ -596,7 +592,7 @@ namespace System.IO
}
if (_stream == null)
{
- throw new ObjectDisposedException(null, SR.ObjectDisposed_FileClosed);
+ throw Error.GetFileNotOpen();
}
return _stream.Read(buffer, index, count);
@@ -606,7 +602,7 @@ namespace System.IO
{
if (_stream == null)
{
- throw new ObjectDisposedException(null, SR.ObjectDisposed_FileClosed);
+ throw Error.GetFileNotOpen();
}
return _stream.Read(buffer);
@@ -665,7 +661,7 @@ namespace System.IO
if (_stream == null)
{
- throw new ObjectDisposedException(null, SR.ObjectDisposed_FileClosed);
+ throw Error.GetFileNotOpen();
}
// Need to find a good threshold for calling ReadByte() repeatedly
@@ -676,7 +672,7 @@ namespace System.IO
n = _stream.ReadByte();
if (n == -1)
{
- throw new EndOfStreamException(SR.IO_EOF_ReadBeyondEOF);
+ throw Error.GetEndOfFile();
}
_buffer[0] = (byte)n;
@@ -688,7 +684,7 @@ namespace System.IO
n = _stream.Read(_buffer, bytesRead, numBytes - bytesRead);
if (n == 0)
{
- throw new EndOfStreamException(SR.IO_EOF_ReadBeyondEOF);
+ throw Error.GetEndOfFile();
}
bytesRead += n;
} while (bytesRead < numBytes);
diff --git a/src/System.Private.CoreLib/shared/System/IO/BinaryWriter.cs b/src/System.Private.CoreLib/shared/System/IO/BinaryWriter.cs
index ad1d31f57..d1a333f41 100644
--- a/src/System.Private.CoreLib/shared/System/IO/BinaryWriter.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/BinaryWriter.cs
@@ -166,7 +166,7 @@ namespace System.IO
//
public unsafe virtual void Write(char ch)
{
- if (Char.IsSurrogate(ch))
+ if (char.IsSurrogate(ch))
throw new ArgumentException(SR.Arg_SurrogatesNotAllowedAsSingleChar);
Debug.Assert(_encoding.GetMaxByteCount(1) <= 16, "_encoding.GetMaxByteCount(1) <= 16)");
@@ -223,7 +223,7 @@ namespace System.IO
public virtual void Write(decimal value)
{
- Decimal.GetBytes(value, _buffer);
+ decimal.GetBytes(value, _buffer);
OutStream.Write(_buffer, 0, 16);
}
@@ -325,7 +325,7 @@ namespace System.IO
// a four-byte unsigned integer, and then writes that many characters
// to the stream.
//
- public unsafe virtual void Write(String value)
+ public unsafe virtual void Write(string value)
{
if (value == null)
throw new ArgumentNullException(nameof(value));
diff --git a/src/System.Private.CoreLib/shared/System/IO/DisableMediaInsertionPrompt.cs b/src/System.Private.CoreLib/shared/System/IO/DisableMediaInsertionPrompt.cs
index aa10e8d88..a3a2d2983 100644
--- a/src/System.Private.CoreLib/shared/System/IO/DisableMediaInsertionPrompt.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/DisableMediaInsertionPrompt.cs
@@ -2,7 +2,13 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+#if MS_IO_REDIST
+using System;
+
+namespace Microsoft.IO
+#else
namespace System.IO
+#endif
{
/// <summary>
/// Simple wrapper to safely disable the normal media insertion prompt for
diff --git a/src/System.Private.CoreLib/shared/System/IO/DriveNotFoundException.cs b/src/System.Private.CoreLib/shared/System/IO/DriveNotFoundException.cs
deleted file mode 100644
index 3f2c88c74..000000000
--- a/src/System.Private.CoreLib/shared/System/IO/DriveNotFoundException.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Runtime.Serialization;
-
-namespace System.IO
-{
- //Thrown when trying to access a drive that is not available.
- [Serializable]
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- internal class DriveNotFoundException : IOException
- {
- public DriveNotFoundException()
- : base(SR.Arg_DriveNotFoundException)
- {
- HResult = HResults.COR_E_DIRECTORYNOTFOUND;
- }
-
- public DriveNotFoundException(string message)
- : base(message)
- {
- HResult = HResults.COR_E_DIRECTORYNOTFOUND;
- }
-
- public DriveNotFoundException(string message, Exception innerException)
- : base(message, innerException)
- {
- HResult = HResults.COR_E_DIRECTORYNOTFOUND;
- }
-
- protected DriveNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
- }
-}
diff --git a/src/System.Private.CoreLib/shared/System/IO/FileStream.Unix.cs b/src/System.Private.CoreLib/shared/System/IO/FileStream.Unix.cs
index d9fcf6571..ae4b709ea 100644
--- a/src/System.Private.CoreLib/shared/System/IO/FileStream.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/FileStream.Unix.cs
@@ -61,10 +61,12 @@ namespace System.IO
return SafeFileHandle.Open(_path, openFlags, (int)OpenPermissions);
}
+ private static bool GetDefaultIsAsync(SafeFileHandle handle) => handle.IsAsync ?? DefaultIsAsync;
+
/// <summary>Initializes a stream for reading or writing a Unix file.</summary>
/// <param name="mode">How the file should be opened.</param>
/// <param name="share">What other access to the file should be allowed. This is currently ignored.</param>
- private void Init(FileMode mode, FileShare share)
+ private void Init(FileMode mode, FileShare share, string originalPath)
{
_fileHandle.IsAsync = _useAsyncIO;
diff --git a/src/System.Private.CoreLib/shared/System/IO/FileStream.Win32.cs b/src/System.Private.CoreLib/shared/System/IO/FileStream.Win32.cs
index 4b75ad6da..edcf8e546 100644
--- a/src/System.Private.CoreLib/shared/System/IO/FileStream.Win32.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/FileStream.Win32.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Diagnostics;
using Microsoft.Win32.SafeHandles;
namespace System.IO
@@ -43,5 +44,62 @@ namespace System.IO
Interop.Kernel32.CreateFile(_path, fAccess, share, ref secAttrs, mode, flagsAndAttributes, IntPtr.Zero));
}
}
+
+ private static bool GetDefaultIsAsync(SafeFileHandle handle)
+ {
+ return handle.IsAsync ?? !IsHandleSynchronous(handle, ignoreInvalid: true) ?? DefaultIsAsync;
+ }
+
+ private static unsafe bool? IsHandleSynchronous(SafeFileHandle fileHandle, bool ignoreInvalid)
+ {
+ if (fileHandle.IsInvalid)
+ return null;
+
+ uint fileMode;
+
+ int status = Interop.NtDll.NtQueryInformationFile(
+ FileHandle: fileHandle,
+ IoStatusBlock: out Interop.NtDll.IO_STATUS_BLOCK ioStatus,
+ FileInformation: &fileMode,
+ Length: sizeof(uint),
+ FileInformationClass: Interop.NtDll.FileModeInformation);
+
+ switch (status)
+ {
+ case 0:
+ // We we're successful
+ break;
+ case Interop.NtDll.STATUS_INVALID_HANDLE:
+ if (!ignoreInvalid)
+ {
+ throw Win32Marshal.GetExceptionForWin32Error(Interop.Errors.ERROR_INVALID_HANDLE);
+ }
+ else
+ {
+ return null;
+ }
+ default:
+ // Something else is preventing access
+ Debug.Fail("Unable to get the file mode information, status was" + status.ToString());
+ return null;
+ }
+
+ // If either of these two flags are set, the file handle is synchronous (not overlapped)
+ return (fileMode & (Interop.NtDll.FILE_SYNCHRONOUS_IO_ALERT | Interop.NtDll.FILE_SYNCHRONOUS_IO_NONALERT)) > 0;
+ }
+
+ private static void VerifyHandleIsSync(SafeFileHandle handle, int fileType, FileAccess access)
+ {
+ // As we can accurately check the handle type when we have access to NtQueryInformationFile we don't need to skip for
+ // any particular file handle type.
+
+ // If the handle was passed in without an explicit async setting, we already looked it up in GetDefaultIsAsync
+ if (!handle.IsAsync.HasValue)
+ return;
+
+ // If we can't check the handle, just assume it is ok.
+ if (!(IsHandleSynchronous(handle, ignoreInvalid: false) ?? true))
+ throw new ArgumentException(SR.Arg_HandleNotSync, nameof(handle));
+ }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/IO/FileStream.WinRT.cs b/src/System.Private.CoreLib/shared/System/IO/FileStream.WinRT.cs
index 304088eea..b326525a7 100644
--- a/src/System.Private.CoreLib/shared/System/IO/FileStream.WinRT.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/FileStream.WinRT.cs
@@ -40,5 +40,58 @@ namespace System.IO
pCreateExParams: ref parameters));
}
}
+
+ private static bool GetDefaultIsAsync(SafeFileHandle handle) => handle.IsAsync ?? DefaultIsAsync;
+
+ private static unsafe bool? IsHandleSynchronous(SafeFileHandle handle, FileAccess access)
+ {
+ // Do NOT use this method on any type other than DISK. Reading or writing to a pipe may
+ // cause an app to block incorrectly, introducing a deadlock (depending on whether a write
+ // will wake up an already-blocked thread or this Win32FileStream's thread).
+
+ byte* bytes = stackalloc byte[1];
+ int numBytesReadWritten;
+ int r = -1;
+
+ // If the handle is a pipe, ReadFile will block until there
+ // has been a write on the other end. We'll just have to deal with it,
+ // For the read end of a pipe, you can mess up and
+ // accidentally read synchronously from an async pipe.
+ if ((access & FileAccess.Read) != 0)
+ {
+ r = Interop.Kernel32.ReadFile(handle, bytes, 0, out numBytesReadWritten, IntPtr.Zero);
+ }
+ else if ((access & FileAccess.Write) != 0)
+ {
+ r = Interop.Kernel32.WriteFile(handle, bytes, 0, out numBytesReadWritten, IntPtr.Zero);
+ }
+
+ if (r == 0)
+ {
+ int errorCode = Marshal.GetLastWin32Error();
+ switch (errorCode)
+ {
+ case Interop.Errors.ERROR_INVALID_PARAMETER:
+ return false;
+ case Interop.Errors.ERROR_INVALID_HANDLE:
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode);
+ }
+ }
+
+ return true;
+ }
+
+ private static void VerifyHandleIsSync(SafeFileHandle handle, int fileType, FileAccess access)
+ {
+ // The technique here only really works for FILE_TYPE_DISK. FileMode is the right thing to check, but it currently
+ // isn't available in WinRT.
+
+ if (fileType == Interop.Kernel32.FileTypes.FILE_TYPE_DISK)
+ {
+ // If we can't check the handle, just assume it is ok.
+ if (!(IsHandleSynchronous(handle, access) ?? true))
+ throw new ArgumentException(SR.Arg_HandleNotSync, nameof(handle));
+ }
+ }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/IO/FileStream.Windows.cs b/src/System.Private.CoreLib/shared/System/IO/FileStream.Windows.cs
index 291a30bb5..ddbac1bf7 100644
--- a/src/System.Private.CoreLib/shared/System/IO/FileStream.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/FileStream.Windows.cs
@@ -52,17 +52,29 @@ namespace System.IO
private PreAllocatedOverlapped _preallocatedOverlapped; // optimization for async ops to avoid per-op allocations
private FileStreamCompletionSource _currentOverlappedOwner; // async op currently using the preallocated overlapped
- private void Init(FileMode mode, FileShare share)
+ private void Init(FileMode mode, FileShare share, string originalPath)
{
- // Disallow access to all non-file devices from the Win32FileStream
- // constructors that take a String. Everyone else can call
- // CreateFile themselves then use the constructor that takes an
- // IntPtr. Disallows "con:", "com1:", "lpt1:", etc.
- int fileType = Interop.Kernel32.GetFileType(_fileHandle);
- if (fileType != Interop.Kernel32.FileTypes.FILE_TYPE_DISK)
+ if (!PathInternal.IsExtended(originalPath))
{
- _fileHandle.Dispose();
- throw new NotSupportedException(SR.NotSupported_FileStreamOnNonFiles);
+ // To help avoid stumbling into opening COM/LPT ports by accident, we will block on non file handles unless
+ // we were explicitly passed a path that has \\?\. GetFullPath() will turn paths like C:\foo\con.txt into
+ // \\.\CON, so we'll only allow the \\?\ syntax.
+
+ int fileType = Interop.Kernel32.GetFileType(_fileHandle);
+ if (fileType != Interop.Kernel32.FileTypes.FILE_TYPE_DISK)
+ {
+ int errorCode = fileType == Interop.Kernel32.FileTypes.FILE_TYPE_UNKNOWN
+ ? Marshal.GetLastWin32Error()
+ : Interop.Errors.ERROR_SUCCESS;
+
+ _fileHandle.Dispose();
+
+ if (errorCode != Interop.Errors.ERROR_SUCCESS)
+ {
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode);
+ }
+ throw new NotSupportedException(SR.NotSupported_FileStreamOnNonFiles);
+ }
}
// This is necessary for async IO using IO Completion ports via our
@@ -161,8 +173,7 @@ namespace System.IO
}
else if (!useAsyncIO)
{
- if (handleType != Interop.Kernel32.FileTypes.FILE_TYPE_PIPE)
- VerifyHandleIsSync(handle, access);
+ VerifyHandleIsSync(handle, handleType, access);
}
if (_canSeek)
@@ -171,75 +182,31 @@ namespace System.IO
_filePosition = 0;
}
- private unsafe static Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share)
+ private static unsafe Interop.Kernel32.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share)
{
- Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default(Interop.Kernel32.SECURITY_ATTRIBUTES);
+ Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = default;
if ((share & FileShare.Inheritable) != 0)
{
- secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES();
- secAttrs.nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES);
-
- secAttrs.bInheritHandle = Interop.BOOL.TRUE;
- }
- return secAttrs;
- }
-
- // Verifies that this handle supports synchronous IO operations (unless you
- // didn't open it for either reading or writing).
- private unsafe static void VerifyHandleIsSync(SafeFileHandle handle, FileAccess access)
- {
- // Do NOT use this method on pipes. Reading or writing to a pipe may
- // cause an app to block incorrectly, introducing a deadlock (depending
- // on whether a write will wake up an already-blocked thread or this
- // Win32FileStream's thread).
- Debug.Assert(Interop.Kernel32.GetFileType(handle) != Interop.Kernel32.FileTypes.FILE_TYPE_PIPE);
-
- byte* bytes = stackalloc byte[1];
- int numBytesReadWritten;
- int r = -1;
-
- // If the handle is a pipe, ReadFile will block until there
- // has been a write on the other end. We'll just have to deal with it,
- // For the read end of a pipe, you can mess up and
- // accidentally read synchronously from an async pipe.
- if ((access & FileAccess.Read) != 0) // don't use the virtual CanRead or CanWrite, as this may be used in the ctor
- {
- r = Interop.Kernel32.ReadFile(handle, bytes, 0, out numBytesReadWritten, IntPtr.Zero);
- }
- else if ((access & FileAccess.Write) != 0) // don't use the virtual CanRead or CanWrite, as this may be used in the ctor
- {
- r = Interop.Kernel32.WriteFile(handle, bytes, 0, out numBytesReadWritten, IntPtr.Zero);
- }
-
- if (r == 0)
- {
- int errorCode = Marshal.GetLastWin32Error();
- switch (errorCode)
+ secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES
{
- case Interop.Errors.ERROR_INVALID_PARAMETER:
- throw new ArgumentException(SR.Arg_HandleNotSync, "handle");
- case Interop.Errors.ERROR_INVALID_HANDLE:
- throw Win32Marshal.GetExceptionForWin32Error(errorCode);
- }
+ nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES),
+ bInheritHandle = Interop.BOOL.TRUE
+ };
}
+ return secAttrs;
}
private bool HasActiveBufferOperation
- {
- get { return _activeBufferOperation != null && !_activeBufferOperation.IsCompleted; }
- }
+ => _activeBufferOperation != null && !_activeBufferOperation.IsCompleted;
- public override bool CanSeek
- {
- get { return _canSeek; }
- }
+ public override bool CanSeek => _canSeek;
private unsafe long GetLengthInternal()
{
Interop.Kernel32.FILE_STANDARD_INFO info = new Interop.Kernel32.FILE_STANDARD_INFO();
if (!Interop.Kernel32.GetFileInformationByHandleEx(_fileHandle, Interop.Kernel32.FILE_INFO_BY_HANDLE_CLASS.FileStandardInfo, out info, (uint)sizeof(Interop.Kernel32.FILE_STANDARD_INFO)))
- throw Win32Marshal.GetExceptionForLastWin32Error();
+ throw Win32Marshal.GetExceptionForLastWin32Error(_path);
long len = info.EndOfFile;
// If we're writing near the end of the file, we must include our
// internal buffer in our Length calculation. Don't flush because
@@ -307,7 +274,7 @@ namespace System.IO
{
if (!Interop.Kernel32.FlushFileBuffers(_fileHandle))
{
- throw Win32Marshal.GetExceptionForLastWin32Error();
+ throw Win32Marshal.GetExceptionForLastWin32Error(_path);
}
}
@@ -404,7 +371,7 @@ namespace System.IO
int errorCode = Marshal.GetLastWin32Error();
if (errorCode == Interop.Errors.ERROR_INVALID_PARAMETER)
throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_FileLengthTooBig);
- throw Win32Marshal.GetExceptionForWin32Error(errorCode);
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, _path);
}
// Return file pointer to where it was before setting length
if (origPos != value)
@@ -506,8 +473,7 @@ namespace System.IO
// Make sure we are reading from the right spot
VerifyOSHandlePosition();
- int errorCode = 0;
- int r = ReadFileNative(_fileHandle, buffer, null, out errorCode);
+ int r = ReadFileNative(_fileHandle, buffer, null, out int errorCode);
if (r == -1)
{
@@ -521,7 +487,7 @@ namespace System.IO
if (errorCode == ERROR_INVALID_PARAMETER)
throw new ArgumentException(SR.Arg_HandleNotSync, "_fileHandle");
- throw Win32Marshal.GetExceptionForWin32Error(errorCode);
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, _path);
}
}
Debug.Assert(r >= 0, "FileStream's ReadNative is likely broken.");
@@ -621,17 +587,15 @@ namespace System.IO
Debug.Assert(!fileHandle.IsClosed && _canSeek, "!fileHandle.IsClosed && _canSeek");
Debug.Assert(origin >= SeekOrigin.Begin && origin <= SeekOrigin.End, "origin >= SeekOrigin.Begin && origin <= SeekOrigin.End");
- long ret = 0;
-
- if (!Interop.Kernel32.SetFilePointerEx(fileHandle, offset, out ret, (uint)origin))
+ if (!Interop.Kernel32.SetFilePointerEx(fileHandle, offset, out long ret, (uint)origin))
{
if (closeInvalidHandle)
{
- throw Win32Marshal.GetExceptionForWin32Error(GetLastWin32ErrorAndDisposeHandleIfInvalid(throwIfInvalidHandle: false));
+ throw Win32Marshal.GetExceptionForWin32Error(GetLastWin32ErrorAndDisposeHandleIfInvalid(), _path);
}
else
{
- throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
+ throw Win32Marshal.GetExceptionForLastWin32Error(_path);
}
}
@@ -739,7 +703,7 @@ namespace System.IO
// to a handle opened asynchronously.
if (errorCode == ERROR_INVALID_PARAMETER)
throw new IOException(SR.IO_FileTooLongOrHandleNotSync);
- throw Win32Marshal.GetExceptionForWin32Error(errorCode);
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, _path);
}
}
Debug.Assert(r >= 0, "FileStream's WriteCore is likely broken.");
@@ -850,7 +814,7 @@ namespace System.IO
}
}
- unsafe private Task<int> ReadNativeAsync(Memory<byte> destination, int numBufferedBytesRead, CancellationToken cancellationToken)
+ private unsafe Task<int> ReadNativeAsync(Memory<byte> destination, int numBufferedBytesRead, CancellationToken cancellationToken)
{
AssertCanRead();
Debug.Assert(_useAsyncIO, "ReadNativeAsync doesn't work on synchronous file streams!");
@@ -875,7 +839,7 @@ namespace System.IO
}
else
{
- destination = default(Memory<byte>);
+ destination = default;
}
}
@@ -938,7 +902,7 @@ namespace System.IO
}
else
{
- throw Win32Marshal.GetExceptionForWin32Error(errorCode);
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, _path);
}
}
else if (cancellationToken.CanBeCanceled) // ERROR_IO_PENDING
@@ -1141,7 +1105,7 @@ namespace System.IO
}
else
{
- throw Win32Marshal.GetExceptionForWin32Error(errorCode);
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, _path);
}
}
else if (cancellationToken.CanBeCanceled) // ERROR_IO_PENDING
@@ -1238,7 +1202,7 @@ namespace System.IO
}
}
- private int GetLastWin32ErrorAndDisposeHandleIfInvalid(bool throwIfInvalidHandle = false)
+ private int GetLastWin32ErrorAndDisposeHandleIfInvalid()
{
int errorCode = Marshal.GetLastWin32Error();
@@ -1262,9 +1226,6 @@ namespace System.IO
if (errorCode == Interop.Errors.ERROR_INVALID_HANDLE)
{
_fileHandle.Dispose();
-
- if (throwIfInvalidHandle)
- throw Win32Marshal.GetExceptionForWin32Error(errorCode);
}
return errorCode;
@@ -1418,7 +1379,7 @@ namespace System.IO
break;
default:
// Everything else is an error (and there won't be a callback).
- throw Win32Marshal.GetExceptionForWin32Error(errorCode);
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, _path);
}
}
@@ -1436,7 +1397,7 @@ namespace System.IO
case Interop.Errors.ERROR_OPERATION_ABORTED: // canceled
throw new OperationCanceledException(cancellationToken.IsCancellationRequested ? cancellationToken : new CancellationToken(true));
default: // error
- throw Win32Marshal.GetExceptionForWin32Error((int)readAwaitable._errorCode);
+ throw Win32Marshal.GetExceptionForWin32Error((int)readAwaitable._errorCode, _path);
}
// Successful operation. If we got zero bytes, we're done: exit the read/write loop.
@@ -1535,7 +1496,7 @@ namespace System.IO
}
/// <summary>Overlapped callback: store the results, then invoke the continuation delegate.</summary>
- internal unsafe static void IOCallback(uint errorCode, uint numBytes, NativeOverlapped* pOVERLAP)
+ internal static unsafe void IOCallback(uint errorCode, uint numBytes, NativeOverlapped* pOVERLAP)
{
var awaitable = (AsyncCopyToAwaitable)ThreadPoolBoundHandle.GetNativeOverlappedState(pOVERLAP);
@@ -1623,7 +1584,7 @@ namespace System.IO
if (!Interop.Kernel32.LockFile(_fileHandle, positionLow, positionHigh, lengthLow, lengthHigh))
{
- throw Win32Marshal.GetExceptionForLastWin32Error();
+ throw Win32Marshal.GetExceptionForLastWin32Error(_path);
}
}
@@ -1636,9 +1597,10 @@ namespace System.IO
if (!Interop.Kernel32.UnlockFile(_fileHandle, positionLow, positionHigh, lengthLow, lengthHigh))
{
- throw Win32Marshal.GetExceptionForLastWin32Error();
+ throw Win32Marshal.GetExceptionForLastWin32Error(_path);
}
}
+
private SafeFileHandle ValidateFileHandle(SafeFileHandle fileHandle)
{
if (fileHandle.IsInvalid)
diff --git a/src/System.Private.CoreLib/shared/System/IO/FileStream.cs b/src/System.Private.CoreLib/shared/System/IO/FileStream.cs
index 717b73ff1..fadbef880 100644
--- a/src/System.Private.CoreLib/shared/System/IO/FileStream.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/FileStream.cs
@@ -6,7 +6,6 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.Win32.SafeHandles;
using System.Diagnostics;
-using System.Security;
namespace System.IO
{
@@ -233,7 +232,7 @@ namespace System.IO
try
{
- Init(mode, share);
+ Init(mode, share, path);
}
catch
{
@@ -245,12 +244,6 @@ namespace System.IO
}
}
- private static bool GetDefaultIsAsync(SafeFileHandle handle)
- {
- // This will eventually get more complicated as we can actually check the underlying handle type on Windows
- return handle.IsAsync.HasValue ? handle.IsAsync.Value : false;
- }
-
[Obsolete("This property has been deprecated. Please use FileStream's SafeFileHandle property instead. http://go.microsoft.com/fwlink/?linkid=14202")]
public virtual IntPtr Handle { get { return SafeFileHandle.DangerousGetHandle(); } }
@@ -304,7 +297,7 @@ namespace System.IO
ReadSpan(new Span<byte>(array, offset, count));
}
- public override int Read(Span<byte> destination)
+ public override int Read(Span<byte> buffer)
{
if (GetType() == typeof(FileStream) && !_useAsyncIO)
{
@@ -312,7 +305,7 @@ namespace System.IO
{
throw Error.GetFileNotOpen();
}
- return ReadSpan(destination);
+ return ReadSpan(buffer);
}
else
{
@@ -322,7 +315,7 @@ namespace System.IO
// of Read(byte[],int,int) overload. Or if the stream is in async mode, we can't call the
// synchronous ReadSpan, so we similarly call the base Read, which will turn delegate to
// Read(byte[],int,int), which will do the right thing if we're in async mode.
- return base.Read(destination);
+ return base.Read(buffer);
}
}
@@ -355,14 +348,14 @@ namespace System.IO
return ReadAsyncTask(buffer, offset, count, cancellationToken);
}
- public override ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken = default(CancellationToken))
+ public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
{
if (!_useAsyncIO || GetType() != typeof(FileStream))
{
// If we're not using async I/O, delegate to the base, which will queue a call to Read.
// Or if this isn't a concrete FileStream, a derived type may have overridden ReadAsync(byte[],...),
// which was introduced first, so delegate to the base which will delegate to that.
- return base.ReadAsync(destination, cancellationToken);
+ return base.ReadAsync(buffer, cancellationToken);
}
if (cancellationToken.IsCancellationRequested)
@@ -375,7 +368,7 @@ namespace System.IO
throw Error.GetFileNotOpen();
}
- Task<int> t = ReadAsyncInternal(destination, cancellationToken, out int synchronousResult);
+ Task<int> t = ReadAsyncInternal(buffer, cancellationToken, out int synchronousResult);
return t != null ?
new ValueTask<int>(t) :
new ValueTask<int>(synchronousResult);
@@ -412,7 +405,7 @@ namespace System.IO
}
}
- public override void Write(ReadOnlySpan<byte> destination)
+ public override void Write(ReadOnlySpan<byte> buffer)
{
if (GetType() == typeof(FileStream) && !_useAsyncIO)
{
@@ -420,7 +413,7 @@ namespace System.IO
{
throw Error.GetFileNotOpen();
}
- WriteSpan(destination);
+ WriteSpan(buffer);
}
else
{
@@ -430,7 +423,7 @@ namespace System.IO
// of Write(byte[],int,int) overload. Or if the stream is in async mode, we can't call the
// synchronous WriteSpan, so we similarly call the base Write, which will turn delegate to
// Write(byte[],int,int), which will do the right thing if we're in async mode.
- base.Write(destination);
+ base.Write(buffer);
}
}
@@ -461,14 +454,14 @@ namespace System.IO
return WriteAsyncInternal(new ReadOnlyMemory<byte>(buffer, offset, count), cancellationToken).AsTask();
}
- public override ValueTask WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default(CancellationToken))
+ public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
{
if (!_useAsyncIO || GetType() != typeof(FileStream))
{
// If we're not using async I/O, delegate to the base, which will queue a call to Write.
// Or if this isn't a concrete FileStream, a derived type may have overridden WriteAsync(byte[],...),
// which was introduced first, so delegate to the base which will delegate to that.
- return base.WriteAsync(source, cancellationToken);
+ return base.WriteAsync(buffer, cancellationToken);
}
if (cancellationToken.IsCancellationRequested)
@@ -481,7 +474,7 @@ namespace System.IO
throw Error.GetFileNotOpen();
}
- return WriteAsyncInternal(source, cancellationToken);
+ return WriteAsyncInternal(buffer, cancellationToken);
}
/// <summary>
diff --git a/src/System.Private.CoreLib/shared/System/IO/FileStreamCompletionSource.Win32.cs b/src/System.Private.CoreLib/shared/System/IO/FileStreamCompletionSource.Win32.cs
index 82274b131..62ace0918 100644
--- a/src/System.Private.CoreLib/shared/System/IO/FileStreamCompletionSource.Win32.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/FileStreamCompletionSource.Win32.cs
@@ -246,7 +246,7 @@ namespace System.IO
internal MemoryFileStreamCompletionSource(FileStream stream, int numBufferedBytes, ReadOnlyMemory<byte> memory) :
base(stream, numBufferedBytes, bytes: null) // this type handles the pinning, so null is passed for bytes
{
- _handle = memory.Retain(pin: true);
+ _handle = memory.Pin();
}
internal override void ReleaseNativeResource()
diff --git a/src/System.Private.CoreLib/shared/System/IO/IOException.cs b/src/System.Private.CoreLib/shared/System/IO/IOException.cs
index 89b25d514..04e653206 100644
--- a/src/System.Private.CoreLib/shared/System/IO/IOException.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/IOException.cs
@@ -17,19 +17,19 @@ namespace System.IO
HResult = HResults.COR_E_IO;
}
- public IOException(String message)
+ public IOException(string message)
: base(message)
{
HResult = HResults.COR_E_IO;
}
- public IOException(String message, int hresult)
+ public IOException(string message, int hresult)
: base(message)
{
HResult = hresult;
}
- public IOException(String message, Exception innerException)
+ public IOException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_IO;
diff --git a/src/System.Private.CoreLib/shared/System/IO/MemoryStream.cs b/src/System.Private.CoreLib/shared/System/IO/MemoryStream.cs
index ffe7f6093..9bac0d818 100644
--- a/src/System.Private.CoreLib/shared/System/IO/MemoryStream.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/MemoryStream.cs
@@ -208,7 +208,7 @@ namespace System.IO
{
if (!_exposable)
{
- buffer = default(ArraySegment<byte>);
+ buffer = default;
return false;
}
@@ -367,19 +367,19 @@ namespace System.IO
return n;
}
- public override int Read(Span<byte> destination)
+ public override int Read(Span<byte> buffer)
{
if (GetType() != typeof(MemoryStream))
{
// MemoryStream is not sealed, and a derived type may have overridden Read(byte[], int, int) prior
// to this Read(Span<byte>) overload being introduced. In that case, this Read(Span<byte>) overload
// should use the behavior of Read(byte[],int,int) overload.
- return base.Read(destination);
+ return base.Read(buffer);
}
EnsureNotClosed();
- int n = Math.Min(_length - _position, destination.Length);
+ int n = Math.Min(_length - _position, buffer.Length);
if (n <= 0)
return 0;
@@ -387,13 +387,13 @@ namespace System.IO
// Read(byte[], int, int) has an n <= 8 optimization, presumably based
// on benchmarking. Determine if/where such a cut-off is here and add
// an equivalent optimization if necessary.
- new Span<byte>(_buffer, _position, n).CopyTo(destination);
+ new Span<byte>(_buffer, _position, n).CopyTo(buffer);
_position += n;
return n;
}
- public override Task<int> ReadAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer), SR.ArgumentNull_Buffer);
@@ -426,7 +426,7 @@ namespace System.IO
}
}
- public override ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken = default(CancellationToken))
+ public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -448,9 +448,9 @@ namespace System.IO
// something other than an array and this is a MemoryStream-derived type that doesn't override Read(Span<byte>) will
// it then fall back to doing the ArrayPool/copy behavior.
return new ValueTask<int>(
- MemoryMarshal.TryGetArray(destination, out ArraySegment<byte> destinationArray) ?
+ MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> destinationArray) ?
Read(destinationArray.Array, destinationArray.Offset, destinationArray.Count) :
- Read(destination.Span));
+ Read(buffer.Span));
}
catch (OperationCanceledException oce)
{
@@ -681,14 +681,14 @@ namespace System.IO
_position = i;
}
- public override void Write(ReadOnlySpan<byte> source)
+ public override void Write(ReadOnlySpan<byte> buffer)
{
if (GetType() != typeof(MemoryStream))
{
// MemoryStream is not sealed, and a derived type may have overridden Write(byte[], int, int) prior
// to this Write(Span<byte>) overload being introduced. In that case, this Write(Span<byte>) overload
// should use the behavior of Write(byte[],int,int) overload.
- base.Write(source);
+ base.Write(buffer);
return;
}
@@ -696,7 +696,7 @@ namespace System.IO
EnsureWriteable();
// Check for overflow
- int i = _position + source.Length;
+ int i = _position + buffer.Length;
if (i < 0)
throw new IOException(SR.IO_StreamTooLong);
@@ -718,11 +718,11 @@ namespace System.IO
_length = i;
}
- source.CopyTo(new Span<byte>(_buffer, _position, source.Length));
+ buffer.CopyTo(new Span<byte>(_buffer, _position, buffer.Length));
_position = i;
}
- public override Task WriteAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer), SR.ArgumentNull_Buffer);
@@ -752,7 +752,7 @@ namespace System.IO
}
}
- public override ValueTask WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default(CancellationToken))
+ public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -763,13 +763,13 @@ namespace System.IO
{
// See corresponding comment in ReadAsync for why we don't just always use Write(ReadOnlySpan<byte>).
// Unlike ReadAsync, we could delegate to WriteAsync(byte[], ...) here, but we don't for consistency.
- if (MemoryMarshal.TryGetArray(source, out ArraySegment<byte> sourceArray))
+ if (MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> sourceArray))
{
Write(sourceArray.Array, sourceArray.Offset, sourceArray.Count);
}
else
{
- Write(source.Span);
+ Write(buffer.Span);
}
return default;
}
diff --git a/src/System.Private.CoreLib/shared/System/IO/Path.Unix.cs b/src/System.Private.CoreLib/shared/System/IO/Path.Unix.cs
index fd24cc810..ecf71e612 100644
--- a/src/System.Private.CoreLib/shared/System/IO/Path.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/Path.Unix.cs
@@ -23,7 +23,7 @@ namespace System.IO
if (path.Length == 0)
throw new ArgumentException(SR.Arg_PathEmpty, nameof(path));
- if (path.IndexOf('\0') != -1)
+ if (path.Contains('\0'))
throw new ArgumentException(SR.Argument_InvalidPathChars, nameof(path));
// Expand with current directory if necessary
@@ -34,7 +34,7 @@ namespace System.IO
// We would ideally use realpath to do this, but it resolves symlinks, requires that the file actually exist,
// and turns it into a full path, which we only want if fullCheck is true.
- string collapsedString = RemoveRelativeSegments(path);
+ string collapsedString = PathInternal.RemoveRelativeSegments(path, PathInternal.GetRootLength(path));
Debug.Assert(collapsedString.Length < path.Length || collapsedString.ToString() == path,
"Either we've removed characters, or the string should be unmodified from the input path.");
diff --git a/src/System.Private.CoreLib/shared/System/IO/Path.Windows.cs b/src/System.Private.CoreLib/shared/System/IO/Path.Windows.cs
index b921db9e6..ddfd7966b 100644
--- a/src/System.Private.CoreLib/shared/System/IO/Path.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/Path.Windows.cs
@@ -5,7 +5,14 @@
using System.Diagnostics;
using System.Text;
+#if MS_IO_REDIST
+using System;
+using System.IO;
+
+namespace Microsoft.IO
+#else
namespace System.IO
+#endif
{
public static partial class Path
{
@@ -34,16 +41,16 @@ namespace System.IO
throw new ArgumentNullException(nameof(path));
// If the path would normalize to string empty, we'll consider it empty
- if (PathInternal.IsEffectivelyEmpty(path))
+ if (PathInternal.IsEffectivelyEmpty(path.AsSpan()))
throw new ArgumentException(SR.Arg_PathEmpty, nameof(path));
// Embedded null characters are the only invalid character case we trully care about.
// This is because the nulls will signal the end of the string to Win32 and therefore have
// unpredictable results.
- if (path.IndexOf('\0') != -1)
+ if (path.Contains('\0'))
throw new ArgumentException(SR.Argument_InvalidPathChars, nameof(path));
- if (PathInternal.IsExtended(path))
+ if (PathInternal.IsExtended(path.AsSpan()))
{
// \\?\ paths are considered normalized by definition. Windows doesn't normalize \\?\
// paths and neither should we. Even if we wanted to GetFullPathName does not work
@@ -72,6 +79,9 @@ namespace System.IO
if (IsPathFullyQualified(path))
return GetFullPath(path);
+ if (PathInternal.IsEffectivelyEmpty(path.AsSpan()))
+ return basePath;
+
int length = path.Length;
string combinedPath = null;
@@ -80,30 +90,30 @@ namespace System.IO
// Path is current drive rooted i.e. starts with \:
// "\Foo" and "C:\Bar" => "C:\Foo"
// "\Foo" and "\\?\C:\Bar" => "\\?\C:\Foo"
- combinedPath = Join(GetPathRoot(basePath.AsSpan()), path);
+ combinedPath = Join(GetPathRoot(basePath.AsSpan()), path.AsSpan(1)); // Cut the separator to ensure we don't end up with two separators when joining with the root.
}
else if (length >= 2 && PathInternal.IsValidDriveChar(path[0]) && path[1] == PathInternal.VolumeSeparatorChar)
{
// Drive relative paths
Debug.Assert(length == 2 || !PathInternal.IsDirectorySeparator(path[2]));
- if (StringSpanHelpers.Equals(GetVolumeName(path), GetVolumeName(basePath)))
+ if (GetVolumeName(path.AsSpan()).EqualsOrdinal(GetVolumeName(basePath.AsSpan())))
{
// Matching root
// "C:Foo" and "C:\Bar" => "C:\Bar\Foo"
// "C:Foo" and "\\?\C:\Bar" => "\\?\C:\Bar\Foo"
- combinedPath = Join(basePath, path.AsSpan().Slice(2));
+ combinedPath = Join(basePath.AsSpan(), path.AsSpan(2));
}
else
{
// No matching root, root to specified drive
// "D:Foo" and "C:\Bar" => "D:Foo"
// "D:Foo" and "\\?\C:\Bar" => "\\?\D:\Foo"
- combinedPath = !PathInternal.IsDevice(basePath)
+ combinedPath = !PathInternal.IsDevice(basePath.AsSpan())
? path.Insert(2, @"\")
: length == 2
- ? JoinInternal(basePath.AsSpan().Slice(0, 4), path, @"\")
- : JoinInternal(basePath.AsSpan().Slice(0, 4), path.AsSpan().Slice(0, 2), @"\", path.AsSpan().Slice(2));
+ ? JoinInternal(basePath.AsSpan(0, 4), path.AsSpan(), @"\".AsSpan())
+ : JoinInternal(basePath.AsSpan(0, 4), path.AsSpan(0, 2), @"\".AsSpan(), path.AsSpan(2));
}
}
else
@@ -111,37 +121,70 @@ namespace System.IO
// "Simple" relative path
// "Foo" and "C:\Bar" => "C:\Bar\Foo"
// "Foo" and "\\?\C:\Bar" => "\\?\C:\Bar\Foo"
- combinedPath = JoinInternal(basePath, path);
+ combinedPath = JoinInternal(basePath.AsSpan(), path.AsSpan());
}
- // Device paths are normalized by definition, so passing something of this format
- // to GetFullPath() won't do anything by design. Additionally, GetFullPathName() in
- // Windows doesn't root them properly. As such we need to manually remove segments.
- return PathInternal.IsDevice(combinedPath)
- ? RemoveRelativeSegments(combinedPath, PathInternal.GetRootLength(combinedPath))
+ // Device paths are normalized by definition, so passing something of this format (i.e. \\?\C:\.\tmp, \\.\C:\foo)
+ // to Windows APIs won't do anything by design. Additionally, GetFullPathName() in Windows doesn't root
+ // them properly. As such we need to manually remove segments and not use GetFullPath().
+
+ return PathInternal.IsDevice(combinedPath.AsSpan())
+ ? PathInternal.RemoveRelativeSegments(combinedPath, PathInternal.GetRootLength(combinedPath.AsSpan()))
: GetFullPath(combinedPath);
}
public static string GetTempPath()
{
- StringBuilder sb = StringBuilderCache.Acquire(Interop.Kernel32.MAX_PATH);
- uint r = Interop.Kernel32.GetTempPathW(Interop.Kernel32.MAX_PATH, sb);
- if (r == 0)
+ Span<char> initialBuffer = stackalloc char[PathInternal.MaxShortPath];
+ var builder = new ValueStringBuilder(initialBuffer);
+
+ GetTempPath(ref builder);
+
+ string path = PathHelper.Normalize(ref builder);
+ builder.Dispose();
+ return path;
+ }
+
+ private static void GetTempPath(ref ValueStringBuilder builder)
+ {
+ uint result = 0;
+ while ((result = Interop.Kernel32.GetTempPathW(builder.Capacity, ref builder.GetPinnableReference())) > builder.Capacity)
+ {
+ // Reported size is greater than the buffer size. Increase the capacity.
+ builder.EnsureCapacity(checked((int)result));
+ }
+
+ if (result == 0)
throw Win32Marshal.GetExceptionForLastWin32Error();
- return GetFullPath(StringBuilderCache.GetStringAndRelease(sb));
+
+ builder.Length = (int)result;
}
// Returns a unique temporary file name, and creates a 0-byte file by that
// name on disk.
public static string GetTempFileName()
{
- string path = GetTempPath();
+ Span<char> initialTempPathBuffer = stackalloc char[PathInternal.MaxShortPath];
+ ValueStringBuilder tempPathBuilder = new ValueStringBuilder(initialTempPathBuffer);
+
+ GetTempPath(ref tempPathBuilder);
+
+ Span<char> initialBuffer = stackalloc char[PathInternal.MaxShortPath];
+ var builder = new ValueStringBuilder(initialBuffer);
- StringBuilder sb = StringBuilderCache.Acquire(Interop.Kernel32.MAX_PATH);
- uint r = Interop.Kernel32.GetTempFileNameW(path, "tmp", 0, sb);
- if (r == 0)
+ uint result = Interop.Kernel32.GetTempFileNameW(
+ ref tempPathBuilder.GetPinnableReference(), "tmp", 0, ref builder.GetPinnableReference());
+
+ tempPathBuilder.Dispose();
+
+ if (result == 0)
throw Win32Marshal.GetExceptionForLastWin32Error();
- return StringBuilderCache.GetStringAndRelease(sb);
+
+ builder.Length = builder.RawChars.IndexOf('\0');
+
+ string path = PathHelper.Normalize(ref builder);
+ builder.Dispose();
+ return path;
}
// Tests if the given path contains a root. A path is considered rooted
@@ -169,14 +212,14 @@ namespace System.IO
// only contains whitespace characters an ArgumentException gets thrown.
public static string GetPathRoot(string path)
{
- if (PathInternal.IsEffectivelyEmpty(path))
+ if (PathInternal.IsEffectivelyEmpty(path.AsSpan()))
return null;
ReadOnlySpan<char> result = GetPathRoot(path.AsSpan());
if (path.Length == result.Length)
return PathInternal.NormalizeDirectorySeparators(path);
- return PathInternal.NormalizeDirectorySeparators(new string(result));
+ return PathInternal.NormalizeDirectorySeparators(result.ToString());
}
/// <remarks>
@@ -237,11 +280,11 @@ namespace System.IO
{
bool isDevice = PathInternal.IsDevice(path);
- if (!isDevice && StringSpanHelpers.Equals(path.Slice(0, 2), @"\\") )
+ if (!isDevice && path.Slice(0, 2).EqualsOrdinal(@"\\".AsSpan()) )
return 2;
else if (isDevice && path.Length >= 8
- && (StringSpanHelpers.Equals(path.Slice(0, 8), PathInternal.UncExtendedPathPrefix)
- || StringSpanHelpers.Equals(path.Slice(5, 4), @"UNC\")))
+ && (path.Slice(0, 8).EqualsOrdinal(PathInternal.UncExtendedPathPrefix.AsSpan())
+ || path.Slice(5, 4).EqualsOrdinal(@"UNC\".AsSpan())))
return 8;
return -1;
diff --git a/src/System.Private.CoreLib/shared/System/IO/Path.cs b/src/System.Private.CoreLib/shared/System/IO/Path.cs
index 41ae1cd0b..7b4565a13 100644
--- a/src/System.Private.CoreLib/shared/System/IO/Path.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/Path.cs
@@ -6,7 +6,14 @@ using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
+#if MS_IO_REDIST
+using System;
+using System.IO;
+
+namespace Microsoft.IO
+#else
namespace System.IO
+#endif
{
// Provides methods for processing file system strings in a cross-platform manner.
// Most of the methods don't do a complete parsing (such as examining a UNC hostname),
@@ -79,10 +86,10 @@ namespace System.IO
/// </remarks>
public static string GetDirectoryName(string path)
{
- if (path == null || PathInternal.IsEffectivelyEmpty(path))
+ if (path == null || PathInternal.IsEffectivelyEmpty(path.AsSpan()))
return null;
- int end = GetDirectoryNameOffset(path);
+ int end = GetDirectoryNameOffset(path.AsSpan());
return end >= 0 ? PathInternal.NormalizeDirectorySeparators(path.Substring(0, end)) : null;
}
@@ -130,7 +137,7 @@ namespace System.IO
if (path == null)
return null;
- return new string(GetExtension(path.AsSpan()));
+ return GetExtension(path.AsSpan()).ToString();
}
/// <summary>
@@ -173,7 +180,7 @@ namespace System.IO
if (path.Length == result.Length)
return path;
- return new string(result);
+ return result.ToString();
}
/// <summary>
@@ -204,7 +211,7 @@ namespace System.IO
if (path.Length == result.Length)
return path;
- return new string(result);
+ return result.ToString();
}
/// <summary>
@@ -388,9 +395,9 @@ namespace System.IO
public static string Join(ReadOnlySpan<char> path1, ReadOnlySpan<char> path2)
{
if (path1.Length == 0)
- return new string(path2);
+ return path2.ToString();
if (path2.Length == 0)
- return new string(path1);
+ return path1.ToString();
return JoinInternal(path1, path2);
}
@@ -409,6 +416,16 @@ namespace System.IO
return JoinInternal(path1, path2, path3);
}
+ public static string Join(string path1, string path2)
+ {
+ return Join(path1.AsSpan(), path2.AsSpan());
+ }
+
+ public static string Join(string path1, string path2, string path3)
+ {
+ return Join(path1.AsSpan(), path2.AsSpan(), path3.AsSpan());
+ }
+
public static bool TryJoin(ReadOnlySpan<char> path1, ReadOnlySpan<char> path2, Span<char> destination, out int charsWritten)
{
charsWritten = 0;
@@ -477,22 +494,6 @@ namespace System.IO
return true;
}
- private static string CombineInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second)
- {
- if (first.Length == 0)
- return second.Length == 0
- ? string.Empty
- : new string(second);
-
- if (second.Length == 0)
- return new string(first);
-
- if (IsPathRooted(second))
- return new string(second);
-
- return JoinInternal(first, second);
- }
-
private static string CombineInternal(string first, string second)
{
if (string.IsNullOrEmpty(first))
@@ -504,7 +505,7 @@ namespace System.IO
if (IsPathRooted(second.AsSpan()))
return second;
- return JoinInternal(first, second);
+ return JoinInternal(first.AsSpan(), second.AsSpan());
}
private static string CombineInternal(string first, string second, string third)
@@ -521,7 +522,7 @@ namespace System.IO
if (IsPathRooted(second.AsSpan()))
return CombineInternal(second, third);
- return JoinInternal(first, second, third);
+ return JoinInternal(first.AsSpan(), second.AsSpan(), third.AsSpan());
}
private static string CombineInternal(string first, string second, string third, string fourth)
@@ -542,10 +543,10 @@ namespace System.IO
if (IsPathRooted(second.AsSpan()))
return CombineInternal(second, third, fourth);
- return JoinInternal(first, second, third, fourth);
+ return JoinInternal(first.AsSpan(), second.AsSpan(), third.AsSpan(), fourth.AsSpan());
}
- private unsafe static string JoinInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second)
+ private static unsafe string JoinInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second)
{
Debug.Assert(first.Length > 0 && second.Length > 0, "should have dealt with empty paths");
@@ -554,7 +555,11 @@ namespace System.IO
fixed (char* f = &MemoryMarshal.GetReference(first), s = &MemoryMarshal.GetReference(second))
{
+#if MS_IO_REDIST
+ return StringExtensions.Create(
+#else
return string.Create(
+#endif
first.Length + second.Length + (hasSeparator ? 0 : 1),
(First: (IntPtr)f, FirstLength: first.Length, Second: (IntPtr)s, SecondLength: second.Length, HasSeparator: hasSeparator),
(destination, state) =>
@@ -567,7 +572,7 @@ namespace System.IO
}
}
- private unsafe static string JoinInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second, ReadOnlySpan<char> third)
+ private static unsafe string JoinInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second, ReadOnlySpan<char> third)
{
Debug.Assert(first.Length > 0 && second.Length > 0 && third.Length > 0, "should have dealt with empty paths");
@@ -578,7 +583,11 @@ namespace System.IO
fixed (char* f = &MemoryMarshal.GetReference(first), s = &MemoryMarshal.GetReference(second), t = &MemoryMarshal.GetReference(third))
{
+#if MS_IO_REDIST
+ return StringExtensions.Create(
+#else
return string.Create(
+#endif
first.Length + second.Length + third.Length + (firstHasSeparator ? 0 : 1) + (thirdHasSeparator ? 0 : 1),
(First: (IntPtr)f, FirstLength: first.Length, Second: (IntPtr)s, SecondLength: second.Length,
Third: (IntPtr)t, ThirdLength: third.Length, FirstHasSeparator: firstHasSeparator, ThirdHasSeparator: thirdHasSeparator),
@@ -595,7 +604,7 @@ namespace System.IO
}
}
- private unsafe static string JoinInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second, ReadOnlySpan<char> third, ReadOnlySpan<char> fourth)
+ private static unsafe string JoinInternal(ReadOnlySpan<char> first, ReadOnlySpan<char> second, ReadOnlySpan<char> third, ReadOnlySpan<char> fourth)
{
Debug.Assert(first.Length > 0 && second.Length > 0 && third.Length > 0 && fourth.Length > 0, "should have dealt with empty paths");
@@ -608,7 +617,12 @@ namespace System.IO
fixed (char* f = &MemoryMarshal.GetReference(first), s = &MemoryMarshal.GetReference(second), t = &MemoryMarshal.GetReference(third), u = &MemoryMarshal.GetReference(fourth))
{
+
+#if MS_IO_REDIST
+ return StringExtensions.Create(
+#else
return string.Create(
+#endif
first.Length + second.Length + third.Length + fourth.Length + (firstHasSeparator ? 0 : 1) + (thirdHasSeparator ? 0 : 1) + (fourthHasSeparator ? 0 : 1),
(First: (IntPtr)f, FirstLength: first.Length, Second: (IntPtr)s, SecondLength: second.Length,
Third: (IntPtr)t, ThirdLength: third.Length, Fourth: (IntPtr)u, FourthLength:fourth.Length,
@@ -688,93 +702,6 @@ namespace System.IO
}
/// <summary>
- /// Try to remove relative segments from the given path (without combining with a root).
- /// </summary>
- /// <param name="skip">Skip the specified number of characters before evaluating.</param>
- private static string RemoveRelativeSegments(string path, int skip = 0)
- {
- bool flippedSeparator = false;
-
- // Remove "//", "/./", and "/../" from the path by copying each character to the output,
- // except the ones we're removing, such that the builder contains the normalized path
- // at the end.
- StringBuilder sb = StringBuilderCache.Acquire(path.Length);
- if (skip > 0)
- {
- sb.Append(path, 0, skip);
- }
-
- for (int i = skip; i < path.Length; i++)
- {
- char c = path[i];
-
- if (PathInternal.IsDirectorySeparator(c) && i + 1 < path.Length)
- {
- // Skip this character if it's a directory separator and if the next character is, too,
- // e.g. "parent//child" => "parent/child"
- if (PathInternal.IsDirectorySeparator(path[i + 1]))
- {
- continue;
- }
-
- // Skip this character and the next if it's referring to the current directory,
- // e.g. "parent/./child" => "parent/child"
- if ((i + 2 == path.Length || PathInternal.IsDirectorySeparator(path[i + 2])) &&
- path[i + 1] == '.')
- {
- i++;
- continue;
- }
-
- // Skip this character and the next two if it's referring to the parent directory,
- // e.g. "parent/child/../grandchild" => "parent/grandchild"
- if (i + 2 < path.Length &&
- (i + 3 == path.Length || PathInternal.IsDirectorySeparator(path[i + 3])) &&
- path[i + 1] == '.' && path[i + 2] == '.')
- {
- // Unwind back to the last slash (and if there isn't one, clear out everything).
- int s;
- for (s = sb.Length - 1; s >= 0; s--)
- {
- if (PathInternal.IsDirectorySeparator(sb[s]))
- {
- sb.Length = s;
- break;
- }
- }
- if (s < 0)
- {
- sb.Length = 0;
- }
-
- i += 2;
- continue;
- }
- }
-
- // Normalize the directory separator if needed
- if (c != PathInternal.DirectorySeparatorChar && c == PathInternal.AltDirectorySeparatorChar)
- {
- c = PathInternal.DirectorySeparatorChar;
- flippedSeparator = true;
- }
-
- sb.Append(c);
- }
-
- if (flippedSeparator || sb.Length != path.Length)
- {
- return StringBuilderCache.GetStringAndRelease(sb);
- }
- else
- {
- // We haven't changed the source path, return the original
- StringBuilderCache.Release(sb);
- return path;
- }
- }
-
- /// <summary>
/// Create a relative path from one path to another. Paths will be resolved before calculating the difference.
/// Default path comparison for the active platform will be used (OrdinalIgnoreCase for Windows or Mac, Ordinal for Unix).
/// </summary>
@@ -790,7 +717,7 @@ namespace System.IO
private static string GetRelativePath(string relativeTo, string path, StringComparison comparisonType)
{
if (string.IsNullOrEmpty(relativeTo)) throw new ArgumentNullException(nameof(relativeTo));
- if (PathInternal.IsEffectivelyEmpty(path)) throw new ArgumentNullException(nameof(path));
+ if (PathInternal.IsEffectivelyEmpty(path.AsSpan())) throw new ArgumentNullException(nameof(path));
Debug.Assert(comparisonType == StringComparison.Ordinal || comparisonType == StringComparison.OrdinalIgnoreCase);
relativeTo = GetFullPath(relativeTo);
@@ -808,10 +735,10 @@ namespace System.IO
// Trailing separators aren't significant for comparison
int relativeToLength = relativeTo.Length;
- if (PathInternal.EndsInDirectorySeparator(relativeTo))
+ if (PathInternal.EndsInDirectorySeparator(relativeTo.AsSpan()))
relativeToLength--;
- bool pathEndsInSeparator = PathInternal.EndsInDirectorySeparator(path);
+ bool pathEndsInSeparator = PathInternal.EndsInDirectorySeparator(path.AsSpan());
int pathLength = path.Length;
if (pathEndsInSeparator)
pathLength--;
@@ -834,13 +761,14 @@ namespace System.IO
// Add parent segments for segments past the common on the "from" path
if (commonLength < relativeToLength)
{
- sb.Append(PathInternal.ParentDirectoryPrefix);
+ sb.Append("..");
- for (int i = commonLength; i < relativeToLength; i++)
+ for (int i = commonLength + 1; i < relativeToLength; i++)
{
if (PathInternal.IsDirectorySeparator(relativeTo[i]))
{
- sb.Append(PathInternal.ParentDirectoryPrefix);
+ sb.Append(DirectorySeparatorChar);
+ sb.Append("..");
}
}
}
@@ -852,11 +780,20 @@ namespace System.IO
}
// Now add the rest of the "to" path, adding back the trailing separator
- int count = pathLength - commonLength;
+ int differenceLength = pathLength - commonLength;
if (pathEndsInSeparator)
- count++;
+ differenceLength++;
+
+ if (differenceLength > 0)
+ {
+ if (sb.Length > 0)
+ {
+ sb.Append(DirectorySeparatorChar);
+ }
+
+ sb.Append(path, commonLength, differenceLength);
+ }
- sb.Append(path, commonLength, count);
return StringBuilderCache.GetStringAndRelease(sb);
}
diff --git a/src/System.Private.CoreLib/shared/System/IO/PathHelper.Windows.cs b/src/System.Private.CoreLib/shared/System/IO/PathHelper.Windows.cs
index 74ceed10a..bada2f5cd 100644
--- a/src/System.Private.CoreLib/shared/System/IO/PathHelper.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/PathHelper.Windows.cs
@@ -26,30 +26,57 @@ namespace System.IO
internal static string Normalize(string path)
{
Span<char> initialBuffer = stackalloc char[PathInternal.MaxShortPath];
- ValueStringBuilder builder = new ValueStringBuilder(initialBuffer);
+ var builder = new ValueStringBuilder(initialBuffer);
// Get the full path
- GetFullPathName(path, ref builder);
+ GetFullPathName(path.AsSpan(), ref builder);
// If we have the exact same string we were passed in, don't allocate another string.
// TryExpandShortName does this input identity check.
- string result = builder.AsSpan().Contains('~')
+ string result = builder.AsSpan().IndexOf('~') >= 0
? TryExpandShortFileName(ref builder, originalPath: path)
- : builder.AsSpan().Equals(path.AsSpan()) ? path : builder.ToString();
+ : builder.AsSpan().Equals(path.AsSpan(), StringComparison.Ordinal) ? path : builder.ToString();
// Clear the buffer
builder.Dispose();
return result;
}
- private static void GetFullPathName(string path, ref ValueStringBuilder builder)
+ /// <summary>
+ /// Normalize the given path.
+ /// </summary>
+ /// <remarks>
+ /// Exceptions are the same as the string overload.
+ /// </remarks>
+ internal static string Normalize(ref ValueStringBuilder path)
+ {
+ Span<char> initialBuffer = stackalloc char[PathInternal.MaxShortPath];
+ var builder = new ValueStringBuilder(initialBuffer);
+
+ // Get the full path
+ GetFullPathName(path.AsSpan(terminate: true), ref builder);
+
+ string result = builder.AsSpan().IndexOf('~') >= 0
+ ? TryExpandShortFileName(ref builder, originalPath: null)
+ : builder.ToString();
+
+ // Clear the buffer
+ builder.Dispose();
+ return result;
+ }
+
+ /// <summary>
+ /// Calls GetFullPathName on the given path.
+ /// </summary>
+ /// <param name="path">The path name. MUST be null terminated after the span.</param>
+ private static void GetFullPathName(ReadOnlySpan<char> path, ref ValueStringBuilder builder)
{
// If the string starts with an extended prefix we would need to remove it from the path before we call GetFullPathName as
// it doesn't root extended paths correctly. We don't currently resolve extended paths, so we'll just assert here.
Debug.Assert(PathInternal.IsPartiallyQualified(path) || !PathInternal.IsExtended(path));
uint result = 0;
- while ((result = Interop.Kernel32.GetFullPathNameW(path, (uint)builder.Capacity, ref builder.GetPinnableReference(), IntPtr.Zero)) > builder.Capacity)
+ while ((result = Interop.Kernel32.GetFullPathNameW(ref MemoryMarshal.GetReference(path), (uint)builder.Capacity, ref builder.GetPinnableReference(), IntPtr.Zero)) > builder.Capacity)
{
// Reported size is greater than the buffer size. Increase the capacity.
builder.EnsureCapacity(checked((int)result));
@@ -61,13 +88,13 @@ namespace System.IO
int errorCode = Marshal.GetLastWin32Error();
if (errorCode == 0)
errorCode = Interop.Errors.ERROR_BAD_PATHNAME;
- throw Win32Marshal.GetExceptionForWin32Error(errorCode, path);
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, path.ToString());
}
builder.Length = (int)result;
}
- private static int PrependDevicePathChars(ref ValueStringBuilder content, bool isDosUnc, ref ValueStringBuilder buffer)
+ internal static int PrependDevicePathChars(ref ValueStringBuilder content, bool isDosUnc, ref ValueStringBuilder buffer)
{
int length = content.Length;
@@ -84,7 +111,7 @@ namespace System.IO
buffer.Append(PathInternal.UncExtendedPathPrefix);
// Copy Server\Share\... over to the buffer
- buffer.Append(content.AsSpan().Slice(PathInternal.UncPrefixLength));
+ buffer.Append(content.AsSpan(PathInternal.UncPrefixLength));
// Return the prefix difference
return PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength;
@@ -98,7 +125,7 @@ namespace System.IO
}
}
- private static string TryExpandShortFileName(ref ValueStringBuilder outputBuilder, string originalPath)
+ internal static string TryExpandShortFileName(ref ValueStringBuilder outputBuilder, string originalPath)
{
// We guarantee we'll expand short names for paths that only partially exist. As such, we need to find the part of the path that actually does exist. To
// avoid allocating like crazy we'll create only one input array and modify the contents with embedded nulls.
@@ -119,7 +146,7 @@ namespace System.IO
bool isDevice = PathInternal.IsDevice(outputBuilder.AsSpan());
// As this is a corner case we're not going to add a stackalloc here to keep the stack pressure down.
- ValueStringBuilder inputBuilder = new ValueStringBuilder();
+ var inputBuilder = new ValueStringBuilder();
bool isDosUnc = false;
int rootDifference = 0;
@@ -149,12 +176,10 @@ namespace System.IO
bool success = false;
int foundIndex = inputBuilder.Length - 1;
- // Need to null terminate the input builder
- inputBuilder.Append('\0');
-
while (!success)
{
- uint result = Interop.Kernel32.GetLongPathNameW(ref inputBuilder.GetPinnableReference(), ref outputBuilder.GetPinnableReference(), (uint)outputBuilder.Capacity);
+ uint result = Interop.Kernel32.GetLongPathNameW(
+ ref inputBuilder.GetPinnableReference(terminate: true), ref outputBuilder.GetPinnableReference(), (uint)outputBuilder.Capacity);
// Replace any temporary null we added
if (inputBuilder[foundIndex] == '\0') inputBuilder[foundIndex] = '\\';
@@ -198,14 +223,11 @@ namespace System.IO
if (foundIndex < inputLength - 1)
{
// It was a partial find, put the non-existent part of the path back
- outputBuilder.Append(inputBuilder.AsSpan().Slice(foundIndex, inputBuilder.Length - foundIndex));
+ outputBuilder.Append(inputBuilder.AsSpan(foundIndex, inputBuilder.Length - foundIndex));
}
}
}
- // Need to trim out the trailing separator in the input builder
- inputBuilder.Length = inputBuilder.Length - 1;
-
// If we were able to expand the path, use it, otherwise use the original full path result
ref ValueStringBuilder builderToUse = ref (success ? ref outputBuilder : ref inputBuilder);
@@ -218,10 +240,10 @@ namespace System.IO
builderToUse[PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength] = '\\';
// Strip out any added characters at the front of the string
- ReadOnlySpan<char> output = builderToUse.AsSpan().Slice(rootDifference);
+ ReadOnlySpan<char> output = builderToUse.AsSpan(rootDifference);
- string returnValue = output.Equals(originalPath.AsSpan())
- ? originalPath : new string(output);
+ string returnValue = ((originalPath != null) && output.Equals(originalPath.AsSpan(), StringComparison.Ordinal))
+ ? originalPath : output.ToString();
inputBuilder.Dispose();
return returnValue;
diff --git a/src/System.Private.CoreLib/shared/System/IO/PathInternal.Windows.cs b/src/System.Private.CoreLib/shared/System/IO/PathInternal.Windows.cs
index 81d51ba4b..5f9ee0e02 100644
--- a/src/System.Private.CoreLib/shared/System/IO/PathInternal.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/PathInternal.Windows.cs
@@ -70,7 +70,7 @@ namespace System.IO
return ((value >= 'A' && value <= 'Z') || (value >= 'a' && value <= 'z'));
}
- private static bool EndsWithPeriodOrSpace(string path)
+ internal static bool EndsWithPeriodOrSpace(string path)
{
if (string.IsNullOrEmpty(path))
return false;
@@ -130,7 +130,7 @@ namespace System.IO
// In any case, all internal usages should be hitting normalize path (Path.GetFullPath) before they hit this
// shimming method. (Or making a change that doesn't impact normalization, such as adding a filename to a
// normalized base path.)
- if (IsPartiallyQualified(path) || IsDevice(path))
+ if (IsPartiallyQualified(path.AsSpan()) || IsDevice(path.AsSpan()))
return path;
// Given \\server\share in longpath becomes \\?\UNC\server\share
@@ -270,19 +270,6 @@ namespace System.IO
return i;
}
- private static bool StartsWithOrdinal(ReadOnlySpan<char> source, string value)
- {
- if (source.Length < value.Length)
- return false;
-
- for (int i = 0; i < value.Length; i++)
- {
- if (value[i] != source[i])
- return false;
- }
- return true;
- }
-
/// <summary>
/// Returns true if the path specified is relative to the current drive or working directory.
/// Returns false if the path is fixed to a specific drive or UNC path. This method does no
diff --git a/src/System.Private.CoreLib/shared/System/IO/PathInternal.cs b/src/System.Private.CoreLib/shared/System/IO/PathInternal.cs
index eb06c2608..1b08a2612 100644
--- a/src/System.Private.CoreLib/shared/System/IO/PathInternal.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/PathInternal.cs
@@ -2,6 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Diagnostics;
+using System.Text;
+
namespace System.IO
{
/// <summary>Contains internal path helpers that are shared between many projects.</summary>
@@ -19,10 +22,10 @@ namespace System.IO
internal static bool StartsWithDirectorySeparator(ReadOnlySpan<char> path) => path.Length > 0 && IsDirectorySeparator(path[0]);
internal static string EnsureTrailingSeparator(string path)
- => EndsInDirectorySeparator(path) ? path : path + DirectorySeparatorCharAsString;
+ => EndsInDirectorySeparator(path.AsSpan()) ? path : path + DirectorySeparatorCharAsString;
internal static string TrimEndingDirectorySeparator(string path) =>
- EndsInDirectorySeparator(path) && !IsRoot(path) ?
+ EndsInDirectorySeparator(path.AsSpan()) && !IsRoot(path.AsSpan()) ?
path.Substring(0, path.Length - 1) :
path;
@@ -63,7 +66,7 @@ namespace System.IO
/// <summary>
/// Gets the count of common characters from the left optionally ignoring case
/// </summary>
- unsafe internal static int EqualStartingCharacterCount(string first, string second, bool ignoreCase)
+ internal static unsafe int EqualStartingCharacterCount(string first, string second, bool ignoreCase)
{
if (string.IsNullOrEmpty(first) || string.IsNullOrEmpty(second)) return 0;
@@ -94,8 +97,8 @@ namespace System.IO
/// </summary>
internal static bool AreRootsEqual(string first, string second, StringComparison comparisonType)
{
- int firstRootLength = GetRootLength(first);
- int secondRootLength = GetRootLength(second);
+ int firstRootLength = GetRootLength(first.AsSpan());
+ int secondRootLength = GetRootLength(second.AsSpan());
return firstRootLength == secondRootLength
&& string.Compare(
@@ -106,5 +109,121 @@ namespace System.IO
length: firstRootLength,
comparisonType: comparisonType) == 0;
}
+
+ /// <summary>
+ /// Try to remove relative segments from the given path (without combining with a root).
+ /// </summary>
+ /// <param name="rootLength">The length of the root of the given path</param>
+ internal static string RemoveRelativeSegments(string path, int rootLength)
+ {
+ Span<char> initialBuffer = stackalloc char[260 /* PathInternal.MaxShortPath */];
+ ValueStringBuilder sb = new ValueStringBuilder(initialBuffer);
+
+ if (RemoveRelativeSegments(path.AsSpan(), rootLength, ref sb))
+ {
+ path = sb.ToString();
+ }
+
+ sb.Dispose();
+ return path;
+ }
+
+ /// <summary>
+ /// Try to remove relative segments from the given path (without combining with a root).
+ /// </summary>
+ /// <param name="rootLength">The length of the root of the given path</param>
+ /// <returns>"true" if the path was modified</returns>
+ internal static bool RemoveRelativeSegments(ReadOnlySpan<char> path, int rootLength, ref ValueStringBuilder sb)
+ {
+ Debug.Assert(rootLength > 0);
+ bool flippedSeparator = false;
+
+ int skip = rootLength;
+ // We treat "\.." , "\." and "\\" as a relative segment. We want to collapse the first separator past the root presuming
+ // the root actually ends in a separator. Otherwise the first segment for RemoveRelativeSegments
+ // in cases like "\\?\C:\.\" and "\\?\C:\..\", the first segment after the root will be ".\" and "..\" which is not considered as a relative segment and hence not be removed.
+ if (PathInternal.IsDirectorySeparator(path[skip - 1]))
+ skip--;
+
+ // Remove "//", "/./", and "/../" from the path by copying each character to the output,
+ // except the ones we're removing, such that the builder contains the normalized path
+ // at the end.
+ if (skip > 0)
+ {
+ sb.Append(path.Slice(0, skip));
+ }
+
+ for (int i = skip; i < path.Length; i++)
+ {
+ char c = path[i];
+
+ if (PathInternal.IsDirectorySeparator(c) && i + 1 < path.Length)
+ {
+ // Skip this character if it's a directory separator and if the next character is, too,
+ // e.g. "parent//child" => "parent/child"
+ if (PathInternal.IsDirectorySeparator(path[i + 1]))
+ {
+ continue;
+ }
+
+ // Skip this character and the next if it's referring to the current directory,
+ // e.g. "parent/./child" => "parent/child"
+ if ((i + 2 == path.Length || PathInternal.IsDirectorySeparator(path[i + 2])) &&
+ path[i + 1] == '.')
+ {
+ i++;
+ continue;
+ }
+
+ // Skip this character and the next two if it's referring to the parent directory,
+ // e.g. "parent/child/../grandchild" => "parent/grandchild"
+ if (i + 2 < path.Length &&
+ (i + 3 == path.Length || PathInternal.IsDirectorySeparator(path[i + 3])) &&
+ path[i + 1] == '.' && path[i + 2] == '.')
+ {
+ // Unwind back to the last slash (and if there isn't one, clear out everything).
+ int s;
+ for (s = sb.Length - 1; s >= skip; s--)
+ {
+ if (PathInternal.IsDirectorySeparator(sb[s]))
+ {
+ sb.Length = (i + 3 >= path.Length && s == skip) ? s + 1 : s; // to avoid removing the complete "\tmp\" segment in cases like \\?\C:\tmp\..\, C:\tmp\..
+ break;
+ }
+ }
+ if (s < skip)
+ {
+ sb.Length = skip;
+ }
+
+ i += 2;
+ continue;
+ }
+ }
+
+ // Normalize the directory separator if needed
+ if (c != PathInternal.DirectorySeparatorChar && c == PathInternal.AltDirectorySeparatorChar)
+ {
+ c = PathInternal.DirectorySeparatorChar;
+ flippedSeparator = true;
+ }
+
+ sb.Append(c);
+ }
+
+ // If we haven't changed the source path, return the original
+ if (!flippedSeparator && sb.Length == path.Length)
+ {
+ return false;
+ }
+
+ // We may have eaten the trailing separator from the root when we started and not replaced it
+ if (skip != rootLength && sb.Length < rootLength)
+ {
+ sb.Append(path[rootLength - 1]);
+ }
+
+ return true;
+ }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/IO/PinnedBufferMemoryStream.cs b/src/System.Private.CoreLib/shared/System/IO/PinnedBufferMemoryStream.cs
index dfcc05d06..94331a2ef 100644
--- a/src/System.Private.CoreLib/shared/System/IO/PinnedBufferMemoryStream.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/PinnedBufferMemoryStream.cs
@@ -38,9 +38,9 @@ namespace System.IO
Initialize(ptr, len, len, FileAccess.Read);
}
- public override int Read(Span<byte> destination) => ReadCore(destination);
+ public override int Read(Span<byte> buffer) => ReadCore(buffer);
- public override void Write(ReadOnlySpan<byte> source) => WriteCore(source);
+ public override void Write(ReadOnlySpan<byte> buffer) => WriteCore(buffer);
~PinnedBufferMemoryStream()
{
diff --git a/src/System.Private.CoreLib/shared/System/IO/Stream.cs b/src/System.Private.CoreLib/shared/System/IO/Stream.cs
new file mode 100644
index 000000000..faeb69fb5
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/IO/Stream.cs
@@ -0,0 +1,1322 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Abstract base class for all Streams. Provides
+** default implementations of asynchronous reads & writes, in
+** terms of the synchronous reads & writes (and vice versa).
+**
+**
+===========================================================*/
+
+using System.Buffers;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.ExceptionServices;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.IO
+{
+ public abstract partial class Stream : MarshalByRefObject, IDisposable
+ {
+ public static readonly Stream Null = new NullStream();
+
+ // We pick a value that is the largest multiple of 4096 that is still smaller than the large object heap threshold (85K).
+ // The CopyTo/CopyToAsync buffer is short-lived and is likely to be collected at Gen0, and it offers a significant
+ // improvement in Copy performance.
+ private const int DefaultCopyBufferSize = 81920;
+
+ // To implement Async IO operations on streams that don't support async IO
+
+ private ReadWriteTask _activeReadWriteTask;
+ private SemaphoreSlim _asyncActiveSemaphore;
+
+ internal SemaphoreSlim EnsureAsyncActiveSemaphoreInitialized()
+ {
+ // Lazily-initialize _asyncActiveSemaphore. As we're never accessing the SemaphoreSlim's
+ // WaitHandle, we don't need to worry about Disposing it.
+ return LazyInitializer.EnsureInitialized(ref _asyncActiveSemaphore, () => new SemaphoreSlim(1, 1));
+ }
+
+ public abstract bool CanRead
+ {
+ get;
+ }
+
+ // If CanSeek is false, Position, Seek, Length, and SetLength should throw.
+ public abstract bool CanSeek
+ {
+ get;
+ }
+
+ public virtual bool CanTimeout
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public abstract bool CanWrite
+ {
+ get;
+ }
+
+ public abstract long Length
+ {
+ get;
+ }
+
+ public abstract long Position
+ {
+ get;
+ set;
+ }
+
+ public virtual int ReadTimeout
+ {
+ get
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_TimeoutsNotSupported);
+ }
+ set
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_TimeoutsNotSupported);
+ }
+ }
+
+ public virtual int WriteTimeout
+ {
+ get
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_TimeoutsNotSupported);
+ }
+ set
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_TimeoutsNotSupported);
+ }
+ }
+
+ public Task CopyToAsync(Stream destination)
+ {
+ int bufferSize = GetCopyBufferSize();
+
+ return CopyToAsync(destination, bufferSize);
+ }
+
+ public Task CopyToAsync(Stream destination, int bufferSize)
+ {
+ return CopyToAsync(destination, bufferSize, CancellationToken.None);
+ }
+
+ public Task CopyToAsync(Stream destination, CancellationToken cancellationToken)
+ {
+ int bufferSize = GetCopyBufferSize();
+
+ return CopyToAsync(destination, bufferSize, cancellationToken);
+ }
+
+ public virtual Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
+ {
+ StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize);
+
+ return CopyToAsyncInternal(destination, bufferSize, cancellationToken);
+ }
+
+ private async Task CopyToAsyncInternal(Stream destination, int bufferSize, CancellationToken cancellationToken)
+ {
+ byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize);
+ try
+ {
+ while (true)
+ {
+ int bytesRead = await ReadAsync(new Memory<byte>(buffer), cancellationToken).ConfigureAwait(false);
+ if (bytesRead == 0) break;
+ await destination.WriteAsync(new ReadOnlyMemory<byte>(buffer, 0, bytesRead), cancellationToken).ConfigureAwait(false);
+ }
+ }
+ finally
+ {
+ ArrayPool<byte>.Shared.Return(buffer);
+ }
+ }
+
+ // Reads the bytes from the current stream and writes the bytes to
+ // the destination stream until all bytes are read, starting at
+ // the current position.
+ public void CopyTo(Stream destination)
+ {
+ int bufferSize = GetCopyBufferSize();
+
+ CopyTo(destination, bufferSize);
+ }
+
+ public virtual void CopyTo(Stream destination, int bufferSize)
+ {
+ StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize);
+
+ byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize);
+ try
+ {
+ int read;
+ while ((read = Read(buffer, 0, buffer.Length)) != 0)
+ {
+ destination.Write(buffer, 0, read);
+ }
+ }
+ finally
+ {
+ ArrayPool<byte>.Shared.Return(buffer);
+ }
+ }
+
+ private int GetCopyBufferSize()
+ {
+ int bufferSize = DefaultCopyBufferSize;
+
+ if (CanSeek)
+ {
+ long length = Length;
+ long position = Position;
+ if (length <= position) // Handles negative overflows
+ {
+ // There are no bytes left in the stream to copy.
+ // However, because CopyTo{Async} is virtual, we need to
+ // ensure that any override is still invoked to provide its
+ // own validation, so we use the smallest legal buffer size here.
+ bufferSize = 1;
+ }
+ else
+ {
+ long remaining = length - position;
+ if (remaining > 0)
+ {
+ // In the case of a positive overflow, stick to the default size
+ bufferSize = (int)Math.Min(bufferSize, remaining);
+ }
+ }
+ }
+
+ return bufferSize;
+ }
+
+ // Stream used to require that all cleanup logic went into Close(),
+ // which was thought up before we invented IDisposable. However, we
+ // need to follow the IDisposable pattern so that users can write
+ // sensible subclasses without needing to inspect all their base
+ // classes, and without worrying about version brittleness, from a
+ // base class switching to the Dispose pattern. We're moving
+ // Stream to the Dispose(bool) pattern - that's where all subclasses
+ // should put their cleanup now.
+ public virtual void Close()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ public void Dispose()
+ {
+ Close();
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ // Note: Never change this to call other virtual methods on Stream
+ // like Write, since the state on subclasses has already been
+ // torn down. This is the last code to run on cleanup for a stream.
+ }
+
+ public abstract void Flush();
+
+ public Task FlushAsync()
+ {
+ return FlushAsync(CancellationToken.None);
+ }
+
+ public virtual Task FlushAsync(CancellationToken cancellationToken)
+ {
+ return Task.Factory.StartNew(state => ((Stream)state).Flush(), this,
+ cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+ }
+
+ [Obsolete("CreateWaitHandle will be removed eventually. Please use \"new ManualResetEvent(false)\" instead.")]
+ protected virtual WaitHandle CreateWaitHandle()
+ {
+ return new ManualResetEvent(false);
+ }
+
+ public virtual IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+ return BeginReadInternal(buffer, offset, count, callback, state, serializeAsynchronously: false, apm: true);
+ }
+
+ internal IAsyncResult BeginReadInternal(
+ byte[] buffer, int offset, int count, AsyncCallback callback, object state,
+ bool serializeAsynchronously, bool apm)
+ {
+ if (!CanRead) throw Error.GetReadNotSupported();
+
+ // To avoid a race with a stream's position pointer & generating race conditions
+ // with internal buffer indexes in our own streams that
+ // don't natively support async IO operations when there are multiple
+ // async requests outstanding, we will block the application's main
+ // thread if it does a second IO request until the first one completes.
+ var semaphore = EnsureAsyncActiveSemaphoreInitialized();
+ Task semaphoreTask = null;
+ if (serializeAsynchronously)
+ {
+ semaphoreTask = semaphore.WaitAsync();
+ }
+ else
+ {
+ semaphore.Wait();
+ }
+
+ // Create the task to asynchronously do a Read. This task serves both
+ // as the asynchronous work item and as the IAsyncResult returned to the user.
+ var asyncResult = new ReadWriteTask(true /*isRead*/, apm, delegate
+ {
+ // The ReadWriteTask stores all of the parameters to pass to Read.
+ // As we're currently inside of it, we can get the current task
+ // and grab the parameters from it.
+ var thisTask = Task.InternalCurrent as ReadWriteTask;
+ Debug.Assert(thisTask != null, "Inside ReadWriteTask, InternalCurrent should be the ReadWriteTask");
+
+ try
+ {
+ // Do the Read and return the number of bytes read
+ return thisTask._stream.Read(thisTask._buffer, thisTask._offset, thisTask._count);
+ }
+ finally
+ {
+ // If this implementation is part of Begin/EndXx, then the EndXx method will handle
+ // finishing the async operation. However, if this is part of XxAsync, then there won't
+ // be an end method, and this task is responsible for cleaning up.
+ if (!thisTask._apm)
+ {
+ thisTask._stream.FinishTrackingAsyncOperation();
+ }
+
+ thisTask.ClearBeginState(); // just to help alleviate some memory pressure
+ }
+ }, state, this, buffer, offset, count, callback);
+
+ // Schedule it
+ if (semaphoreTask != null)
+ RunReadWriteTaskWhenReady(semaphoreTask, asyncResult);
+ else
+ RunReadWriteTask(asyncResult);
+
+
+ return asyncResult; // return it
+ }
+
+ public virtual int EndRead(IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException(nameof(asyncResult));
+
+ var readTask = _activeReadWriteTask;
+
+ if (readTask == null)
+ {
+ throw new ArgumentException(SR.InvalidOperation_WrongAsyncResultOrEndReadCalledMultiple);
+ }
+ else if (readTask != asyncResult)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_WrongAsyncResultOrEndReadCalledMultiple);
+ }
+ else if (!readTask._isRead)
+ {
+ throw new ArgumentException(SR.InvalidOperation_WrongAsyncResultOrEndReadCalledMultiple);
+ }
+
+ try
+ {
+ return readTask.GetAwaiter().GetResult(); // block until completion, then get result / propagate any exception
+ }
+ finally
+ {
+ FinishTrackingAsyncOperation();
+ }
+ }
+
+ public Task<int> ReadAsync(byte[] buffer, int offset, int count)
+ {
+ return ReadAsync(buffer, offset, count, CancellationToken.None);
+ }
+
+ public virtual Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ // If cancellation was requested, bail early with an already completed task.
+ // Otherwise, return a task that represents the Begin/End methods.
+ return cancellationToken.IsCancellationRequested
+ ? Task.FromCanceled<int>(cancellationToken)
+ : BeginEndReadAsync(buffer, offset, count);
+ }
+
+ public virtual ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
+ {
+ if (MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> array))
+ {
+ return new ValueTask<int>(ReadAsync(array.Array, array.Offset, array.Count, cancellationToken));
+ }
+ else
+ {
+ byte[] sharedBuffer = ArrayPool<byte>.Shared.Rent(buffer.Length);
+ return FinishReadAsync(ReadAsync(sharedBuffer, 0, buffer.Length, cancellationToken), sharedBuffer, buffer);
+
+ async ValueTask<int> FinishReadAsync(Task<int> readTask, byte[] localBuffer, Memory<byte> localDestination)
+ {
+ try
+ {
+ int result = await readTask.ConfigureAwait(false);
+ new Span<byte>(localBuffer, 0, result).CopyTo(localDestination.Span);
+ return result;
+ }
+ finally
+ {
+ ArrayPool<byte>.Shared.Return(localBuffer);
+ }
+ }
+ }
+ }
+
+ private Task<int> BeginEndReadAsync(byte[] buffer, int offset, int count)
+ {
+ if (!HasOverriddenBeginEndRead())
+ {
+ // If the Stream does not override Begin/EndRead, then we can take an optimized path
+ // that skips an extra layer of tasks / IAsyncResults.
+ return (Task<int>)BeginReadInternal(buffer, offset, count, null, null, serializeAsynchronously: true, apm: false);
+ }
+
+ // Otherwise, we need to wrap calls to Begin/EndWrite to ensure we use the derived type's functionality.
+ return TaskFactory<int>.FromAsyncTrim(
+ this, new ReadWriteParameters { Buffer = buffer, Offset = offset, Count = count },
+ (stream, args, callback, state) => stream.BeginRead(args.Buffer, args.Offset, args.Count, callback, state), // cached by compiler
+ (stream, asyncResult) => stream.EndRead(asyncResult)); // cached by compiler
+ }
+
+ private struct ReadWriteParameters // struct for arguments to Read and Write calls
+ {
+ internal byte[] Buffer;
+ internal int Offset;
+ internal int Count;
+ }
+
+
+
+ public virtual IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+ return BeginWriteInternal(buffer, offset, count, callback, state, serializeAsynchronously: false, apm: true);
+ }
+
+ internal IAsyncResult BeginWriteInternal(
+ byte[] buffer, int offset, int count, AsyncCallback callback, object state,
+ bool serializeAsynchronously, bool apm)
+ {
+ if (!CanWrite) throw Error.GetWriteNotSupported();
+
+ // To avoid a race condition with a stream's position pointer & generating conditions
+ // with internal buffer indexes in our own streams that
+ // don't natively support async IO operations when there are multiple
+ // async requests outstanding, we will block the application's main
+ // thread if it does a second IO request until the first one completes.
+ var semaphore = EnsureAsyncActiveSemaphoreInitialized();
+ Task semaphoreTask = null;
+ if (serializeAsynchronously)
+ {
+ semaphoreTask = semaphore.WaitAsync(); // kick off the asynchronous wait, but don't block
+ }
+ else
+ {
+ semaphore.Wait(); // synchronously wait here
+ }
+
+ // Create the task to asynchronously do a Write. This task serves both
+ // as the asynchronous work item and as the IAsyncResult returned to the user.
+ var asyncResult = new ReadWriteTask(false /*isRead*/, apm, delegate
+ {
+ // The ReadWriteTask stores all of the parameters to pass to Write.
+ // As we're currently inside of it, we can get the current task
+ // and grab the parameters from it.
+ var thisTask = Task.InternalCurrent as ReadWriteTask;
+ Debug.Assert(thisTask != null, "Inside ReadWriteTask, InternalCurrent should be the ReadWriteTask");
+
+ try
+ {
+ // Do the Write
+ thisTask._stream.Write(thisTask._buffer, thisTask._offset, thisTask._count);
+ return 0; // not used, but signature requires a value be returned
+ }
+ finally
+ {
+ // If this implementation is part of Begin/EndXx, then the EndXx method will handle
+ // finishing the async operation. However, if this is part of XxAsync, then there won't
+ // be an end method, and this task is responsible for cleaning up.
+ if (!thisTask._apm)
+ {
+ thisTask._stream.FinishTrackingAsyncOperation();
+ }
+
+ thisTask.ClearBeginState(); // just to help alleviate some memory pressure
+ }
+ }, state, this, buffer, offset, count, callback);
+
+ // Schedule it
+ if (semaphoreTask != null)
+ RunReadWriteTaskWhenReady(semaphoreTask, asyncResult);
+ else
+ RunReadWriteTask(asyncResult);
+
+ return asyncResult; // return it
+ }
+
+ private void RunReadWriteTaskWhenReady(Task asyncWaiter, ReadWriteTask readWriteTask)
+ {
+ Debug.Assert(readWriteTask != null);
+ Debug.Assert(asyncWaiter != null);
+
+ // If the wait has already completed, run the task.
+ if (asyncWaiter.IsCompleted)
+ {
+ Debug.Assert(asyncWaiter.IsCompletedSuccessfully, "The semaphore wait should always complete successfully.");
+ RunReadWriteTask(readWriteTask);
+ }
+ else // Otherwise, wait for our turn, and then run the task.
+ {
+ asyncWaiter.ContinueWith((t, state) =>
+ {
+ Debug.Assert(t.IsCompletedSuccessfully, "The semaphore wait should always complete successfully.");
+ var rwt = (ReadWriteTask)state;
+ rwt._stream.RunReadWriteTask(rwt); // RunReadWriteTask(readWriteTask);
+ }, readWriteTask, default, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
+ }
+ }
+
+ private void RunReadWriteTask(ReadWriteTask readWriteTask)
+ {
+ Debug.Assert(readWriteTask != null);
+ Debug.Assert(_activeReadWriteTask == null, "Expected no other readers or writers");
+
+ // Schedule the task. ScheduleAndStart must happen after the write to _activeReadWriteTask to avoid a race.
+ // Internally, we're able to directly call ScheduleAndStart rather than Start, avoiding
+ // two interlocked operations. However, if ReadWriteTask is ever changed to use
+ // a cancellation token, this should be changed to use Start.
+ _activeReadWriteTask = readWriteTask; // store the task so that EndXx can validate it's given the right one
+ readWriteTask.m_taskScheduler = TaskScheduler.Default;
+ readWriteTask.ScheduleAndStart(needsProtection: false);
+ }
+
+ private void FinishTrackingAsyncOperation()
+ {
+ _activeReadWriteTask = null;
+ Debug.Assert(_asyncActiveSemaphore != null, "Must have been initialized in order to get here.");
+ _asyncActiveSemaphore.Release();
+ }
+
+ public virtual void EndWrite(IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException(nameof(asyncResult));
+
+ var writeTask = _activeReadWriteTask;
+ if (writeTask == null)
+ {
+ throw new ArgumentException(SR.InvalidOperation_WrongAsyncResultOrEndWriteCalledMultiple);
+ }
+ else if (writeTask != asyncResult)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_WrongAsyncResultOrEndWriteCalledMultiple);
+ }
+ else if (writeTask._isRead)
+ {
+ throw new ArgumentException(SR.InvalidOperation_WrongAsyncResultOrEndWriteCalledMultiple);
+ }
+
+ try
+ {
+ writeTask.GetAwaiter().GetResult(); // block until completion, then propagate any exceptions
+ Debug.Assert(writeTask.Status == TaskStatus.RanToCompletion);
+ }
+ finally
+ {
+ FinishTrackingAsyncOperation();
+ }
+ }
+
+ // Task used by BeginRead / BeginWrite to do Read / Write asynchronously.
+ // A single instance of this task serves four purposes:
+ // 1. The work item scheduled to run the Read / Write operation
+ // 2. The state holding the arguments to be passed to Read / Write
+ // 3. The IAsyncResult returned from BeginRead / BeginWrite
+ // 4. The completion action that runs to invoke the user-provided callback.
+ // This last item is a bit tricky. Before the AsyncCallback is invoked, the
+ // IAsyncResult must have completed, so we can't just invoke the handler
+ // from within the task, since it is the IAsyncResult, and thus it's not
+ // yet completed. Instead, we use AddCompletionAction to install this
+ // task as its own completion handler. That saves the need to allocate
+ // a separate completion handler, it guarantees that the task will
+ // have completed by the time the handler is invoked, and it allows
+ // the handler to be invoked synchronously upon the completion of the
+ // task. This all enables BeginRead / BeginWrite to be implemented
+ // with a single allocation.
+ private sealed class ReadWriteTask : Task<int>, ITaskCompletionAction
+ {
+ internal readonly bool _isRead;
+ internal readonly bool _apm; // true if this is from Begin/EndXx; false if it's from XxAsync
+ internal Stream _stream;
+ internal byte[] _buffer;
+ internal readonly int _offset;
+ internal readonly int _count;
+ private AsyncCallback _callback;
+ private ExecutionContext _context;
+
+ internal void ClearBeginState() // Used to allow the args to Read/Write to be made available for GC
+ {
+ _stream = null;
+ _buffer = null;
+ }
+
+ public ReadWriteTask(
+ bool isRead,
+ bool apm,
+ Func<object, int> function, object state,
+ Stream stream, byte[] buffer, int offset, int count, AsyncCallback callback) :
+ base(function, state, CancellationToken.None, TaskCreationOptions.DenyChildAttach)
+ {
+ Debug.Assert(function != null);
+ Debug.Assert(stream != null);
+ Debug.Assert(buffer != null);
+
+ // Store the arguments
+ _isRead = isRead;
+ _apm = apm;
+ _stream = stream;
+ _buffer = buffer;
+ _offset = offset;
+ _count = count;
+
+ // If a callback was provided, we need to:
+ // - Store the user-provided handler
+ // - Capture an ExecutionContext under which to invoke the handler
+ // - Add this task as its own completion handler so that the Invoke method
+ // will run the callback when this task completes.
+ if (callback != null)
+ {
+ _callback = callback;
+ _context = ExecutionContext.Capture();
+ base.AddCompletionAction(this);
+ }
+ }
+
+ private static void InvokeAsyncCallback(object completedTask)
+ {
+ var rwc = (ReadWriteTask)completedTask;
+ var callback = rwc._callback;
+ rwc._callback = null;
+ callback(rwc);
+ }
+
+ private static ContextCallback s_invokeAsyncCallback;
+
+ void ITaskCompletionAction.Invoke(Task completingTask)
+ {
+ // Get the ExecutionContext. If there is none, just run the callback
+ // directly, passing in the completed task as the IAsyncResult.
+ // If there is one, process it with ExecutionContext.Run.
+ var context = _context;
+ if (context == null)
+ {
+ var callback = _callback;
+ _callback = null;
+ callback(completingTask);
+ }
+ else
+ {
+ _context = null;
+
+ var invokeAsyncCallback = s_invokeAsyncCallback;
+ if (invokeAsyncCallback == null) s_invokeAsyncCallback = invokeAsyncCallback = InvokeAsyncCallback; // benign race condition
+
+ ExecutionContext.RunInternal(context, invokeAsyncCallback, this);
+ }
+ }
+
+ bool ITaskCompletionAction.InvokeMayRunArbitraryCode { get { return true; } }
+ }
+
+ public Task WriteAsync(byte[] buffer, int offset, int count)
+ {
+ return WriteAsync(buffer, offset, count, CancellationToken.None);
+ }
+
+ public virtual Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ // If cancellation was requested, bail early with an already completed task.
+ // Otherwise, return a task that represents the Begin/End methods.
+ return cancellationToken.IsCancellationRequested
+ ? Task.FromCanceled(cancellationToken)
+ : BeginEndWriteAsync(buffer, offset, count);
+ }
+
+ public virtual ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
+ {
+ if (MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> array))
+ {
+ return new ValueTask(WriteAsync(array.Array, array.Offset, array.Count, cancellationToken));
+ }
+ else
+ {
+ byte[] sharedBuffer = ArrayPool<byte>.Shared.Rent(buffer.Length);
+ buffer.Span.CopyTo(sharedBuffer);
+ return new ValueTask(FinishWriteAsync(WriteAsync(sharedBuffer, 0, buffer.Length, cancellationToken), sharedBuffer));
+ }
+ }
+
+ private async Task FinishWriteAsync(Task writeTask, byte[] localBuffer)
+ {
+ try
+ {
+ await writeTask.ConfigureAwait(false);
+ }
+ finally
+ {
+ ArrayPool<byte>.Shared.Return(localBuffer);
+ }
+ }
+
+ private Task BeginEndWriteAsync(byte[] buffer, int offset, int count)
+ {
+ if (!HasOverriddenBeginEndWrite())
+ {
+ // If the Stream does not override Begin/EndWrite, then we can take an optimized path
+ // that skips an extra layer of tasks / IAsyncResults.
+ return (Task)BeginWriteInternal(buffer, offset, count, null, null, serializeAsynchronously: true, apm: false);
+ }
+
+ // Otherwise, we need to wrap calls to Begin/EndWrite to ensure we use the derived type's functionality.
+ return TaskFactory<VoidTaskResult>.FromAsyncTrim(
+ this, new ReadWriteParameters { Buffer = buffer, Offset = offset, Count = count },
+ (stream, args, callback, state) => stream.BeginWrite(args.Buffer, args.Offset, args.Count, callback, state), // cached by compiler
+ (stream, asyncResult) => // cached by compiler
+ {
+ stream.EndWrite(asyncResult);
+ return default;
+ });
+ }
+
+ public abstract long Seek(long offset, SeekOrigin origin);
+
+ public abstract void SetLength(long value);
+
+ public abstract int Read(byte[] buffer, int offset, int count);
+
+ public virtual int Read(Span<byte> buffer)
+ {
+ byte[] sharedBuffer = ArrayPool<byte>.Shared.Rent(buffer.Length);
+ try
+ {
+ int numRead = Read(sharedBuffer, 0, buffer.Length);
+ if ((uint)numRead > buffer.Length)
+ {
+ throw new IOException(SR.IO_StreamTooLong);
+ }
+ new Span<byte>(sharedBuffer, 0, numRead).CopyTo(buffer);
+ return numRead;
+ }
+ finally { ArrayPool<byte>.Shared.Return(sharedBuffer); }
+ }
+
+ // Reads one byte from the stream by calling Read(byte[], int, int).
+ // Will return an unsigned byte cast to an int or -1 on end of stream.
+ // This implementation does not perform well because it allocates a new
+ // byte[] each time you call it, and should be overridden by any
+ // subclass that maintains an internal buffer. Then, it can help perf
+ // significantly for people who are reading one byte at a time.
+ public virtual int ReadByte()
+ {
+ byte[] oneByteArray = new byte[1];
+ int r = Read(oneByteArray, 0, 1);
+ if (r == 0)
+ return -1;
+ return oneByteArray[0];
+ }
+
+ public abstract void Write(byte[] buffer, int offset, int count);
+
+ public virtual void Write(ReadOnlySpan<byte> buffer)
+ {
+ byte[] sharedBuffer = ArrayPool<byte>.Shared.Rent(buffer.Length);
+ try
+ {
+ buffer.CopyTo(sharedBuffer);
+ Write(sharedBuffer, 0, buffer.Length);
+ }
+ finally { ArrayPool<byte>.Shared.Return(sharedBuffer); }
+ }
+
+ // Writes one byte from the stream by calling Write(byte[], int, int).
+ // This implementation does not perform well because it allocates a new
+ // byte[] each time you call it, and should be overridden by any
+ // subclass that maintains an internal buffer. Then, it can help perf
+ // significantly for people who are writing one byte at a time.
+ public virtual void WriteByte(byte value)
+ {
+ byte[] oneByteArray = new byte[1];
+ oneByteArray[0] = value;
+ Write(oneByteArray, 0, 1);
+ }
+
+ public static Stream Synchronized(Stream stream)
+ {
+ if (stream == null)
+ throw new ArgumentNullException(nameof(stream));
+ if (stream is SyncStream)
+ return stream;
+
+ return new SyncStream(stream);
+ }
+
+ [Obsolete("Do not call or override this method.")]
+ protected virtual void ObjectInvariant()
+ {
+ }
+
+ internal IAsyncResult BlockingBeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+ // To avoid a race with a stream's position pointer & generating conditions
+ // with internal buffer indexes in our own streams that
+ // don't natively support async IO operations when there are multiple
+ // async requests outstanding, we will block the application's main
+ // thread and do the IO synchronously.
+ // This can't perform well - use a different approach.
+ SynchronousAsyncResult asyncResult;
+ try
+ {
+ int numRead = Read(buffer, offset, count);
+ asyncResult = new SynchronousAsyncResult(numRead, state);
+ }
+ catch (IOException ex)
+ {
+ asyncResult = new SynchronousAsyncResult(ex, state, isWrite: false);
+ }
+
+ if (callback != null)
+ {
+ callback(asyncResult);
+ }
+
+ return asyncResult;
+ }
+
+ internal static int BlockingEndRead(IAsyncResult asyncResult)
+ {
+ return SynchronousAsyncResult.EndRead(asyncResult);
+ }
+
+ internal IAsyncResult BlockingBeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+ // To avoid a race condition with a stream's position pointer & generating conditions
+ // with internal buffer indexes in our own streams that
+ // don't natively support async IO operations when there are multiple
+ // async requests outstanding, we will block the application's main
+ // thread and do the IO synchronously.
+ // This can't perform well - use a different approach.
+ SynchronousAsyncResult asyncResult;
+ try
+ {
+ Write(buffer, offset, count);
+ asyncResult = new SynchronousAsyncResult(state);
+ }
+ catch (IOException ex)
+ {
+ asyncResult = new SynchronousAsyncResult(ex, state, isWrite: true);
+ }
+
+ if (callback != null)
+ {
+ callback(asyncResult);
+ }
+
+ return asyncResult;
+ }
+
+ internal static void BlockingEndWrite(IAsyncResult asyncResult)
+ {
+ SynchronousAsyncResult.EndWrite(asyncResult);
+ }
+
+ private sealed class NullStream : Stream
+ {
+ private static readonly Task<int> s_zeroTask = Task.FromResult(0);
+
+ internal NullStream() { }
+
+ public override bool CanRead => true;
+
+ public override bool CanWrite => true;
+
+ public override bool CanSeek => true;
+
+ public override long Length => 0;
+
+ public override long Position
+ {
+ get { return 0; }
+ set { }
+ }
+
+ public override void CopyTo(Stream destination, int bufferSize)
+ {
+ StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize);
+
+ // After we validate arguments this is a nop.
+ }
+
+ public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
+ {
+ // Validate arguments here for compat, since previously this method
+ // was inherited from Stream (which did check its arguments).
+ StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize);
+
+ return cancellationToken.IsCancellationRequested ?
+ Task.FromCanceled(cancellationToken) :
+ Task.CompletedTask;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ // Do nothing - we don't want NullStream singleton (static) to be closable
+ }
+
+ public override void Flush()
+ {
+ }
+
+ public override Task FlushAsync(CancellationToken cancellationToken)
+ {
+ return cancellationToken.IsCancellationRequested ?
+ Task.FromCanceled(cancellationToken) :
+ Task.CompletedTask;
+ }
+
+ public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+ if (!CanRead) throw Error.GetReadNotSupported();
+
+ return BlockingBeginRead(buffer, offset, count, callback, state);
+ }
+
+ public override int EndRead(IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException(nameof(asyncResult));
+
+ return BlockingEndRead(asyncResult);
+ }
+
+ public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+ if (!CanWrite) throw Error.GetWriteNotSupported();
+
+ return BlockingBeginWrite(buffer, offset, count, callback, state);
+ }
+
+ public override void EndWrite(IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException(nameof(asyncResult));
+
+ BlockingEndWrite(asyncResult);
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ return 0;
+ }
+
+ public override int Read(Span<byte> buffer)
+ {
+ return 0;
+ }
+
+ public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ return s_zeroTask;
+ }
+
+ public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
+ {
+ return new ValueTask<int>(0);
+ }
+
+ public override int ReadByte()
+ {
+ return -1;
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ }
+
+ public override void Write(ReadOnlySpan<byte> buffer)
+ {
+ }
+
+ public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ return cancellationToken.IsCancellationRequested ?
+ Task.FromCanceled(cancellationToken) :
+ Task.CompletedTask;
+ }
+
+ public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
+ {
+ return cancellationToken.IsCancellationRequested ?
+ new ValueTask(Task.FromCanceled(cancellationToken)) :
+ default;
+ }
+
+ public override void WriteByte(byte value)
+ {
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ return 0;
+ }
+
+ public override void SetLength(long length)
+ {
+ }
+ }
+
+
+ /// <summary>Used as the IAsyncResult object when using asynchronous IO methods on the base Stream class.</summary>
+ private sealed class SynchronousAsyncResult : IAsyncResult
+ {
+ private readonly object _stateObject;
+ private readonly bool _isWrite;
+ private ManualResetEvent _waitHandle;
+ private ExceptionDispatchInfo _exceptionInfo;
+
+ private bool _endXxxCalled;
+ private int _bytesRead;
+
+ internal SynchronousAsyncResult(int bytesRead, object asyncStateObject)
+ {
+ _bytesRead = bytesRead;
+ _stateObject = asyncStateObject;
+ //_isWrite = false;
+ }
+
+ internal SynchronousAsyncResult(object asyncStateObject)
+ {
+ _stateObject = asyncStateObject;
+ _isWrite = true;
+ }
+
+ internal SynchronousAsyncResult(Exception ex, object asyncStateObject, bool isWrite)
+ {
+ _exceptionInfo = ExceptionDispatchInfo.Capture(ex);
+ _stateObject = asyncStateObject;
+ _isWrite = isWrite;
+ }
+
+ public bool IsCompleted
+ {
+ // We never hand out objects of this type to the user before the synchronous IO completed:
+ get { return true; }
+ }
+
+ public WaitHandle AsyncWaitHandle
+ {
+ get
+ {
+ return LazyInitializer.EnsureInitialized(ref _waitHandle, () => new ManualResetEvent(true));
+ }
+ }
+
+ public object AsyncState
+ {
+ get { return _stateObject; }
+ }
+
+ public bool CompletedSynchronously
+ {
+ get { return true; }
+ }
+
+ internal void ThrowIfError()
+ {
+ if (_exceptionInfo != null)
+ _exceptionInfo.Throw();
+ }
+
+ internal static int EndRead(IAsyncResult asyncResult)
+ {
+ SynchronousAsyncResult ar = asyncResult as SynchronousAsyncResult;
+ if (ar == null || ar._isWrite)
+ throw new ArgumentException(SR.Arg_WrongAsyncResult);
+
+ if (ar._endXxxCalled)
+ throw new ArgumentException(SR.InvalidOperation_EndReadCalledMultiple);
+
+ ar._endXxxCalled = true;
+
+ ar.ThrowIfError();
+ return ar._bytesRead;
+ }
+
+ internal static void EndWrite(IAsyncResult asyncResult)
+ {
+ SynchronousAsyncResult ar = asyncResult as SynchronousAsyncResult;
+ if (ar == null || !ar._isWrite)
+ throw new ArgumentException(SR.Arg_WrongAsyncResult);
+
+ if (ar._endXxxCalled)
+ throw new ArgumentException(SR.InvalidOperation_EndWriteCalledMultiple);
+
+ ar._endXxxCalled = true;
+
+ ar.ThrowIfError();
+ }
+ } // class SynchronousAsyncResult
+
+
+ // SyncStream is a wrapper around a stream that takes
+ // a lock for every operation making it thread safe.
+ private sealed class SyncStream : Stream, IDisposable
+ {
+ private Stream _stream;
+
+ internal SyncStream(Stream stream)
+ {
+ if (stream == null)
+ throw new ArgumentNullException(nameof(stream));
+ _stream = stream;
+ }
+
+ public override bool CanRead => _stream.CanRead;
+
+ public override bool CanWrite => _stream.CanWrite;
+
+ public override bool CanSeek => _stream.CanSeek;
+
+ public override bool CanTimeout => _stream.CanTimeout;
+
+ public override long Length
+ {
+ get
+ {
+ lock (_stream)
+ {
+ return _stream.Length;
+ }
+ }
+ }
+
+ public override long Position
+ {
+ get
+ {
+ lock (_stream)
+ {
+ return _stream.Position;
+ }
+ }
+ set
+ {
+ lock (_stream)
+ {
+ _stream.Position = value;
+ }
+ }
+ }
+
+ public override int ReadTimeout
+ {
+ get
+ {
+ return _stream.ReadTimeout;
+ }
+ set
+ {
+ _stream.ReadTimeout = value;
+ }
+ }
+
+ public override int WriteTimeout
+ {
+ get
+ {
+ return _stream.WriteTimeout;
+ }
+ set
+ {
+ _stream.WriteTimeout = value;
+ }
+ }
+
+ // In the off chance that some wrapped stream has different
+ // semantics for Close vs. Dispose, let's preserve that.
+ public override void Close()
+ {
+ lock (_stream)
+ {
+ try
+ {
+ _stream.Close();
+ }
+ finally
+ {
+ base.Dispose(true);
+ }
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ lock (_stream)
+ {
+ try
+ {
+ // Explicitly pick up a potentially methodimpl'ed Dispose
+ if (disposing)
+ ((IDisposable)_stream).Dispose();
+ }
+ finally
+ {
+ base.Dispose(disposing);
+ }
+ }
+ }
+
+ public override void Flush()
+ {
+ lock (_stream)
+ _stream.Flush();
+ }
+
+ public override int Read(byte[] bytes, int offset, int count)
+ {
+ lock (_stream)
+ return _stream.Read(bytes, offset, count);
+ }
+
+ public override int Read(Span<byte> buffer)
+ {
+ lock (_stream)
+ return _stream.Read(buffer);
+ }
+
+ public override int ReadByte()
+ {
+ lock (_stream)
+ return _stream.ReadByte();
+ }
+
+ public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+#if CORERT
+ throw new NotImplementedException(); // TODO: https://github.com/dotnet/corert/issues/3251
+#else
+ bool overridesBeginRead = _stream.HasOverriddenBeginEndRead();
+
+ lock (_stream)
+ {
+ // If the Stream does have its own BeginRead implementation, then we must use that override.
+ // If it doesn't, then we'll use the base implementation, but we'll make sure that the logic
+ // which ensures only one asynchronous operation does so with an asynchronous wait rather
+ // than a synchronous wait. A synchronous wait will result in a deadlock condition, because
+ // the EndXx method for the outstanding async operation won't be able to acquire the lock on
+ // _stream due to this call blocked while holding the lock.
+ return overridesBeginRead ?
+ _stream.BeginRead(buffer, offset, count, callback, state) :
+ _stream.BeginReadInternal(buffer, offset, count, callback, state, serializeAsynchronously: true, apm: true);
+ }
+#endif
+ }
+
+ public override int EndRead(IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException(nameof(asyncResult));
+
+ lock (_stream)
+ return _stream.EndRead(asyncResult);
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ lock (_stream)
+ return _stream.Seek(offset, origin);
+ }
+
+ public override void SetLength(long length)
+ {
+ lock (_stream)
+ _stream.SetLength(length);
+ }
+
+ public override void Write(byte[] bytes, int offset, int count)
+ {
+ lock (_stream)
+ _stream.Write(bytes, offset, count);
+ }
+
+ public override void Write(ReadOnlySpan<byte> buffer)
+ {
+ lock (_stream)
+ _stream.Write(buffer);
+ }
+
+ public override void WriteByte(byte b)
+ {
+ lock (_stream)
+ _stream.WriteByte(b);
+ }
+
+ public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
+ {
+#if CORERT
+ throw new NotImplementedException(); // TODO: https://github.com/dotnet/corert/issues/3251
+#else
+ bool overridesBeginWrite = _stream.HasOverriddenBeginEndWrite();
+
+ lock (_stream)
+ {
+ // If the Stream does have its own BeginWrite implementation, then we must use that override.
+ // If it doesn't, then we'll use the base implementation, but we'll make sure that the logic
+ // which ensures only one asynchronous operation does so with an asynchronous wait rather
+ // than a synchronous wait. A synchronous wait will result in a deadlock condition, because
+ // the EndXx method for the outstanding async operation won't be able to acquire the lock on
+ // _stream due to this call blocked while holding the lock.
+ return overridesBeginWrite ?
+ _stream.BeginWrite(buffer, offset, count, callback, state) :
+ _stream.BeginWriteInternal(buffer, offset, count, callback, state, serializeAsynchronously: true, apm: true);
+ }
+#endif
+ }
+
+ public override void EndWrite(IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException(nameof(asyncResult));
+
+ lock (_stream)
+ _stream.EndWrite(asyncResult);
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/IO/StreamReader.cs b/src/System.Private.CoreLib/shared/System/IO/StreamReader.cs
index 22ec6e645..5c3cc9157 100644
--- a/src/System.Private.CoreLib/shared/System/IO/StreamReader.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/StreamReader.cs
@@ -70,21 +70,21 @@ namespace System.IO
// We don't guarantee thread safety on StreamReader, but we should at
// least prevent users from trying to read anything while an Async
// read from the same thread is in progress.
- private volatile Task _asyncReadTask;
+ private Task _asyncReadTask = Task.CompletedTask;
private void CheckAsyncTaskInProgress()
{
// We are not locking the access to _asyncReadTask because this is not meant to guarantee thread safety.
// We are simply trying to deter calling any Read APIs while an async Read from the same thread is in progress.
-
- Task t = _asyncReadTask;
-
- if (t != null && !t.IsCompleted)
+ if (!_asyncReadTask.IsCompleted)
{
- throw new InvalidOperationException(SR.InvalidOperation_AsyncIOInProgress);
+ ThrowAsyncIOInProgress();
}
}
+ private static void ThrowAsyncIOInProgress() =>
+ throw new InvalidOperationException(SR.InvalidOperation_AsyncIOInProgress);
+
// StreamReader by default will ignore illegal UTF8 characters. We don't want to
// throw here because we want to be able to read ill-formed data without choking.
// The high level goal is to be tolerant of encoding errors when we read and very strict
@@ -1059,7 +1059,7 @@ namespace System.IO
// data read in, let's try writing directly to the user's buffer.
bool readToUserBuffer = false;
- Byte[] tmpByteBuffer = _byteBuffer;
+ byte[] tmpByteBuffer = _byteBuffer;
Stream tmpStream = _stream;
int count = buffer.Length;
@@ -1290,7 +1290,7 @@ namespace System.IO
{
_charLen = 0;
_charPos = 0;
- Byte[] tmpByteBuffer = _byteBuffer;
+ byte[] tmpByteBuffer = _byteBuffer;
Stream tmpStream = _stream;
if (!_checkPreamble)
diff --git a/src/System.Private.CoreLib/shared/System/IO/StreamWriter.cs b/src/System.Private.CoreLib/shared/System/IO/StreamWriter.cs
index a37624428..8d94ac60b 100644
--- a/src/System.Private.CoreLib/shared/System/IO/StreamWriter.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/StreamWriter.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
@@ -44,19 +45,21 @@ namespace System.IO
// We don't guarantee thread safety on StreamWriter, but we should at
// least prevent users from trying to write anything while an Async
// write from the same thread is in progress.
- private volatile Task _asyncWriteTask;
+ private Task _asyncWriteTask = Task.CompletedTask;
private void CheckAsyncTaskInProgress()
{
// We are not locking the access to _asyncWriteTask because this is not meant to guarantee thread safety.
// We are simply trying to deter calling any Write APIs while an async Write from the same thread is in progress.
-
- Task t = _asyncWriteTask;
-
- if (t != null && !t.IsCompleted)
- throw new InvalidOperationException(SR.InvalidOperation_AsyncIOInProgress);
+ if (!_asyncWriteTask.IsCompleted)
+ {
+ ThrowAsyncIOInProgress();
+ }
}
+ private static void ThrowAsyncIOInProgress() =>
+ throw new InvalidOperationException(SR.InvalidOperation_AsyncIOInProgress);
+
// The high level goal is to be tolerant of encoding errors when we read and very strict
// when we write. Hence, default StreamWriter encoding will throw on encoding error.
// Note: when StreamWriter throws on invalid encoding chars (for ex, high surrogate character
@@ -323,14 +326,13 @@ namespace System.IO
}
}
+ [MethodImpl(MethodImplOptions.NoInlining)] // prevent WriteSpan from bloating call sites
public override void Write(char[] buffer)
{
- if (buffer != null)
- {
- WriteCore(buffer, _autoFlush);
- }
+ WriteSpan(buffer, appendNewLine: false);
}
+ [MethodImpl(MethodImplOptions.NoInlining)] // prevent WriteSpan from bloating call sites
public override void Write(char[] buffer, int index, int count)
{
if (buffer == null)
@@ -350,14 +352,15 @@ namespace System.IO
throw new ArgumentException(SR.Argument_InvalidOffLen);
}
- WriteCore(new ReadOnlySpan<char>(buffer, index, count), _autoFlush);
+ WriteSpan(buffer.AsSpan(index, count), appendNewLine: false);
}
+ [MethodImpl(MethodImplOptions.NoInlining)] // prevent WriteSpan from bloating call sites
public override void Write(ReadOnlySpan<char> buffer)
{
if (GetType() == typeof(StreamWriter))
{
- WriteCore(buffer, _autoFlush);
+ WriteSpan(buffer, appendNewLine: false);
}
else
{
@@ -367,7 +370,8 @@ namespace System.IO
}
}
- private unsafe void WriteCore(ReadOnlySpan<char> buffer, bool autoFlush)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private unsafe void WriteSpan(ReadOnlySpan<char> buffer, bool appendNewLine)
{
CheckAsyncTaskInProgress();
@@ -422,41 +426,47 @@ namespace System.IO
}
}
- if (autoFlush)
+ if (appendNewLine)
+ {
+ char[] coreNewLine = CoreNewLine;
+ for (int i = 0; i < coreNewLine.Length; i++) // Generally 1 (\n) or 2 (\r\n) iterations
+ {
+ if (_charPos == _charLen)
+ {
+ Flush(false, false);
+ }
+
+ _charBuffer[_charPos] = coreNewLine[i];
+ _charPos++;
+ }
+ }
+
+ if (_autoFlush)
{
Flush(true, false);
}
}
+ [MethodImpl(MethodImplOptions.NoInlining)] // prevent WriteSpan from bloating call sites
public override void Write(string value)
{
- if (value != null)
- {
- WriteCore(value.AsSpan(), _autoFlush);
- }
+ WriteSpan(value, appendNewLine: false);
}
- //
- // Optimize the most commonly used WriteLine overload. This optimization is important for System.Console in particular
- // because of it will make one WriteLine equal to one call to the OS instead of two in the common case.
- //
+ [MethodImpl(MethodImplOptions.NoInlining)] // prevent WriteSpan from bloating call sites
public override void WriteLine(string value)
{
CheckAsyncTaskInProgress();
- if (value != null)
- {
- WriteCore(value.AsSpan(), autoFlush: false);
- }
- WriteCore(new ReadOnlySpan<char>(CoreNewLine), autoFlush: true);
+ WriteSpan(value, appendNewLine: true);
}
+ [MethodImpl(MethodImplOptions.NoInlining)] // prevent WriteSpan from bloating call sites
public override void WriteLine(ReadOnlySpan<char> value)
{
if (GetType() == typeof(StreamWriter))
{
CheckAsyncTaskInProgress();
- WriteCore(value, autoFlush: false);
- WriteCore(new ReadOnlySpan<char>(CoreNewLine), autoFlush: true);
+ WriteSpan(value, appendNewLine: true);
}
else
{
@@ -466,6 +476,123 @@ namespace System.IO
}
}
+ private void WriteFormatHelper(string format, ParamsArray args, bool appendNewLine)
+ {
+ StringBuilder sb =
+ StringBuilderCache.Acquire(format.Length + args.Length * 8)
+ .AppendFormatHelper(null, format, args);
+
+ StringBuilder.ChunkEnumerator chunks = sb.GetChunks();
+
+ bool more = chunks.MoveNext();
+ while (more)
+ {
+ ReadOnlySpan<char> current = chunks.Current.Span;
+ more = chunks.MoveNext();
+
+ // If final chunk, include the newline if needed
+ WriteSpan(current, appendNewLine: more ? false : appendNewLine);
+ }
+
+ StringBuilderCache.Release(sb);
+ }
+
+ public override void Write(string format, object arg0)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg0), appendNewLine: false);
+ }
+ else
+ {
+ base.Write(format, arg0);
+ }
+ }
+
+ public override void Write(string format, object arg0, object arg1)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg0, arg1), appendNewLine: false);
+ }
+ else
+ {
+ base.Write(format, arg0, arg1);
+ }
+ }
+
+ public override void Write(string format, object arg0, object arg1, object arg2)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg0, arg1, arg2), appendNewLine: false);
+ }
+ else
+ {
+ base.Write(format, arg0, arg1, arg2);
+ }
+ }
+
+ public override void Write(string format, params object[] arg)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg), appendNewLine: false);
+ }
+ else
+ {
+ base.Write(format, arg);
+ }
+ }
+
+ public override void WriteLine(string format, object arg0)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg0), appendNewLine: true);
+ }
+ else
+ {
+ base.WriteLine(format, arg0);
+ }
+ }
+
+ public override void WriteLine(string format, object arg0, object arg1)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg0, arg1), appendNewLine: true);
+ }
+ else
+ {
+ base.WriteLine(format, arg0, arg1);
+ }
+ }
+
+ public override void WriteLine(string format, object arg0, object arg1, object arg2)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg0, arg1, arg2), appendNewLine: true);
+ }
+ else
+ {
+ base.WriteLine(format, arg0, arg1, arg2);
+ }
+ }
+
+ public override void WriteLine(string format, params object[] arg)
+ {
+ if (GetType() == typeof(StreamWriter))
+ {
+ WriteFormatHelper(format, new ParamsArray(arg), appendNewLine: true);
+ }
+ else
+ {
+ base.WriteLine(format, arg);
+ }
+ }
+
#region Task based Async APIs
public override Task WriteAsync(char value)
{
@@ -955,7 +1082,7 @@ namespace System.IO
// to ensure performant access inside the state machine that corresponds this async method.
private static async Task FlushAsyncInternal(StreamWriter _this, bool flushStream, bool flushEncoder,
char[] charBuffer, int charPos, bool haveWrittenPreamble,
- Encoding encoding, Encoder encoder, Byte[] byteBuffer, Stream stream, CancellationToken cancellationToken)
+ Encoding encoding, Encoder encoder, byte[] byteBuffer, Stream stream, CancellationToken cancellationToken)
{
if (!haveWrittenPreamble)
{
diff --git a/src/System.Private.CoreLib/shared/System/IO/TextReader.cs b/src/System.Private.CoreLib/shared/System/IO/TextReader.cs
index eb94dd759..bb5b142bd 100644
--- a/src/System.Private.CoreLib/shared/System/IO/TextReader.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/TextReader.cs
@@ -207,7 +207,7 @@ namespace System.IO
#region Task based Async APIs
public virtual Task<string> ReadLineAsync()
{
- return Task<String>.Factory.StartNew(state =>
+ return Task<string>.Factory.StartNew(state =>
{
return ((TextReader)state).ReadLine();
},
@@ -251,7 +251,7 @@ namespace System.IO
return ReadAsyncInternal(new Memory<char>(buffer, index, count), default).AsTask();
}
- public virtual ValueTask<int> ReadAsync(Memory<char> buffer, CancellationToken cancellationToken = default(CancellationToken)) =>
+ public virtual ValueTask<int> ReadAsync(Memory<char> buffer, CancellationToken cancellationToken = default) =>
new ValueTask<int>(MemoryMarshal.TryGetArray(buffer, out ArraySegment<char> array) ?
ReadAsync(array.Array, array.Offset, array.Count) :
Task<int>.Factory.StartNew(state =>
@@ -289,7 +289,7 @@ namespace System.IO
return ReadBlockAsyncInternal(new Memory<char>(buffer, index, count), default).AsTask();
}
- public virtual ValueTask<int> ReadBlockAsync(Memory<char> buffer, CancellationToken cancellationToken = default(CancellationToken)) =>
+ public virtual ValueTask<int> ReadBlockAsync(Memory<char> buffer, CancellationToken cancellationToken = default) =>
new ValueTask<int>(MemoryMarshal.TryGetArray(buffer, out ArraySegment<char> array) ?
ReadBlockAsync(array.Array, array.Offset, array.Count) :
Task<int>.Factory.StartNew(state =>
diff --git a/src/System.Private.CoreLib/shared/System/IO/TextWriter.cs b/src/System.Private.CoreLib/shared/System/IO/TextWriter.cs
index 48e702be6..547c597f0 100644
--- a/src/System.Private.CoreLib/shared/System/IO/TextWriter.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/TextWriter.cs
@@ -13,24 +13,24 @@ using System.Buffers;
namespace System.IO
{
// This abstract base class represents a writer that can write a sequential
- // stream of characters. A subclass must minimally implement the
+ // stream of characters. A subclass must minimally implement the
// Write(char) method.
//
- // This class is intended for character output, not bytes.
- // There are methods on the Stream class for writing bytes.
+ // This class is intended for character output, not bytes.
+ // There are methods on the Stream class for writing bytes.
public abstract partial class TextWriter : MarshalByRefObject, IDisposable
{
public static readonly TextWriter Null = new NullTextWriter();
- // We don't want to allocate on every TextWriter creation, so cache the char array.
+ // We don't want to allocate on every TextWriter creation, so cache the char array.
private static readonly char[] s_coreNewLine = Environment.NewLine.ToCharArray();
/// <summary>
- /// This is the 'NewLine' property expressed as a char[].
+ /// This is the 'NewLine' property expressed as a char[].
/// It is exposed to subclasses as a protected field for read-only
- /// purposes. You should only modify it by using the 'NewLine' property.
- /// In particular you should never modify the elements of the array
- /// as they are shared among many instances of TextWriter.
+ /// purposes. You should only modify it by using the 'NewLine' property.
+ /// In particular you should never modify the elements of the array
+ /// as they are shared among many instances of TextWriter.
/// </summary>
protected char[] CoreNewLine = s_coreNewLine;
private string CoreNewLineStr = Environment.NewLine;
@@ -94,7 +94,7 @@ namespace System.IO
/// <summary>
/// Returns the line terminator string used by this TextWriter. The default line
- /// terminator string is Environment.NewLine, which is platform specific.
+ /// terminator string is Environment.NewLine, which is platform specific.
/// On Windows this is a carriage return followed by a line feed ("\r\n").
/// On OSX and Linux this is a line feed ("\n").
/// </summary>
@@ -184,7 +184,7 @@ namespace System.IO
}
// Writes the text representation of a boolean to the text stream. This
- // method outputs either Boolean.TrueString or Boolean.FalseString.
+ // method outputs either bool.TrueString or bool.FalseString.
//
public virtual void Write(bool value)
{
@@ -193,7 +193,7 @@ namespace System.IO
// Writes the text representation of an integer to the text stream. The
// text representation of the given value is produced by calling the
- // Int32.ToString() method.
+ // int.ToString() method.
//
public virtual void Write(int value)
{
@@ -202,7 +202,7 @@ namespace System.IO
// Writes the text representation of an integer to the text stream. The
// text representation of the given value is produced by calling the
- // UInt32.ToString() method.
+ // uint.ToString() method.
//
[CLSCompliant(false)]
public virtual void Write(uint value)
@@ -212,16 +212,16 @@ namespace System.IO
// Writes the text representation of a long to the text stream. The
// text representation of the given value is produced by calling the
- // Int64.ToString() method.
+ // long.ToString() method.
//
public virtual void Write(long value)
{
Write(value.ToString(FormatProvider));
}
- // Writes the text representation of an unsigned long to the text
- // stream. The text representation of the given value is produced
- // by calling the UInt64.ToString() method.
+ // Writes the text representation of an unsigned long to the text
+ // stream. The text representation of the given value is produced
+ // by calling the ulong.ToString() method.
//
[CLSCompliant(false)]
public virtual void Write(ulong value)
@@ -231,7 +231,7 @@ namespace System.IO
// Writes the text representation of a float to the text stream. The
// text representation of the given value is produced by calling the
- // Float.toString(float) method.
+ // float.ToString(float) method.
//
public virtual void Write(float value)
{
@@ -240,7 +240,7 @@ namespace System.IO
// Writes the text representation of a double to the text stream. The
// text representation of the given value is produced by calling the
- // Double.toString(double) method.
+ // double.ToString(double) method.
//
public virtual void Write(double value)
{
@@ -283,33 +283,48 @@ namespace System.IO
}
}
+ /// <summary>
+ /// Equivalent to Write(stringBuilder.ToString()) however it uses the
+ /// StringBuilder.GetChunks() method to avoid creating the intermediate string
+ /// </summary>
+ /// <param name="value">The string (as a StringBuilder) to write to the stream</param>
+ public virtual void Write(StringBuilder value)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException(nameof(value));
+ }
+ foreach (ReadOnlyMemory<char> chunk in value.GetChunks())
+ Write(chunk);
+ }
+
// Writes out a formatted string. Uses the same semantics as
- // String.Format.
- //
+ // string.Format.
+ //
public virtual void Write(string format, object arg0)
{
Write(string.Format(FormatProvider, format, arg0));
}
// Writes out a formatted string. Uses the same semantics as
- // String.Format.
- //
+ // string.Format.
+ //
public virtual void Write(string format, object arg0, object arg1)
{
Write(string.Format(FormatProvider, format, arg0, arg1));
}
// Writes out a formatted string. Uses the same semantics as
- // String.Format.
- //
+ // string.Format.
+ //
public virtual void Write(string format, object arg0, object arg1, object arg2)
{
Write(string.Format(FormatProvider, format, arg0, arg1, arg2));
}
// Writes out a formatted string. Uses the same semantics as
- // String.Format.
- //
+ // string.Format.
+ //
public virtual void Write(string format, params object[] arg)
{
Write(string.Format(FormatProvider, format, arg));
@@ -383,7 +398,7 @@ namespace System.IO
WriteLine();
}
- // Writes the text representation of an unsigned integer followed by
+ // Writes the text representation of an unsigned integer followed by
// a line terminator to the text stream.
//
[CLSCompliant(false)]
@@ -402,7 +417,7 @@ namespace System.IO
WriteLine();
}
- // Writes the text representation of an unsigned long followed by
+ // Writes the text representation of an unsigned long followed by
// a line terminator to the text stream.
//
[CLSCompliant(false)]
@@ -447,6 +462,16 @@ namespace System.IO
Write(CoreNewLineStr);
}
+ /// <summary>
+ /// Equivalent to WriteLine(stringBuilder.ToString()) however it uses the
+ /// StringBuilder.GetChunks() method to avoid creating the intermediate string
+ /// </summary>
+ public virtual void WriteLine(StringBuilder value)
+ {
+ Write(value);
+ WriteLine();
+ }
+
// Writes the text representation of an object followed by a line
// terminator to the text stream.
//
@@ -472,33 +497,33 @@ namespace System.IO
}
}
- // Writes out a formatted string and a new line. Uses the same
- // semantics as String.Format.
- //
+ // Writes out a formatted string and a new line. Uses the same
+ // semantics as string.Format.
+ //
public virtual void WriteLine(string format, object arg0)
{
WriteLine(string.Format(FormatProvider, format, arg0));
}
- // Writes out a formatted string and a new line. Uses the same
- // semantics as String.Format.
- //
+ // Writes out a formatted string and a new line. Uses the same
+ // semantics as string.Format.
+ //
public virtual void WriteLine(string format, object arg0, object arg1)
{
WriteLine(string.Format(FormatProvider, format, arg0, arg1));
}
- // Writes out a formatted string and a new line. Uses the same
- // semantics as String.Format.
- //
+ // Writes out a formatted string and a new line. Uses the same
+ // semantics as string.Format.
+ //
public virtual void WriteLine(string format, object arg0, object arg1, object arg2)
{
WriteLine(string.Format(FormatProvider, format, arg0, arg1, arg2));
}
- // Writes out a formatted string and a new line. Uses the same
- // semantics as String.Format.
- //
+ // Writes out a formatted string and a new line. Uses the same
+ // semantics as string.Format.
+ //
public virtual void WriteLine(string format, params object[] arg)
{
WriteLine(string.Format(FormatProvider, format, arg));
@@ -527,6 +552,27 @@ namespace System.IO
tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
}
+ /// <summary>
+ /// Equivalent to WriteAsync(stringBuilder.ToString()) however it uses the
+ /// StringBuilder.GetChunks() method to avoid creating the intermediate string
+ /// </summary>
+ /// <param name="value">The string (as a StringBuilder) to write to the stream</param>
+ public virtual Task WriteAsync(StringBuilder value, CancellationToken cancellationToken = default)
+ {
+ return
+ cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) :
+ value == null ? Task.CompletedTask :
+ WriteAsyncCore(value, cancellationToken);
+
+ async Task WriteAsyncCore(StringBuilder sb, CancellationToken ct)
+ {
+ foreach (ReadOnlyMemory<char> chunk in sb.GetChunks())
+ {
+ await WriteAsync(chunk, ct).ConfigureAwait(false);
+ }
+ }
+ }
+
public Task WriteAsync(char[] buffer)
{
if (buffer == null)
@@ -548,7 +594,8 @@ namespace System.IO
tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
}
- public virtual Task WriteAsync(ReadOnlyMemory<char> buffer, CancellationToken cancellationToken = default(CancellationToken)) =>
+ public virtual Task WriteAsync(ReadOnlyMemory<char> buffer, CancellationToken cancellationToken = default) =>
+ cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) :
MemoryMarshal.TryGetArray(buffer, out ArraySegment<char> array) ?
WriteAsync(array.Array, array.Offset, array.Count) :
Task.Factory.StartNew(state =>
@@ -579,6 +626,28 @@ namespace System.IO
tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
}
+ /// <summary>
+ /// Equivalent to WriteLineAsync(stringBuilder.ToString()) however it uses the
+ /// StringBuilder.GetChunks() method to avoid creating the intermediate string
+ /// </summary>
+ /// <param name="value">The string (as a StringBuilder) to write to the stream</param>
+ public virtual Task WriteLineAsync(StringBuilder value, CancellationToken cancellationToken = default)
+ {
+ return
+ cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) :
+ value == null ? WriteAsync(CoreNewLine, cancellationToken) :
+ WriteLineAsyncCore(value, cancellationToken);
+
+ async Task WriteLineAsyncCore(StringBuilder sb, CancellationToken ct)
+ {
+ foreach (ReadOnlyMemory<char> chunk in sb.GetChunks())
+ {
+ await WriteAsync(chunk, ct).ConfigureAwait(false);
+ }
+ await WriteAsync(CoreNewLine, ct).ConfigureAwait(false);
+ }
+ }
+
public Task WriteLineAsync(char[] buffer)
{
if (buffer == null)
@@ -600,7 +669,8 @@ namespace System.IO
tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
}
- public virtual Task WriteLineAsync(ReadOnlyMemory<char> buffer, CancellationToken cancellationToken = default(CancellationToken)) =>
+ public virtual Task WriteLineAsync(ReadOnlyMemory<char> buffer, CancellationToken cancellationToken = default) =>
+ cancellationToken.IsCancellationRequested ? Task.FromCanceled(cancellationToken) :
MemoryMarshal.TryGetArray(buffer, out ArraySegment<char> array) ?
WriteLineAsync(array.Array, array.Offset, array.Count) :
Task.Factory.StartNew(state =>
@@ -739,12 +809,15 @@ namespace System.IO
public override void Write(double value) => _out.Write(value);
[MethodImpl(MethodImplOptions.Synchronized)]
- public override void Write(Decimal value) => _out.Write(value);
+ public override void Write(decimal value) => _out.Write(value);
[MethodImpl(MethodImplOptions.Synchronized)]
public override void Write(string value) => _out.Write(value);
[MethodImpl(MethodImplOptions.Synchronized)]
+ public override void Write(StringBuilder value) => _out.Write(value);
+
+ [MethodImpl(MethodImplOptions.Synchronized)]
public override void Write(object value) => _out.Write(value);
[MethodImpl(MethodImplOptions.Synchronized)]
@@ -799,6 +872,9 @@ namespace System.IO
public override void WriteLine(string value) => _out.WriteLine(value);
[MethodImpl(MethodImplOptions.Synchronized)]
+ public override void WriteLine(StringBuilder value) => _out.WriteLine(value);
+
+ [MethodImpl(MethodImplOptions.Synchronized)]
public override void WriteLine(object value) => _out.WriteLine(value);
[MethodImpl(MethodImplOptions.Synchronized)]
@@ -832,6 +908,13 @@ namespace System.IO
}
[MethodImpl(MethodImplOptions.Synchronized)]
+ public override Task WriteAsync(StringBuilder value, CancellationToken cancellationToken = default)
+ {
+ Write(value);
+ return Task.CompletedTask;
+ }
+
+ [MethodImpl(MethodImplOptions.Synchronized)]
public override Task WriteAsync(char[] buffer, int index, int count)
{
Write(buffer, index, count);
@@ -853,6 +936,13 @@ namespace System.IO
}
[MethodImpl(MethodImplOptions.Synchronized)]
+ public override Task WriteLineAsync(StringBuilder value, CancellationToken cancellationToken = default)
+ {
+ WriteLine(value);
+ return Task.CompletedTask;
+ }
+
+ [MethodImpl(MethodImplOptions.Synchronized)]
public override Task WriteLineAsync(char[] buffer, int index, int count)
{
WriteLine(buffer, index, count);
diff --git a/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStream.cs b/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStream.cs
index d1a13156a..d4af4cfee 100644
--- a/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStream.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStream.cs
@@ -47,7 +47,7 @@ namespace System.IO
private long _offset;
private FileAccess _access;
private bool _isOpen;
- private Task<Int32> _lastReadTask; // The last successful task returned from ReadAsync
+ private Task<int> _lastReadTask; // The last successful task returned from ReadAsync
/// <summary>
/// Creates a closed stream.
@@ -379,22 +379,22 @@ namespace System.IO
return ReadCore(new Span<byte>(buffer, offset, count));
}
- public override int Read(Span<byte> destination)
+ public override int Read(Span<byte> buffer)
{
if (GetType() == typeof(UnmanagedMemoryStream))
{
- return ReadCore(destination);
+ return ReadCore(buffer);
}
else
{
// UnmanagedMemoryStream is not sealed, and a derived type may have overridden Read(byte[], int, int) prior
// to this Read(Span<byte>) overload being introduced. In that case, this Read(Span<byte>) overload
// should use the behavior of Read(byte[],int,int) overload.
- return base.Read(destination);
+ return base.Read(buffer);
}
}
- internal int ReadCore(Span<byte> destination)
+ internal int ReadCore(Span<byte> buffer)
{
EnsureNotClosed();
EnsureReadable();
@@ -403,7 +403,7 @@ namespace System.IO
// changes our position after we decide we can read some bytes.
long pos = Interlocked.Read(ref _position);
long len = Interlocked.Read(ref _length);
- long n = Math.Min(len - pos, destination.Length);
+ long n = Math.Min(len - pos, buffer.Length);
if (n <= 0)
{
return 0;
@@ -418,7 +418,7 @@ namespace System.IO
unsafe
{
- fixed (byte* pBuffer = &MemoryMarshal.GetReference(destination))
+ fixed (byte* pBuffer = &MemoryMarshal.GetReference(buffer))
{
if (_buffer != null)
{
@@ -456,7 +456,7 @@ namespace System.IO
/// <param name="count">Maximum number of bytes to read.</param>
/// <param name="cancellationToken">Token that can be used to cancel this operation.</param>
/// <returns>Task that can be used to access the number of bytes actually read.</returns>
- public override Task<Int32> ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
+ public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer), SR.ArgumentNull_Buffer);
@@ -468,27 +468,27 @@ namespace System.IO
throw new ArgumentException(SR.Argument_InvalidOffLen);
if (cancellationToken.IsCancellationRequested)
- return Task.FromCanceled<Int32>(cancellationToken);
+ return Task.FromCanceled<int>(cancellationToken);
try
{
- Int32 n = Read(buffer, offset, count);
- Task<Int32> t = _lastReadTask;
+ int n = Read(buffer, offset, count);
+ Task<int> t = _lastReadTask;
return (t != null && t.Result == n) ? t : (_lastReadTask = Task.FromResult<Int32>(n));
}
catch (Exception ex)
{
Debug.Assert(!(ex is OperationCanceledException));
- return Task.FromException<Int32>(ex);
+ return Task.FromException<int>(ex);
}
}
/// <summary>
/// Reads bytes from stream and puts them into the buffer
/// </summary>
- /// <param name="destination">Buffer to read the bytes to.</param>
+ /// <param name="buffer">Buffer to read the bytes to.</param>
/// <param name="cancellationToken">Token that can be used to cancel this operation.</param>
- public override ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken = default(CancellationToken))
+ public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -510,9 +510,9 @@ namespace System.IO
// something other than an array and this is an UnmanagedMemoryStream-derived type that doesn't override Read(Span<byte>) will
// it then fall back to doing the ArrayPool/copy behavior.
return new ValueTask<int>(
- MemoryMarshal.TryGetArray(destination, out ArraySegment<byte> destinationArray) ?
+ MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> destinationArray) ?
Read(destinationArray.Array, destinationArray.Offset, destinationArray.Count) :
- Read(destination.Span));
+ Read(buffer.Span));
}
catch (Exception ex)
{
@@ -659,29 +659,29 @@ namespace System.IO
WriteCore(new Span<byte>(buffer, offset, count));
}
- public override void Write(ReadOnlySpan<byte> source)
+ public override void Write(ReadOnlySpan<byte> buffer)
{
if (GetType() == typeof(UnmanagedMemoryStream))
{
- WriteCore(source);
+ WriteCore(buffer);
}
else
{
// UnmanagedMemoryStream is not sealed, and a derived type may have overridden Write(byte[], int, int) prior
// to this Write(Span<byte>) overload being introduced. In that case, this Write(Span<byte>) overload
// should use the behavior of Write(byte[],int,int) overload.
- base.Write(source);
+ base.Write(buffer);
}
}
- internal unsafe void WriteCore(ReadOnlySpan<byte> source)
+ internal unsafe void WriteCore(ReadOnlySpan<byte> buffer)
{
EnsureNotClosed();
EnsureWriteable();
long pos = Interlocked.Read(ref _position); // Use a local to avoid a race condition
long len = Interlocked.Read(ref _length);
- long n = pos + source.Length;
+ long n = pos + buffer.Length;
// Check for overflow
if (n < 0)
{
@@ -709,12 +709,12 @@ namespace System.IO
}
}
- fixed (byte* pBuffer = &MemoryMarshal.GetReference(source))
+ fixed (byte* pBuffer = &MemoryMarshal.GetReference(buffer))
{
if (_buffer != null)
{
long bytesLeft = _capacity - pos;
- if (bytesLeft < source.Length)
+ if (bytesLeft < buffer.Length)
{
throw new ArgumentException(SR.Arg_BufferTooSmall);
}
@@ -724,7 +724,7 @@ namespace System.IO
try
{
_buffer.AcquirePointer(ref pointer);
- Buffer.Memcpy(pointer + pos + _offset, pBuffer, source.Length);
+ Buffer.Memcpy(pointer + pos + _offset, pBuffer, buffer.Length);
}
finally
{
@@ -736,7 +736,7 @@ namespace System.IO
}
else
{
- Buffer.Memcpy(_mem + pos, pBuffer, source.Length);
+ Buffer.Memcpy(_mem + pos, pBuffer, buffer.Length);
}
}
@@ -752,7 +752,7 @@ namespace System.IO
/// <param name="count">Number of bytes to write.</param>
/// <param name="cancellationToken">Token that can be used to cancel the operation.</param>
/// <returns>Task that can be awaited </returns>
- public override Task WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
+ public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer), SR.ArgumentNull_Buffer);
@@ -783,7 +783,7 @@ namespace System.IO
/// </summary>
/// <param name="buffer">Buffer that will be written.</param>
/// <param name="cancellationToken">Token that can be used to cancel the operation.</param>
- public override ValueTask WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default(CancellationToken))
+ public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
{
if (cancellationToken.IsCancellationRequested)
{
@@ -794,13 +794,13 @@ namespace System.IO
{
// See corresponding comment in ReadAsync for why we don't just always use Write(ReadOnlySpan<byte>).
// Unlike ReadAsync, we could delegate to WriteAsync(byte[], ...) here, but we don't for consistency.
- if (MemoryMarshal.TryGetArray(source, out ArraySegment<byte> sourceArray))
+ if (MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> sourceArray))
{
Write(sourceArray.Array, sourceArray.Offset, sourceArray.Count);
}
else
{
- Write(source.Span);
+ Write(buffer.Span);
}
return default;
}
diff --git a/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStreamWrapper.cs b/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStreamWrapper.cs
index f34c3c413..9a598951e 100644
--- a/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStreamWrapper.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/UnmanagedMemoryStreamWrapper.cs
@@ -71,7 +71,7 @@ namespace System.IO
public override bool TryGetBuffer(out ArraySegment<byte> buffer)
{
- buffer = default(ArraySegment<byte>);
+ buffer = default;
return false;
}
@@ -112,9 +112,9 @@ namespace System.IO
return _unmanagedStream.Read(buffer, offset, count);
}
- public override int Read(Span<byte> destination)
+ public override int Read(Span<byte> buffer)
{
- return _unmanagedStream.Read(destination);
+ return _unmanagedStream.Read(buffer);
}
public override int ReadByte()
@@ -139,9 +139,9 @@ namespace System.IO
_unmanagedStream.Write(buffer, offset, count);
}
- public override void Write(ReadOnlySpan<byte> source)
+ public override void Write(ReadOnlySpan<byte> buffer)
{
- _unmanagedStream.Write(source);
+ _unmanagedStream.Write(buffer);
}
public override void WriteByte(byte value)
@@ -160,7 +160,7 @@ namespace System.IO
stream.Write(buffer, 0, buffer.Length);
}
- public override void SetLength(Int64 value)
+ public override void SetLength(long value)
{
// This was probably meant to call _unmanagedStream.SetLength(value), but it was forgotten in V.4.0.
// Now this results in a call to the base which touches the underlying array which is never actually used.
@@ -169,7 +169,7 @@ namespace System.IO
}
- public override Task CopyToAsync(Stream destination, Int32 bufferSize, CancellationToken cancellationToken)
+ public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
{
// The parameter checks must be in sync with the base version:
if (destination == null)
@@ -201,25 +201,25 @@ namespace System.IO
}
- public override Task<Int32> ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
+ public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
return _unmanagedStream.ReadAsync(buffer, offset, count, cancellationToken);
}
- public override ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken = default(CancellationToken))
+ public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
{
- return _unmanagedStream.ReadAsync(destination, cancellationToken);
+ return _unmanagedStream.ReadAsync(buffer, cancellationToken);
}
- public override Task WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
+ public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
return _unmanagedStream.WriteAsync(buffer, offset, count, cancellationToken);
}
- public override ValueTask WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default(CancellationToken))
+ public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
{
- return _unmanagedStream.WriteAsync(source, cancellationToken);
+ return _unmanagedStream.WriteAsync(buffer, cancellationToken);
}
} // class UnmanagedMemoryStreamWrapper
} // namespace
diff --git a/src/System.Private.CoreLib/shared/System/IO/Win32Marshal.cs b/src/System.Private.CoreLib/shared/System/IO/Win32Marshal.cs
index b8b305776..cf1d94cba 100644
--- a/src/System.Private.CoreLib/shared/System/IO/Win32Marshal.cs
+++ b/src/System.Private.CoreLib/shared/System/IO/Win32Marshal.cs
@@ -2,14 +2,12 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-using System.Diagnostics;
using System.Runtime.InteropServices;
namespace System.IO
{
/// <summary>
- /// Provides static methods for converting from Win32 errors codes to exceptions, HRESULTS and error messages.
+ /// Provides static methods for converting from Win32 errors codes to exceptions, HRESULTS and error messages.
/// </summary>
internal static class Win32Marshal
{
@@ -22,94 +20,84 @@ namespace System.IO
#endif
/// <summary>
- /// Converts, resetting it, the last Win32 error into a corresponding <see cref="Exception"/> object.
+ /// Converts, resetting it, the last Win32 error into a corresponding <see cref="Exception"/> object, optionally
+ /// including the specified path in the error message.
/// </summary>
- internal static Exception GetExceptionForLastWin32Error()
- {
- int errorCode = Marshal.GetLastWin32Error();
- return GetExceptionForWin32Error(errorCode, string.Empty);
- }
-
- /// <summary>
- /// Converts the specified Win32 error into a corresponding <see cref="Exception"/> object.
- /// </summary>
- internal static Exception GetExceptionForWin32Error(int errorCode)
- {
- return GetExceptionForWin32Error(errorCode, string.Empty);
- }
+ internal static Exception GetExceptionForLastWin32Error(string path = "")
+ => GetExceptionForWin32Error(Marshal.GetLastWin32Error(), path);
/// <summary>
- /// Converts the specified Win32 error into a corresponding <see cref="Exception"/> object, optionally
- /// including the specified path in the error message.
+ /// Converts the specified Win32 error into a corresponding <see cref="Exception"/> object, optionally
+ /// including the specified path in the error message.
/// </summary>
- internal static Exception GetExceptionForWin32Error(int errorCode, string path)
+ internal static Exception GetExceptionForWin32Error(int errorCode, string path = "")
{
switch (errorCode)
{
case Interop.Errors.ERROR_FILE_NOT_FOUND:
- if (path.Length == 0)
- return new FileNotFoundException(SR.IO_FileNotFound);
- else
- return new FileNotFoundException(SR.Format(SR.IO_FileNotFound_FileName, path), path);
-
+ return new FileNotFoundException(
+ string.IsNullOrEmpty(path) ? SR.IO_FileNotFound : SR.Format(SR.IO_FileNotFound_FileName, path), path);
case Interop.Errors.ERROR_PATH_NOT_FOUND:
- if (path.Length == 0)
- return new DirectoryNotFoundException(SR.IO_PathNotFound_NoPathName);
- else
- return new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, path));
-
+ return new DirectoryNotFoundException(
+ string.IsNullOrEmpty(path) ? SR.IO_PathNotFound_NoPathName : SR.Format(SR.IO_PathNotFound_Path, path));
case Interop.Errors.ERROR_ACCESS_DENIED:
- if (path.Length == 0)
- return new UnauthorizedAccessException(SR.UnauthorizedAccess_IODenied_NoPathName);
- else
- return new UnauthorizedAccessException(SR.Format(SR.UnauthorizedAccess_IODenied_Path, path));
-
+ return new UnauthorizedAccessException(
+ string.IsNullOrEmpty(path) ? SR.UnauthorizedAccess_IODenied_NoPathName : SR.Format(SR.UnauthorizedAccess_IODenied_Path, path));
case Interop.Errors.ERROR_ALREADY_EXISTS:
- if (path.Length == 0)
+ if (string.IsNullOrEmpty(path))
goto default;
-
return new IOException(SR.Format(SR.IO_AlreadyExists_Name, path), MakeHRFromErrorCode(errorCode));
-
case Interop.Errors.ERROR_FILENAME_EXCED_RANGE:
- if (path.Length == 0)
- return new PathTooLongException(SR.IO_PathTooLong);
- else
- return new PathTooLongException(SR.Format(SR.IO_PathTooLong_Path, path));
-
- case Interop.Errors.ERROR_INVALID_DRIVE:
- throw new DriveNotFoundException(SR.Format(SR.IO_DriveNotFound_Drive, path));
-
- case Interop.Errors.ERROR_INVALID_PARAMETER:
- return new IOException(Interop.Kernel32.GetMessage(errorCode), MakeHRFromErrorCode(errorCode));
-
+ return new PathTooLongException(
+ string.IsNullOrEmpty(path) ? SR.IO_PathTooLong : SR.Format(SR.IO_PathTooLong_Path, path));
case Interop.Errors.ERROR_SHARING_VIOLATION:
- if (path.Length == 0)
- return new IOException(SR.IO_SharingViolation_NoFileName, MakeHRFromErrorCode(errorCode));
- else
- return new IOException(SR.Format(SR.IO_SharingViolation_File, path), MakeHRFromErrorCode(errorCode));
-
+ return new IOException(
+ string.IsNullOrEmpty(path) ? SR.IO_SharingViolation_NoFileName : SR.Format(SR.IO_SharingViolation_File, path),
+ MakeHRFromErrorCode(errorCode));
case Interop.Errors.ERROR_FILE_EXISTS:
- if (path.Length == 0)
+ if (string.IsNullOrEmpty(path))
goto default;
-
return new IOException(SR.Format(SR.IO_FileExists_Name, path), MakeHRFromErrorCode(errorCode));
-
case Interop.Errors.ERROR_OPERATION_ABORTED:
return new OperationCanceledException();
-
+ case Interop.Errors.ERROR_INVALID_PARAMETER:
default:
- return new IOException(Interop.Kernel32.GetMessage(errorCode), MakeHRFromErrorCode(errorCode));
+ return new IOException(
+ string.IsNullOrEmpty(path) ? GetMessage(errorCode) : $"{GetMessage(errorCode)} : '{path}'",
+ MakeHRFromErrorCode(errorCode));
}
}
/// <summary>
- /// Returns a HRESULT for the specified Win32 error code.
+ /// If not already an HRESULT, returns an HRESULT for the specified Win32 error code.
/// </summary>
internal static int MakeHRFromErrorCode(int errorCode)
{
- Debug.Assert((0xFFFF0000 & errorCode) == 0, "This is an HRESULT, not an error code!");
+ // Don't convert it if it is already an HRESULT
+ if ((0xFFFF0000 & errorCode) != 0)
+ return errorCode;
return unchecked(((int)0x80070000) | errorCode);
}
+
+ /// <summary>
+ /// Returns a Win32 error code for the specified HRESULT if it came from FACILITY_WIN32
+ /// If not, returns the HRESULT unchanged
+ /// </summary>
+ internal static int TryMakeWin32ErrorCodeFromHR(int hr)
+ {
+ if ((0xFFFF0000 & hr) == 0x80070000)
+ {
+ // Win32 error, Win32Marshal.GetExceptionForWin32Error expects the Win32 format
+ hr &= 0x0000FFFF;
+ }
+
+ return hr;
+ }
+
+ /// <summary>
+ /// Returns a string message for the specified Win32 error code.
+ /// </summary>
+ internal static string GetMessage(int errorCode) => Interop.Kernel32.GetMessage(errorCode);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/IndexOutOfRangeException.cs b/src/System.Private.CoreLib/shared/System/IndexOutOfRangeException.cs
index b6d93ef56..aadc94231 100644
--- a/src/System.Private.CoreLib/shared/System/IndexOutOfRangeException.cs
+++ b/src/System.Private.CoreLib/shared/System/IndexOutOfRangeException.cs
@@ -25,13 +25,13 @@ namespace System
HResult = HResults.COR_E_INDEXOUTOFRANGE;
}
- public IndexOutOfRangeException(String message)
+ public IndexOutOfRangeException(string message)
: base(message)
{
HResult = HResults.COR_E_INDEXOUTOFRANGE;
}
- public IndexOutOfRangeException(String message, Exception innerException)
+ public IndexOutOfRangeException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_INDEXOUTOFRANGE;
diff --git a/src/System.Private.CoreLib/shared/System/InsufficientExecutionStackException.cs b/src/System.Private.CoreLib/shared/System/InsufficientExecutionStackException.cs
index 4822028f8..4c4bf242e 100644
--- a/src/System.Private.CoreLib/shared/System/InsufficientExecutionStackException.cs
+++ b/src/System.Private.CoreLib/shared/System/InsufficientExecutionStackException.cs
@@ -16,13 +16,13 @@ namespace System
HResult = HResults.COR_E_INSUFFICIENTEXECUTIONSTACK;
}
- public InsufficientExecutionStackException(String message)
+ public InsufficientExecutionStackException(string message)
: base(message)
{
HResult = HResults.COR_E_INSUFFICIENTEXECUTIONSTACK;
}
- public InsufficientExecutionStackException(String message, Exception innerException)
+ public InsufficientExecutionStackException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_INSUFFICIENTEXECUTIONSTACK;
diff --git a/src/System.Private.CoreLib/src/System/InsufficientMemoryException.cs b/src/System.Private.CoreLib/shared/System/InsufficientMemoryException.cs
index 4c510c4d7..baa5c9e24 100644
--- a/src/System.Private.CoreLib/src/System/InsufficientMemoryException.cs
+++ b/src/System.Private.CoreLib/shared/System/InsufficientMemoryException.cs
@@ -2,46 +2,43 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-/*=============================================================================
-**
-**
-**
-** Purpose: The exception class for running out of memory
-** but most likely in a non-fatal way that shouldn't
-** be affected by escalation policy. Use this for cases
-** like MemoryFailPoint or a TryAllocate method, where you
-** expect OOM's with no shared state corruption and you
-** want to recover from these errors.
-**
-**
-=============================================================================*/
-
using System;
using System.Runtime.Serialization;
namespace System
{
+ /// <summary>
+ /// Purpose: The exception class for running out of memory
+ /// but most likely in a non-fatal way that shouldn't
+ /// be affected by escalation policy. Use this for cases
+ /// like MemoryFailPoint or a TryAllocate method, where you
+ /// expect OOM's with no shared state corruption and you
+ /// want to recover from these errors.
+ /// </summary>
[Serializable]
#if !MONO
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
#endif
public sealed class InsufficientMemoryException : OutOfMemoryException
{
- // There may be a problem here interacting with the ResourceManager in out of memory conditions,
- // CoreCLR can fall back to literal strings.
- public InsufficientMemoryException()
- : base(SR.Arg_OutOfMemoryException)
+ public InsufficientMemoryException() : base(
+#if CORECLR
+ GetMessageFromNativeResources(ExceptionMessageKind.OutOfMemory)
+#else
+ SR.Arg_OutOfMemoryException
+#endif
+ )
{
HResult = HResults.COR_E_INSUFFICIENTMEMORY;
}
- public InsufficientMemoryException(String message)
+ public InsufficientMemoryException(string message)
: base(message)
{
HResult = HResults.COR_E_INSUFFICIENTMEMORY;
}
- public InsufficientMemoryException(String message, Exception innerException)
+ public InsufficientMemoryException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_INSUFFICIENTMEMORY;
@@ -49,6 +46,6 @@ namespace System
private InsufficientMemoryException(SerializationInfo info, StreamingContext context) : base(info, context)
{
- }
+ }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Int16.cs b/src/System.Private.CoreLib/shared/System/Int16.cs
index fecc87e9f..497329976 100644
--- a/src/System.Private.CoreLib/shared/System/Int16.cs
+++ b/src/System.Private.CoreLib/shared/System/Int16.cs
@@ -12,9 +12,9 @@ namespace System
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct Int16 : IComparable, IConvertible, IFormattable, IComparable<Int16>, IEquatable<Int16>, ISpanFormattable
+ public readonly struct Int16 : IComparable, IConvertible, IFormattable, IComparable<short>, IEquatable<short>, ISpanFormattable
{
- private short m_value; // Do not rename (binary serialization)
+ private readonly short m_value; // Do not rename (binary serialization)
public const short MaxValue = (short)0x7FFF;
public const short MinValue = unchecked((short)0x8000);
@@ -25,37 +25,37 @@ namespace System
// null is considered to be less than any instance.
// If object is not of type Int16, this method throws an ArgumentException.
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
- if (value is Int16)
+ if (value is short)
{
- return m_value - ((Int16)value).m_value;
+ return m_value - ((short)value).m_value;
}
throw new ArgumentException(SR.Arg_MustBeInt16);
}
- public int CompareTo(Int16 value)
+ public int CompareTo(short value)
{
return m_value - value;
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is Int16))
+ if (!(obj is short))
{
return false;
}
- return m_value == ((Int16)obj).m_value;
+ return m_value == ((short)obj).m_value;
}
[NonVersionable]
- public bool Equals(Int16 obj)
+ public bool Equals(short obj)
{
return m_value == obj;
}
@@ -67,22 +67,22 @@ namespace System
}
- public override String ToString()
+ public override string ToString()
{
return Number.FormatInt32(m_value, null, null);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return Number.FormatInt32(m_value, null, provider);
}
- public String ToString(String format)
+ public string ToString(string format)
{
return ToString(format, null);
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
if (m_value < 0 && format != null && format.Length > 0 && (format[0] == 'X' || format[0] == 'x'))
{
@@ -103,26 +103,26 @@ namespace System
return Number.TryFormatInt32(m_value, format, provider, destination, out charsWritten);
}
- public static short Parse(String s)
+ public static short Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}
- public static short Parse(String s, NumberStyles style)
+ public static short Parse(string s, NumberStyles style)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, style, NumberFormatInfo.CurrentInfo);
}
- public static short Parse(String s, IFormatProvider provider)
+ public static short Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
}
- public static short Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static short Parse(string s, NumberStyles style, IFormatProvider provider)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -151,7 +151,7 @@ namespace System
// for negative numbers
if ((style & NumberStyles.AllowHexSpecifier) != 0)
{ // We are parsing a hexadecimal number
- if ((i < 0) || (i > UInt16.MaxValue))
+ if ((i < 0) || (i > ushort.MaxValue))
{
throw new OverflowException(SR.Overflow_Int16);
}
@@ -162,7 +162,7 @@ namespace System
return (short)i;
}
- public static bool TryParse(String s, out Int16 result)
+ public static bool TryParse(string s, out short result)
{
if (s == null)
{
@@ -178,7 +178,7 @@ namespace System
return TryParse(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
}
- public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out Int16 result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out short result)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
@@ -197,7 +197,7 @@ namespace System
return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
}
- private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out Int16 result)
+ private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out short result)
{
result = 0;
int i;
@@ -210,11 +210,11 @@ namespace System
// for negative numbers
if ((style & NumberStyles.AllowHexSpecifier) != 0)
{ // We are parsing a hexadecimal number
- if ((i < 0) || i > UInt16.MaxValue)
+ if ((i < 0) || i > ushort.MaxValue)
{
return false;
}
- result = (Int16)i;
+ result = (short)i;
return true;
}
@@ -222,7 +222,7 @@ namespace System
{
return false;
}
- result = (Int16)i;
+ result = (short)i;
return true;
}
@@ -296,7 +296,7 @@ namespace System
return Convert.ToDouble(m_value);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -306,7 +306,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Int16", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/Int32.cs b/src/System.Private.CoreLib/shared/System/Int32.cs
index b573e950e..1d0aefe73 100644
--- a/src/System.Private.CoreLib/shared/System/Int32.cs
+++ b/src/System.Private.CoreLib/shared/System/Int32.cs
@@ -12,9 +12,9 @@ namespace System
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct Int32 : IComparable, IConvertible, IFormattable, IComparable<Int32>, IEquatable<Int32>, ISpanFormattable
+ public readonly struct Int32 : IComparable, IConvertible, IFormattable, IComparable<int>, IEquatable<int>, ISpanFormattable
{
- private int m_value; // Do not rename (binary serialization)
+ private readonly int m_value; // Do not rename (binary serialization)
public const int MaxValue = 0x7fffffff;
public const int MinValue = unchecked((int)0x80000000);
@@ -28,13 +28,13 @@ namespace System
// null is considered to be less than any instance, hence returns positive number
// If object is not of type Int32, this method throws an ArgumentException.
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
- if (value is Int32)
+ if (value is int)
{
// NOTE: Cannot use return (_value - value) as this causes a wrap
// around in cases where _value - value > MaxValue.
@@ -55,17 +55,17 @@ namespace System
return 0;
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is Int32))
+ if (!(obj is int))
{
return false;
}
- return m_value == ((Int32)obj).m_value;
+ return m_value == ((int)obj).m_value;
}
[NonVersionable]
- public bool Equals(Int32 obj)
+ public bool Equals(int obj)
{
return m_value == obj;
}
@@ -76,22 +76,22 @@ namespace System
return m_value;
}
- public override String ToString()
+ public override string ToString()
{
return Number.FormatInt32(m_value, null, null);
}
- public String ToString(String format)
+ public string ToString(string format)
{
return Number.FormatInt32(m_value, format, null);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return Number.FormatInt32(m_value, null, provider);
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
return Number.FormatInt32(m_value, format, provider);
}
@@ -101,13 +101,13 @@ namespace System
return Number.TryFormatInt32(m_value, format, provider, destination, out charsWritten);
}
- public static int Parse(String s)
+ public static int Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseInt32(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}
- public static int Parse(String s, NumberStyles style)
+ public static int Parse(string s, NumberStyles style)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -118,7 +118,7 @@ namespace System
// a NumberFormatInfo isn't specified, the current culture's
// NumberFormatInfo is assumed.
//
- public static int Parse(String s, IFormatProvider provider)
+ public static int Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseInt32(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
@@ -128,7 +128,7 @@ namespace System
// a NumberFormatInfo isn't specified, the current culture's
// NumberFormatInfo is assumed.
//
- public static int Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static int Parse(string s, NumberStyles style, IFormatProvider provider)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -144,7 +144,7 @@ namespace System
// Parses an integer from a String. Returns false rather
// than throwing exceptin if input is invalid
//
- public static bool TryParse(String s, out Int32 result)
+ public static bool TryParse(string s, out int result)
{
if (s == null)
{
@@ -163,7 +163,7 @@ namespace System
// Parses an integer from a String in the given style. Returns false rather
// than throwing exceptin if input is invalid
//
- public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out Int32 result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out int result)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
@@ -251,7 +251,7 @@ namespace System
return Convert.ToDouble(m_value);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -261,7 +261,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Int32", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/Int64.cs b/src/System.Private.CoreLib/shared/System/Int64.cs
index 0bcca8730..62c9ffd4f 100644
--- a/src/System.Private.CoreLib/shared/System/Int64.cs
+++ b/src/System.Private.CoreLib/shared/System/Int64.cs
@@ -12,9 +12,9 @@ namespace System
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct Int64 : IComparable, IConvertible, IFormattable, IComparable<Int64>, IEquatable<Int64>, ISpanFormattable
+ public readonly struct Int64 : IComparable, IConvertible, IFormattable, IComparable<long>, IEquatable<long>, ISpanFormattable
{
- private long m_value; // Do not rename (binary serialization)
+ private readonly long m_value; // Do not rename (binary serialization)
public const long MaxValue = 0x7fffffffffffffffL;
public const long MinValue = unchecked((long)0x8000000000000000L);
@@ -25,13 +25,13 @@ namespace System
// null is considered to be less than any instance.
// If object is not of type Int64, this method throws an ArgumentException.
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
- if (value is Int64)
+ if (value is long)
{
// Need to use compare because subtraction will wrap
// to positive for very large neg numbers, etc.
@@ -43,7 +43,7 @@ namespace System
throw new ArgumentException(SR.Arg_MustBeInt64);
}
- public int CompareTo(Int64 value)
+ public int CompareTo(long value)
{
// Need to use compare because subtraction will wrap
// to positive for very large neg numbers, etc.
@@ -52,17 +52,17 @@ namespace System
return 0;
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is Int64))
+ if (!(obj is long))
{
return false;
}
- return m_value == ((Int64)obj).m_value;
+ return m_value == ((long)obj).m_value;
}
[NonVersionable]
- public bool Equals(Int64 obj)
+ public bool Equals(long obj)
{
return m_value == obj;
}
@@ -73,22 +73,22 @@ namespace System
return (unchecked((int)((long)m_value)) ^ (int)(m_value >> 32));
}
- public override String ToString()
+ public override string ToString()
{
return Number.FormatInt64(m_value, null, null);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return Number.FormatInt64(m_value, null, provider);
}
- public String ToString(String format)
+ public string ToString(string format)
{
return Number.FormatInt64(m_value, format, null);
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
return Number.FormatInt64(m_value, format, provider);
}
@@ -98,20 +98,20 @@ namespace System
return Number.TryFormatInt64(m_value, format, provider, destination, out charsWritten);
}
- public static long Parse(String s)
+ public static long Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseInt64(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}
- public static long Parse(String s, NumberStyles style)
+ public static long Parse(string s, NumberStyles style)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseInt64(s, style, NumberFormatInfo.CurrentInfo);
}
- public static long Parse(String s, IFormatProvider provider)
+ public static long Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseInt64(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
@@ -122,7 +122,7 @@ namespace System
// a NumberFormatInfo isn't specified, the current culture's
// NumberFormatInfo is assumed.
//
- public static long Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static long Parse(string s, NumberStyles style, IFormatProvider provider)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -135,7 +135,7 @@ namespace System
return Number.ParseInt64(s, style, NumberFormatInfo.GetInstance(provider));
}
- public static Boolean TryParse(String s, out Int64 result)
+ public static bool TryParse(string s, out long result)
{
if (s == null)
{
@@ -151,7 +151,7 @@ namespace System
return Number.TryParseInt64(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
}
- public static Boolean TryParse(String s, NumberStyles style, IFormatProvider provider, out Int64 result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out long result)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
@@ -239,7 +239,7 @@ namespace System
return Convert.ToDouble(m_value);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -249,7 +249,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Int64", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/IntPtr.cs b/src/System.Private.CoreLib/shared/System/IntPtr.cs
index 45c2ded16..d23742fa7 100644
--- a/src/System.Private.CoreLib/shared/System/IntPtr.cs
+++ b/src/System.Private.CoreLib/shared/System/IntPtr.cs
@@ -17,13 +17,13 @@ namespace System
{
[Serializable]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct IntPtr : IEquatable<IntPtr>, ISerializable
+ public readonly struct IntPtr : IEquatable<IntPtr>, ISerializable
{
// WARNING: We allow diagnostic tools to directly inspect this member (_value).
// See https://github.com/dotnet/corert/blob/master/Documentation/design-docs/diagnostics/diagnostics-tools-contract.md for more details.
// Please do not change the type, the name, or the semantic usage of this member without understanding the implication for tools.
// Get in touch with the diagnostics team if you have questions.
- unsafe private void* _value; // Do not rename (binary serialization)
+ private readonly unsafe void* _value; // Do not rename (binary serialization)
[Intrinsic]
public static readonly IntPtr Zero;
@@ -72,7 +72,7 @@ namespace System
info.AddValue("value", ToInt64());
}
- public unsafe override bool Equals(Object obj)
+ public unsafe override bool Equals(object obj)
{
if (obj is IntPtr)
{
@@ -81,9 +81,9 @@ namespace System
return false;
}
- unsafe bool IEquatable<IntPtr>.Equals(IntPtr value)
+ unsafe bool IEquatable<IntPtr>.Equals(IntPtr other)
{
- return _value == value._value;
+ return _value == other._value;
}
public unsafe override int GetHashCode()
@@ -217,6 +217,9 @@ namespace System
[CLSCompliant(false)]
[Intrinsic]
[NonVersionable]
+#if PROJECTN
+ [System.Runtime.CompilerServices.DependencyReductionRootAttribute]
+#endif
public unsafe void* ToPointer()
{
return _value;
diff --git a/src/System.Private.CoreLib/shared/System/InvalidCastException.cs b/src/System.Private.CoreLib/shared/System/InvalidCastException.cs
index 055643278..cb6036aeb 100644
--- a/src/System.Private.CoreLib/shared/System/InvalidCastException.cs
+++ b/src/System.Private.CoreLib/shared/System/InvalidCastException.cs
@@ -22,19 +22,19 @@ namespace System
HResult = HResults.COR_E_INVALIDCAST;
}
- public InvalidCastException(String message)
+ public InvalidCastException(string message)
: base(message)
{
HResult = HResults.COR_E_INVALIDCAST;
}
- public InvalidCastException(String message, Exception innerException)
+ public InvalidCastException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_INVALIDCAST;
}
- public InvalidCastException(String message, int errorCode)
+ public InvalidCastException(string message, int errorCode)
: base(message)
{
HResult = errorCode;
diff --git a/src/System.Private.CoreLib/shared/System/InvalidOperationException.cs b/src/System.Private.CoreLib/shared/System/InvalidOperationException.cs
index 62c222af4..9fffbec43 100644
--- a/src/System.Private.CoreLib/shared/System/InvalidOperationException.cs
+++ b/src/System.Private.CoreLib/shared/System/InvalidOperationException.cs
@@ -26,13 +26,13 @@ namespace System
HResult = HResults.COR_E_INVALIDOPERATION;
}
- public InvalidOperationException(String message)
+ public InvalidOperationException(string message)
: base(message)
{
HResult = HResults.COR_E_INVALIDOPERATION;
}
- public InvalidOperationException(String message, Exception innerException)
+ public InvalidOperationException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_INVALIDOPERATION;
diff --git a/src/System.Private.CoreLib/shared/System/InvalidProgramException.cs b/src/System.Private.CoreLib/shared/System/InvalidProgramException.cs
index c8047c548..62a14f911 100644
--- a/src/System.Private.CoreLib/shared/System/InvalidProgramException.cs
+++ b/src/System.Private.CoreLib/shared/System/InvalidProgramException.cs
@@ -25,13 +25,13 @@ namespace System
HResult = HResults.COR_E_INVALIDPROGRAM;
}
- public InvalidProgramException(String message)
+ public InvalidProgramException(string message)
: base(message)
{
HResult = HResults.COR_E_INVALIDPROGRAM;
}
- public InvalidProgramException(String message, Exception inner)
+ public InvalidProgramException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_INVALIDPROGRAM;
diff --git a/src/System.Private.CoreLib/shared/System/InvalidTimeZoneException.cs b/src/System.Private.CoreLib/shared/System/InvalidTimeZoneException.cs
index 25b155e8d..1bbb7e067 100644
--- a/src/System.Private.CoreLib/shared/System/InvalidTimeZoneException.cs
+++ b/src/System.Private.CoreLib/shared/System/InvalidTimeZoneException.cs
@@ -14,12 +14,12 @@ namespace System
{
}
- public InvalidTimeZoneException(String message)
+ public InvalidTimeZoneException(string message)
: base(message)
{
}
- public InvalidTimeZoneException(String message, Exception innerException)
+ public InvalidTimeZoneException(string message, Exception innerException)
: base(message, innerException)
{
}
diff --git a/src/System.Private.CoreLib/shared/System/Lazy.cs b/src/System.Private.CoreLib/shared/System/Lazy.cs
index 6410c2e28..02122ca05 100644
--- a/src/System.Private.CoreLib/shared/System/Lazy.cs
+++ b/src/System.Private.CoreLib/shared/System/Lazy.cs
@@ -119,7 +119,7 @@ namespace System
default:
Debug.Fail("Invalid logic; State should always have a valid value");
- return default(LazyThreadSafetyMode);
+ return default;
}
}
@@ -454,7 +454,7 @@ namespace System
{
if (!IsValueCreated)
{
- return default(T);
+ return default;
}
return _value;
}
diff --git a/src/System.Private.CoreLib/src/System/Marvin.cs b/src/System.Private.CoreLib/shared/System/Marvin.cs
index 989d33d7e..d25a244c9 100644
--- a/src/System.Private.CoreLib/src/System/Marvin.cs
+++ b/src/System.Private.CoreLib/shared/System/Marvin.cs
@@ -4,40 +4,42 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
-
+using System.Runtime.InteropServices;
using Internal.Runtime.CompilerServices;
+#if BIT64
+using nuint = System.UInt64;
+#else
+using nuint = System.UInt32;
+#endif
+
namespace System
{
internal static class Marvin
{
/// <summary>
- /// Convenience method to compute a Marvin hash and collapse it into a 32-bit hash.
+ /// Compute a Marvin hash and collapse it into a 32-bit hash.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int ComputeHash32(ref byte data, int count, ulong seed)
- {
- long hash64 = ComputeHash(ref data, count, seed);
- return ((int)(hash64 >> 32)) ^ (int)hash64;
- }
+ public static int ComputeHash32(ReadOnlySpan<byte> data, ulong seed) => ComputeHash32(ref MemoryMarshal.GetReference(data), data.Length, seed);
/// <summary>
- /// Computes a 64-hash using the Marvin algorithm.
+ /// Compute a Marvin hash and collapse it into a 32-bit hash.
/// </summary>
- public static long ComputeHash(ref byte data, int count, ulong seed)
+ public static int ComputeHash32(ref byte data, int count, ulong seed)
{
- uint ucount = (uint)count;
+ nuint ucount = (nuint)count;
uint p0 = (uint)seed;
uint p1 = (uint)(seed >> 32);
- int byteOffset = 0; // declared as signed int so we don't have to cast everywhere (it's passed to Unsafe.Add() and used for nothing else.)
+ nuint byteOffset = 0;
while (ucount >= 8)
{
- p0 += Unsafe.As<byte, uint>(ref Unsafe.Add(ref data, byteOffset));
+ p0 += Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref data, byteOffset));
Block(ref p0, ref p1);
- p0 += Unsafe.As<byte, uint>(ref Unsafe.Add(ref data, byteOffset + 4));
+ p0 += Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref data, byteOffset + 4));
Block(ref p0, ref p1);
byteOffset += 8;
@@ -47,7 +49,7 @@ namespace System
switch (ucount)
{
case 4:
- p0 += Unsafe.As<byte, uint>(ref Unsafe.Add(ref data, byteOffset));
+ p0 += Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref data, byteOffset));
Block(ref p0, ref p1);
goto case 0;
@@ -56,33 +58,33 @@ namespace System
break;
case 5:
- p0 += Unsafe.As<byte, uint>(ref Unsafe.Add(ref data, byteOffset));
+ p0 += Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref data, byteOffset));
byteOffset += 4;
Block(ref p0, ref p1);
goto case 1;
case 1:
- p0 += 0x8000u | Unsafe.Add(ref data, byteOffset);
+ p0 += 0x8000u | Unsafe.AddByteOffset(ref data, byteOffset);
break;
case 6:
- p0 += Unsafe.As<byte, uint>(ref Unsafe.Add(ref data, byteOffset));
+ p0 += Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref data, byteOffset));
byteOffset += 4;
Block(ref p0, ref p1);
goto case 2;
case 2:
- p0 += 0x800000u | Unsafe.As<byte, ushort>(ref Unsafe.Add(ref data, byteOffset));
+ p0 += 0x800000u | Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref data, byteOffset));
break;
case 7:
- p0 += Unsafe.As<byte, uint>(ref Unsafe.Add(ref data, byteOffset));
+ p0 += Unsafe.ReadUnaligned<uint>(ref Unsafe.AddByteOffset(ref data, byteOffset));
byteOffset += 4;
Block(ref p0, ref p1);
goto case 3;
case 3:
- p0 += 0x80000000u | (((uint)(Unsafe.Add(ref data, byteOffset + 2))) << 16)| (uint)(Unsafe.As<byte, ushort>(ref Unsafe.Add(ref data, byteOffset)));
+ p0 += 0x80000000u | (((uint)(Unsafe.AddByteOffset(ref data, byteOffset + 2))) << 16)| (uint)(Unsafe.ReadUnaligned<ushort>(ref Unsafe.AddByteOffset(ref data, byteOffset)));
break;
default:
@@ -93,7 +95,7 @@ namespace System
Block(ref p0, ref p1);
Block(ref p0, ref p1);
- return (((long)p1) << 32) | p0;
+ return (int)(p1 ^ p0);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -125,20 +127,15 @@ namespace System
return (value << shift) | (value >> (32 - shift));
}
- public static ulong DefaultSeed => s_defaultSeed;
-
- private static ulong s_defaultSeed = GenerateSeed();
+ public static ulong DefaultSeed { get; } = GenerateSeed();
- private static ulong GenerateSeed()
+ private static unsafe ulong GenerateSeed()
{
#if MONO
return 839433921;
#else
ulong seed;
- unsafe
- {
- Interop.GetRandomBytes((byte*)&seed, sizeof(ulong));
- }
+ Interop.GetRandomBytes((byte*)&seed, sizeof(ulong));
return seed;
#endif
}
diff --git a/src/System.Private.CoreLib/shared/System/Math.cs b/src/System.Private.CoreLib/shared/System/Math.cs
index a175103f8..ef46869e2 100644
--- a/src/System.Private.CoreLib/shared/System/Math.cs
+++ b/src/System.Private.CoreLib/shared/System/Math.cs
@@ -123,15 +123,25 @@ namespace System
public static long DivRem(long a, long b, out long result)
{
- // TODO https://github.com/dotnet/coreclr/issues/3439:
- // Restore to using % and / when the JIT is able to eliminate one of the idivs.
- // In the meantime, a * and - is measurably faster than an extra /.
-
long div = a / b;
result = a - (div * b);
return div;
}
+ internal static uint DivRem(uint a, uint b, out uint result)
+ {
+ uint div = a / b;
+ result = a - (div * b);
+ return div;
+ }
+
+ internal static ulong DivRem(ulong a, ulong b, out ulong result)
+ {
+ ulong div = a / b;
+ result = a - (div * b);
+ return div;
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static decimal Ceiling(decimal d)
{
diff --git a/src/System.Private.CoreLib/shared/System/MemberAccessException.cs b/src/System.Private.CoreLib/shared/System/MemberAccessException.cs
index dfea52dbe..0cf1e0fbe 100644
--- a/src/System.Private.CoreLib/shared/System/MemberAccessException.cs
+++ b/src/System.Private.CoreLib/shared/System/MemberAccessException.cs
@@ -31,13 +31,13 @@ namespace System
// message, its HRESULT set to COR_E_ACCESS,
// and its ExceptionInfo reference set to null.
//
- public MemberAccessException(String message)
+ public MemberAccessException(string message)
: base(message)
{
HResult = HResults.COR_E_MEMBERACCESS;
}
- public MemberAccessException(String message, Exception inner)
+ public MemberAccessException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_MEMBERACCESS;
diff --git a/src/System.Private.CoreLib/shared/System/Memory.cs b/src/System.Private.CoreLib/shared/System/Memory.cs
index fca015f5e..1a7556720 100644
--- a/src/System.Private.CoreLib/shared/System/Memory.cs
+++ b/src/System.Private.CoreLib/shared/System/Memory.cs
@@ -8,9 +8,8 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute;
using EditorBrowsableState = System.ComponentModel.EditorBrowsableState;
-#if !FEATURE_PORTABLE_SPAN
+
using Internal.Runtime.CompilerServices;
-#endif // FEATURE_PORTABLE_SPAN
namespace System
{
@@ -18,23 +17,26 @@ namespace System
/// Memory represents a contiguous region of arbitrary memory similar to <see cref="Span{T}"/>.
/// Unlike <see cref="Span{T}"/>, it is not a byref-like type.
/// </summary>
- [DebuggerDisplay("{DebuggerDisplay,nq}")]
[DebuggerTypeProxy(typeof(MemoryDebugView<>))]
+ [DebuggerDisplay("{ToString(),raw}")]
public readonly struct Memory<T>
{
// NOTE: With the current implementation, Memory<T> and ReadOnlyMemory<T> must have the same layout,
// as code uses Unsafe.As to cast between them.
// The highest order bit of _index is used to discern whether _object is an array/string or an owned memory
- // if (_index >> 31) == 1, object _object is an OwnedMemory<T>
- // else, object _object is a T[] or a string. It can only be a string if the Memory<T> was created by
+ // if (_index >> 31) == 1, object _object is an MemoryManager<T>
+ // else, object _object is a T[] or a string.
+ // if (_length >> 31) == 1, _object is a pre-pinned array, so Pin() will not allocate a new GCHandle
+ // else, Pin() needs to allocate a new GCHandle to pin the object.
+ // It can only be a string if the Memory<T> was created by
// using unsafe / marshaling code to reinterpret a ReadOnlyMemory<char> wrapped around a string as
// a Memory<T>.
private readonly object _object;
private readonly int _index;
private readonly int _length;
- private const int RemoveOwnedFlagBitMask = 0x7FFFFFFF;
+ private const int RemoveFlagsBitMask = 0x7FFFFFFF;
/// <summary>
/// Creates a new memory over the entirety of the target array.
@@ -110,22 +112,61 @@ namespace System
_length = length;
}
- // Constructor for internal use only.
+ /// <summary>
+ /// Creates a new memory from a memory manager that provides specific method implementations beginning
+ /// at 0 index and ending at 'end' index (exclusive).
+ /// </summary>
+ /// <param name="manager">The memory manager.</param>
+ /// <param name="length">The number of items in the memory.</param>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="length"/> is negative.
+ /// </exception>
+ /// <remarks>For internal infrastructure only</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal Memory(OwnedMemory<T> owner, int index, int length)
+ internal Memory(MemoryManager<T> manager, int length)
{
- // No validation performed; caller must provide any necessary validation.
- _object = owner;
- _index = index | (1 << 31); // Before using _index, check if _index < 0, then 'and' it with RemoveOwnedFlagBitMask
+ Debug.Assert(manager != null);
+
+ if (length < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException();
+
+ _object = manager;
+ _index = (1 << 31); // Mark as MemoryManager type
+ // Before using _index, check if _index < 0, then 'and' it with RemoveFlagsBitMask
+ _length = length;
+ }
+
+ /// <summary>
+ /// Creates a new memory from a memory manager that provides specific method implementations beginning
+ /// at 'start' index and ending at 'end' index (exclusive).
+ /// </summary>
+ /// <param name="manager">The memory manager.</param>
+ /// <param name="start">The index at which to begin the memory.</param>
+ /// <param name="length">The number of items in the memory.</param>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or <paramref name="length"/> is negative.
+ /// </exception>
+ /// <remarks>For internal infrastructure only</remarks>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal Memory(MemoryManager<T> manager, int start, int length)
+ {
+ Debug.Assert(manager != null);
+
+ if (length < 0 || start < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException();
+
+ _object = manager;
+ _index = start | (1 << 31); // Mark as MemoryManager type
+ // Before using _index, check if _index < 0, then 'and' it with RemoveFlagsBitMask
_length = length;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private Memory(object obj, int index, int length)
+ internal Memory(object obj, int start, int length)
{
// No validation performed; caller must provide any necessary validation.
_object = obj;
- _index = index;
+ _index = start;
_length = length;
}
@@ -137,7 +178,7 @@ namespace System
/// <summary>
/// Defines an implicit conversion of a <see cref="ArraySegment{T}"/> to a <see cref="Memory{T}"/>
/// </summary>
- public static implicit operator Memory<T>(ArraySegment<T> arraySegment) => new Memory<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
+ public static implicit operator Memory<T>(ArraySegment<T> segment) => new Memory<T>(segment.Array, segment.Offset, segment.Count);
/// <summary>
/// Defines an implicit conversion of a <see cref="Memory{T}"/> to a <see cref="ReadOnlyMemory{T}"/>
@@ -145,9 +186,6 @@ namespace System
public static implicit operator ReadOnlyMemory<T>(Memory<T> memory) =>
Unsafe.As<Memory<T>, ReadOnlyMemory<T>>(ref memory);
- //Debugger Display = {T[length]}
- private string DebuggerDisplay => string.Format("{{{0}[{1}]}}", typeof(T).Name, _length);
-
/// <summary>
/// Returns an empty <see cref="Memory{T}"/>
/// </summary>
@@ -156,12 +194,25 @@ namespace System
/// <summary>
/// The number of items in the memory.
/// </summary>
- public int Length => _length;
+ public int Length => _length & RemoveFlagsBitMask;
/// <summary>
/// Returns true if Length is 0.
/// </summary>
- public bool IsEmpty => _length == 0;
+ public bool IsEmpty => (_length & RemoveFlagsBitMask) == 0;
+
+ /// <summary>
+ /// For <see cref="Memory{Char}"/>, returns a new instance of string that represents the characters pointed to by the memory.
+ /// Otherwise, returns a <see cref="string"/> with the name of the type and the number of elements.
+ /// </summary>
+ public override string ToString()
+ {
+ if (typeof(T) == typeof(char))
+ {
+ return (_object is string str) ? str.Substring(_index, _length & RemoveFlagsBitMask) : Span.ToString();
+ }
+ return string.Format("System.Memory<{0}>[{1}]", typeof(T).Name, _length & RemoveFlagsBitMask);
+ }
/// <summary>
/// Forms a slice out of the given memory, beginning at 'start'.
@@ -173,12 +224,16 @@ namespace System
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Memory<T> Slice(int start)
{
- if ((uint)start > (uint)_length)
+ // Used to maintain the high-bit which indicates whether the Memory has been pre-pinned or not.
+ int capturedLength = _length;
+ int actualLength = capturedLength & RemoveFlagsBitMask;
+ if ((uint)start > (uint)actualLength)
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
}
- return new Memory<T>(_object, _index + start, _length - start);
+ // It is expected for (capturedLength - start) to be negative if the memory is already pre-pinned.
+ return new Memory<T>(_object, _index + start, capturedLength - start);
}
/// <summary>
@@ -192,12 +247,16 @@ namespace System
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Memory<T> Slice(int start, int length)
{
- if ((uint)start > (uint)_length || (uint)length > (uint)(_length - start))
+ // Used to maintain the high-bit which indicates whether the Memory has been pre-pinned or not.
+ int capturedLength = _length;
+ int actualLength = capturedLength & RemoveFlagsBitMask;
+ if ((uint)start > (uint)actualLength || (uint)length > (uint)(actualLength - start))
{
ThrowHelper.ThrowArgumentOutOfRangeException();
}
- return new Memory<T>(_object, _index + start, length);
+ // Set the high-bit to match the this._length high bit (1 for pre-pinned, 0 for unpinned).
+ return new Memory<T>(_object, _index + start, length | (capturedLength & ~RemoveFlagsBitMask));
}
/// <summary>
@@ -210,24 +269,23 @@ namespace System
{
if (_index < 0)
{
- return ((OwnedMemory<T>)_object).Span.Slice(_index & RemoveOwnedFlagBitMask, _length);
+ Debug.Assert(_length >= 0);
+ Debug.Assert(_object != null);
+ return ((MemoryManager<T>)_object).GetSpan().Slice(_index & RemoveFlagsBitMask, _length);
}
else if (typeof(T) == typeof(char) && _object is string s)
{
+ Debug.Assert(_length >= 0);
// This is dangerous, returning a writable span for a string that should be immutable.
// However, we need to handle the case where a ReadOnlyMemory<char> was created from a string
// and then cast to a Memory<T>. Such a cast can only be done with unsafe or marshaling code,
// in which case that's the dangerous operation performed by the dev, and we're just following
// suit here to make it work as best as possible.
-#if FEATURE_PORTABLE_SPAN
- return new Span<T>(Unsafe.As<Pinnable<T>>(s), MemoryExtensions.StringAdjustment, s.Length).Slice(_index, _length);
-#else
return new Span<T>(ref Unsafe.As<char, T>(ref s.GetRawStringData()), s.Length).Slice(_index, _length);
-#endif // FEATURE_PORTABLE_SPAN
}
else if (_object != null)
{
- return new Span<T>((T[])_object, _index, _length);
+ return new Span<T>((T[])_object, _index, _length & RemoveFlagsBitMask);
}
else
{
@@ -260,53 +318,47 @@ namespace System
public bool TryCopyTo(Memory<T> destination) => Span.TryCopyTo(destination.Span);
/// <summary>
- /// Returns a handle for the array.
- /// <param name="pin">If pin is true, the GC will not move the array and hence its address can be taken</param>
+ /// Creates a handle for the memory.
+ /// The GC will not move the memory until the returned <see cref="MemoryHandle"/>
+ /// is disposed, enabling taking and using the memory's address.
+ /// <exception cref="System.ArgumentException">
+ /// An instance with nonprimitive (non-blittable) members cannot be pinned.
+ /// </exception>
/// </summary>
- public unsafe MemoryHandle Retain(bool pin = false)
+ public unsafe MemoryHandle Pin()
{
- MemoryHandle memoryHandle = default;
- if (pin)
+ if (_index < 0)
{
- if (_index < 0)
- {
- memoryHandle = ((OwnedMemory<T>)_object).Pin((_index & RemoveOwnedFlagBitMask) * Unsafe.SizeOf<T>());
- }
- else if (typeof(T) == typeof(char) && _object is string s)
- {
- // This case can only happen if a ReadOnlyMemory<char> was created around a string
- // and then that was cast to a Memory<char> using unsafe / marshaling code. This needs
- // to work, however, so that code that uses a single Memory<char> field to store either
- // a readable ReadOnlyMemory<char> or a writable Memory<char> can still be pinned and
- // used for interop purposes.
- GCHandle handle = GCHandle.Alloc(s, GCHandleType.Pinned);
-#if FEATURE_PORTABLE_SPAN
- void* pointer = Unsafe.Add<T>((void*)handle.AddrOfPinnedObject(), _index);
-#else
- void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref s.GetRawStringData()), _index);
-#endif // FEATURE_PORTABLE_SPAN
- memoryHandle = new MemoryHandle(null, pointer, handle);
- }
- else if (_object is T[] array)
+ Debug.Assert(_object != null);
+ return ((MemoryManager<T>)_object).Pin((_index & RemoveFlagsBitMask));
+ }
+ else if (typeof(T) == typeof(char) && _object is string s)
+ {
+ // This case can only happen if a ReadOnlyMemory<char> was created around a string
+ // and then that was cast to a Memory<char> using unsafe / marshaling code. This needs
+ // to work, however, so that code that uses a single Memory<char> field to store either
+ // a readable ReadOnlyMemory<char> or a writable Memory<char> can still be pinned and
+ // used for interop purposes.
+ GCHandle handle = GCHandle.Alloc(s, GCHandleType.Pinned);
+ void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref s.GetRawStringData()), _index);
+ return new MemoryHandle(pointer, handle);
+ }
+ else if (_object is T[] array)
+ {
+ // Array is already pre-pinned
+ if (_length < 0)
{
- var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
-#if FEATURE_PORTABLE_SPAN
- void* pointer = Unsafe.Add<T>((void*)handle.AddrOfPinnedObject(), _index);
-#else
void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index);
-#endif // FEATURE_PORTABLE_SPAN
- memoryHandle = new MemoryHandle(null, pointer, handle);
+ return new MemoryHandle(pointer);
}
- }
- else
- {
- if (_index < 0)
+ else
{
- ((OwnedMemory<T>)_object).Retain();
- memoryHandle = new MemoryHandle((OwnedMemory<T>)_object);
+ GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
+ void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index);
+ return new MemoryHandle(pointer, handle);
}
}
- return memoryHandle;
+ return default;
}
/// <summary>
diff --git a/src/System.Private.CoreLib/shared/System/MemoryDebugView.cs b/src/System.Private.CoreLib/shared/System/MemoryDebugView.cs
index b1ed88199..6ab6e5065 100644
--- a/src/System.Private.CoreLib/shared/System/MemoryDebugView.cs
+++ b/src/System.Private.CoreLib/shared/System/MemoryDebugView.cs
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
-using System.Runtime.InteropServices;
namespace System
{
@@ -22,31 +21,6 @@ namespace System
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
- public T[] Items
- {
- // This is a work around since we cannot use _memory.ToArray() due to
- // https://devdiv.visualstudio.com/DevDiv/_workitems?id=286592
- get
- {
- if (MemoryMarshal.TryGetArray(_memory, out ArraySegment<T> segment))
- {
- T[] array = new T[_memory.Length];
- Array.Copy(segment.Array, segment.Offset, array, 0, array.Length);
- return array;
- }
-
- if (typeof(T) == typeof(char) &&
- MemoryMarshal.TryGetString((ReadOnlyMemory<char>)(object)_memory, out string text, out int start, out int length))
- {
- return (T[])(object)text.Substring(start, length).ToCharArray();
- }
-
-#if FEATURE_PORTABLE_SPAN
- return SpanHelpers.PerTypeValues<T>.EmptyArray;
-#else
- return Array.Empty<T>();
-#endif // FEATURE_PORTABLE_SPAN
- }
- }
+ public T[] Items => _memory.ToArray();
}
}
diff --git a/src/System.Private.CoreLib/shared/System/MemoryExtensions.Fast.cs b/src/System.Private.CoreLib/shared/System/MemoryExtensions.Fast.cs
index 56dd203e1..e86ca4fcd 100644
--- a/src/System.Private.CoreLib/shared/System/MemoryExtensions.Fast.cs
+++ b/src/System.Private.CoreLib/shared/System/MemoryExtensions.Fast.cs
@@ -28,81 +28,93 @@ namespace System
}
/// <summary>
- /// Determines whether this <paramref name="span"/> and the specified <paramref name="value"/> span have the same characters
+ /// Determines whether this <paramref name="span"/> and the specified <paramref name="other"/> span have the same characters
/// when compared using the specified <paramref name="comparisonType"/> option.
/// <param name="span">The source span.</param>
- /// <param name="value">The value to compare with the source span.</param>
- /// <param name="comparisonType">One of the enumeration values that determines how the <paramref name="span"/> and <paramref name="value"/> are compared.</param>
+ /// <param name="other">The value to compare with the source span.</param>
+ /// <param name="comparisonType">One of the enumeration values that determines how the <paramref name="span"/> and <paramref name="other"/> are compared.</param>
/// </summary>
- public static bool Equals(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType)
+ public static bool Equals(this ReadOnlySpan<char> span, ReadOnlySpan<char> other, StringComparison comparisonType)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ string.CheckStringComparison(comparisonType);
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return (CultureInfo.CurrentCulture.CompareInfo.Compare(span, value, CompareOptions.None) == 0);
+ return (CultureInfo.CurrentCulture.CompareInfo.CompareOptionNone(span, other) == 0);
case StringComparison.CurrentCultureIgnoreCase:
- return (CultureInfo.CurrentCulture.CompareInfo.Compare(span, value, CompareOptions.IgnoreCase) == 0);
+ return (CultureInfo.CurrentCulture.CompareInfo.CompareOptionIgnoreCase(span, other) == 0);
case StringComparison.InvariantCulture:
- return (CompareInfo.Invariant.Compare(span, value, CompareOptions.None) == 0);
+ return (CompareInfo.Invariant.CompareOptionNone(span, other) == 0);
case StringComparison.InvariantCultureIgnoreCase:
- return (CompareInfo.Invariant.Compare(span, value, CompareOptions.IgnoreCase) == 0);
+ return (CompareInfo.Invariant.CompareOptionIgnoreCase(span, other) == 0);
case StringComparison.Ordinal:
- if (span.Length != value.Length)
- return false;
- if (value.Length == 0) // span.Length == value.Length == 0
- return true;
- return span.SequenceEqual(value); //TODO: Optimize - https://github.com/dotnet/corefx/issues/27487
+ return EqualsOrdinal(span, other);
case StringComparison.OrdinalIgnoreCase:
- if (span.Length != value.Length)
- return false;
- if (value.Length == 0) // span.Length == value.Length == 0
- return true;
- return (CompareInfo.CompareOrdinalIgnoreCase(span, value) == 0);
+ return EqualsOrdinalIgnoreCase(span, other);
}
Debug.Fail("StringComparison outside range");
return false;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static bool EqualsOrdinal(this ReadOnlySpan<char> span, ReadOnlySpan<char> value)
+ {
+ if (span.Length != value.Length)
+ return false;
+ if (value.Length == 0) // span.Length == value.Length == 0
+ return true;
+ return span.SequenceEqual(value);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static bool EqualsOrdinalIgnoreCase(this ReadOnlySpan<char> span, ReadOnlySpan<char> value)
+ {
+ if (span.Length != value.Length)
+ return false;
+ if (value.Length == 0) // span.Length == value.Length == 0
+ return true;
+ return CompareInfo.EqualsOrdinalIgnoreCase(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(value), span.Length);
+ }
+
/// <summary>
- /// Compares the specified <paramref name="span"/> and <paramref name="value"/> using the specified <paramref name="comparisonType"/>,
+ /// Compares the specified <paramref name="span"/> and <paramref name="other"/> using the specified <paramref name="comparisonType"/>,
/// and returns an integer that indicates their relative position in the sort order.
/// <param name="span">The source span.</param>
- /// <param name="value">The value to compare with the source span.</param>
- /// <param name="comparisonType">One of the enumeration values that determines how the <paramref name="span"/> and <paramref name="value"/> are compared.</param>
+ /// <param name="other">The value to compare with the source span.</param>
+ /// <param name="comparisonType">One of the enumeration values that determines how the <paramref name="span"/> and <paramref name="other"/> are compared.</param>
/// </summary>
- public static int CompareTo(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType)
+ public static int CompareTo(this ReadOnlySpan<char> span, ReadOnlySpan<char> other, StringComparison comparisonType)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ string.CheckStringComparison(comparisonType);
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return CultureInfo.CurrentCulture.CompareInfo.Compare(span, value, CompareOptions.None);
+ return CultureInfo.CurrentCulture.CompareInfo.CompareOptionNone(span, other);
case StringComparison.CurrentCultureIgnoreCase:
- return CultureInfo.CurrentCulture.CompareInfo.Compare(span, value, CompareOptions.IgnoreCase);
+ return CultureInfo.CurrentCulture.CompareInfo.CompareOptionIgnoreCase(span, other);
case StringComparison.InvariantCulture:
- return CompareInfo.Invariant.Compare(span, value, CompareOptions.None);
+ return CompareInfo.Invariant.CompareOptionNone(span, other);
case StringComparison.InvariantCultureIgnoreCase:
- return CompareInfo.Invariant.Compare(span, value, CompareOptions.IgnoreCase);
+ return CompareInfo.Invariant.CompareOptionIgnoreCase(span, other);
case StringComparison.Ordinal:
- if (span.Length == 0 || value.Length == 0)
- return span.Length - value.Length;
- return string.CompareOrdinal(span, value);
+ if (span.Length == 0 || other.Length == 0)
+ return span.Length - other.Length;
+ return string.CompareOrdinal(span, other);
case StringComparison.OrdinalIgnoreCase:
- return CompareInfo.CompareOrdinalIgnoreCase(span, value);
+ return CompareInfo.CompareOrdinalIgnoreCase(span, other);
}
Debug.Fail("StringComparison outside range");
@@ -117,7 +129,7 @@ namespace System
/// </summary>
public static int IndexOf(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ string.CheckStringComparison(comparisonType);
if (value.Length == 0)
{
@@ -129,29 +141,66 @@ namespace System
return -1;
}
+ if (GlobalizationMode.Invariant)
+ {
+ return CompareInfo.InvariantIndexOf(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType) != CompareOptions.None);
+ }
+
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return SpanHelpers.IndexOfCultureHelper(span, value, CultureInfo.CurrentCulture.CompareInfo);
-
case StringComparison.CurrentCultureIgnoreCase:
- return SpanHelpers.IndexOfCultureIgnoreCaseHelper(span, value, CultureInfo.CurrentCulture.CompareInfo);
+ return CultureInfo.CurrentCulture.CompareInfo.IndexOf(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.InvariantCulture:
- return SpanHelpers.IndexOfCultureHelper(span, value, CompareInfo.Invariant);
-
case StringComparison.InvariantCultureIgnoreCase:
- return SpanHelpers.IndexOfCultureIgnoreCaseHelper(span, value, CompareInfo.Invariant);
+ return CompareInfo.Invariant.IndexOf(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType));
- case StringComparison.Ordinal:
- return SpanHelpers.IndexOfOrdinalHelper(span, value, ignoreCase: false);
+ default:
+ Debug.Assert(comparisonType == StringComparison.Ordinal || comparisonType == StringComparison.OrdinalIgnoreCase);
+ return CompareInfo.Invariant.IndexOfOrdinal(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType) != CompareOptions.None);
+ }
+ }
- case StringComparison.OrdinalIgnoreCase:
- return SpanHelpers.IndexOfOrdinalHelper(span, value, ignoreCase: true);
+ /// <summary>
+ /// Reports the zero-based index of the last occurrence of the specified <paramref name="value"/> in the current <paramref name="span"/>.
+ /// <param name="span">The source span.</param>
+ /// <param name="value">The value to seek within the source span.</param>
+ /// <param name="comparisonType">One of the enumeration values that determines how the <paramref name="span"/> and <paramref name="value"/> are compared.</param>
+ /// </summary>
+ public static int LastIndexOf(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType)
+ {
+ string.CheckStringComparison(comparisonType);
+
+ if (value.Length == 0)
+ {
+ return span.Length > 0 ? span.Length - 1 : 0;
}
- Debug.Fail("StringComparison outside range");
- return -1;
+ if (span.Length == 0)
+ {
+ return -1;
+ }
+
+ if (GlobalizationMode.Invariant)
+ {
+ return CompareInfo.InvariantIndexOf(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType) != CompareOptions.None, fromBeginning: false);
+ }
+
+ switch (comparisonType)
+ {
+ case StringComparison.CurrentCulture:
+ case StringComparison.CurrentCultureIgnoreCase:
+ return CultureInfo.CurrentCulture.CompareInfo.LastIndexOf(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType));
+
+ case StringComparison.InvariantCulture:
+ case StringComparison.InvariantCultureIgnoreCase:
+ return CompareInfo.Invariant.LastIndexOf(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType));
+
+ default:
+ Debug.Assert(comparisonType == StringComparison.Ordinal || comparisonType == StringComparison.OrdinalIgnoreCase);
+ return CompareInfo.Invariant.LastIndexOfOrdinal(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType) != CompareOptions.None);
+ }
}
/// <summary>
@@ -163,6 +212,7 @@ namespace System
/// <param name="culture">An object that supplies culture-specific casing rules.</param>
/// <remarks>If the source and destinations overlap, this method behaves as if the original values are in
/// a temporary location before the destination is overwritten.</remarks>
+ /// <returns>The number of characters written into the destination span. If the destination is too small, returns -1.</returns>
/// <exception cref="System.ArgumentNullException">
/// Thrown when <paramref name="culture"/> is null.
/// </exception>
@@ -176,7 +226,7 @@ namespace System
return -1;
if (GlobalizationMode.Invariant)
- culture.TextInfo.ToLowerAsciiInvariant(source, destination);
+ TextInfo.ToLowerAsciiInvariant(source, destination);
else
culture.TextInfo.ChangeCase(source, destination, toUpper: false);
return source.Length;
@@ -190,6 +240,7 @@ namespace System
/// <param name="destination">The destination span which contains the transformed characters.</param>
/// <remarks>If the source and destinations overlap, this method behaves as if the original values are in
/// a temporary location before the destination is overwritten.</remarks>
+ /// <returns>The number of characters written into the destination span. If the destination is too small, returns -1.</returns>
public static int ToLowerInvariant(this ReadOnlySpan<char> source, Span<char> destination)
{
// Assuming that changing case does not affect length
@@ -197,7 +248,7 @@ namespace System
return -1;
if (GlobalizationMode.Invariant)
- CultureInfo.InvariantCulture.TextInfo.ToLowerAsciiInvariant(source, destination);
+ TextInfo.ToLowerAsciiInvariant(source, destination);
else
CultureInfo.InvariantCulture.TextInfo.ChangeCase(source, destination, toUpper: false);
return source.Length;
@@ -212,6 +263,7 @@ namespace System
/// <param name="culture">An object that supplies culture-specific casing rules.</param>
/// <remarks>If the source and destinations overlap, this method behaves as if the original values are in
/// a temporary location before the destination is overwritten.</remarks>
+ /// <returns>The number of characters written into the destination span. If the destination is too small, returns -1.</returns>
/// <exception cref="System.ArgumentNullException">
/// Thrown when <paramref name="culture"/> is null.
/// </exception>
@@ -225,7 +277,7 @@ namespace System
return -1;
if (GlobalizationMode.Invariant)
- culture.TextInfo.ToUpperAsciiInvariant(source, destination);
+ TextInfo.ToUpperAsciiInvariant(source, destination);
else
culture.TextInfo.ChangeCase(source, destination, toUpper: true);
return source.Length;
@@ -239,6 +291,7 @@ namespace System
/// <param name="destination">The destination span which contains the transformed characters.</param>
/// <remarks>If the source and destinations overlap, this method behaves as if the original values are in
/// a temporary location before the destination is overwritten.</remarks>
+ /// <returns>The number of characters written into the destination span. If the destination is too small, returns -1.</returns>
public static int ToUpperInvariant(this ReadOnlySpan<char> source, Span<char> destination)
{
// Assuming that changing case does not affect length
@@ -246,7 +299,7 @@ namespace System
return -1;
if (GlobalizationMode.Invariant)
- CultureInfo.InvariantCulture.TextInfo.ToUpperAsciiInvariant(source, destination);
+ TextInfo.ToUpperAsciiInvariant(source, destination);
else
CultureInfo.InvariantCulture.TextInfo.ChangeCase(source, destination, toUpper: true);
return source.Length;
@@ -260,35 +313,29 @@ namespace System
/// <param name="comparisonType">One of the enumeration values that determines how the <paramref name="span"/> and <paramref name="value"/> are compared.</param>
public static bool EndsWith(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType)
{
+ string.CheckStringComparison(comparisonType);
+
if (value.Length == 0)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
return true;
}
- switch (comparisonType)
+ if (comparisonType >= StringComparison.Ordinal || GlobalizationMode.Invariant)
{
- case StringComparison.CurrentCulture:
- return SpanHelpers.EndsWithCultureHelper(span, value, CultureInfo.CurrentCulture.CompareInfo);
-
- case StringComparison.CurrentCultureIgnoreCase:
- return SpanHelpers.EndsWithCultureIgnoreCaseHelper(span, value, CultureInfo.CurrentCulture.CompareInfo);
-
- case StringComparison.InvariantCulture:
- return SpanHelpers.EndsWithCultureHelper(span, value, CompareInfo.Invariant);
-
- case StringComparison.InvariantCultureIgnoreCase:
- return SpanHelpers.EndsWithCultureIgnoreCaseHelper(span, value, CompareInfo.Invariant);
-
- case StringComparison.Ordinal:
- return span.EndsWith(value); //TODO: Optimize - https://github.com/dotnet/corefx/issues/27487
+ if (string.GetCaseCompareOfComparisonCulture(comparisonType) == CompareOptions.None)
+ return span.EndsWith(value);
- case StringComparison.OrdinalIgnoreCase:
- return SpanHelpers.EndsWithOrdinalIgnoreCaseHelper(span, value);
+ return (span.Length >= value.Length) ? (CompareInfo.CompareOrdinalIgnoreCase(span.Slice(span.Length - value.Length), value) == 0) : false;
+ }
- default:
- throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
+ if (span.Length == 0)
+ {
+ return false;
}
+
+ return (comparisonType >= StringComparison.InvariantCulture) ?
+ CompareInfo.Invariant.IsSuffix(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType)) :
+ CultureInfo.CurrentCulture.CompareInfo.IsSuffix(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType));
}
/// <summary>
@@ -299,86 +346,35 @@ namespace System
/// <param name="comparisonType">One of the enumeration values that determines how the <paramref name="span"/> and <paramref name="value"/> are compared.</param>
public static bool StartsWith(this ReadOnlySpan<char> span, ReadOnlySpan<char> value, StringComparison comparisonType)
{
+ string.CheckStringComparison(comparisonType);
+
if (value.Length == 0)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
return true;
}
- switch (comparisonType)
+ if (comparisonType >= StringComparison.Ordinal || GlobalizationMode.Invariant)
{
- case StringComparison.CurrentCulture:
- return SpanHelpers.StartsWithCultureHelper(span, value, CultureInfo.CurrentCulture.CompareInfo);
-
- case StringComparison.CurrentCultureIgnoreCase:
- return SpanHelpers.StartsWithCultureIgnoreCaseHelper(span, value, CultureInfo.CurrentCulture.CompareInfo);
-
- case StringComparison.InvariantCulture:
- return SpanHelpers.StartsWithCultureHelper(span, value, CompareInfo.Invariant);
-
- case StringComparison.InvariantCultureIgnoreCase:
- return SpanHelpers.StartsWithCultureIgnoreCaseHelper(span, value, CompareInfo.Invariant);
-
- case StringComparison.Ordinal:
- return span.StartsWith(value); //TODO: Optimize - https://github.com/dotnet/corefx/issues/27487
+ if (string.GetCaseCompareOfComparisonCulture(comparisonType) == CompareOptions.None)
+ return span.StartsWith(value);
- case StringComparison.OrdinalIgnoreCase:
- return SpanHelpers.StartsWithOrdinalIgnoreCaseHelper(span, value);
-
- default:
- throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
+ return (span.Length >= value.Length) ? (CompareInfo.CompareOrdinalIgnoreCase(span.Slice(0, value.Length), value) == 0) : false;
}
- }
-
- /// <summary>
- /// Casts a Span of one primitive type <typeparamref name="T"/> to Span of bytes.
- /// That type may not contain pointers or references. This is checked at runtime in order to preserve type safety.
- /// </summary>
- /// <param name="source">The source slice, of type <typeparamref name="T"/>.</param>
- /// <exception cref="System.ArgumentException">
- /// Thrown when <typeparamref name="T"/> contains pointers.
- /// </exception>
- /// <exception cref="System.OverflowException">
- /// Thrown if the Length property of the new Span would exceed Int32.MaxValue.
- /// </exception>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Span<byte> AsBytes<T>(this Span<T> source)
- where T : struct
- {
- if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
- ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
-
- return new Span<byte>(
- ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(source)),
- checked(source.Length * Unsafe.SizeOf<T>()));
- }
- /// <summary>
- /// Casts a ReadOnlySpan of one primitive type <typeparamref name="T"/> to ReadOnlySpan of bytes.
- /// That type may not contain pointers or references. This is checked at runtime in order to preserve type safety.
- /// </summary>
- /// <param name="source">The source slice, of type <typeparamref name="T"/>.</param>
- /// <exception cref="System.ArgumentException">
- /// Thrown when <typeparamref name="T"/> contains pointers.
- /// </exception>
- /// <exception cref="System.OverflowException">
- /// Thrown if the Length property of the new Span would exceed Int32.MaxValue.
- /// </exception>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ReadOnlySpan<byte> AsBytes<T>(this ReadOnlySpan<T> source)
- where T : struct
- {
- if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
- ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+ if (span.Length == 0)
+ {
+ return false;
+ }
- return new ReadOnlySpan<byte>(
- ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(source)),
- checked(source.Length * Unsafe.SizeOf<T>()));
+ return (comparisonType >= StringComparison.InvariantCulture) ?
+ CompareInfo.Invariant.IsPrefix(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType)) :
+ CultureInfo.CurrentCulture.CompareInfo.IsPrefix(span, value, string.GetCaseCompareOfComparisonCulture(comparisonType));
}
/// <summary>
/// Creates a new span over the portion of the target array.
/// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> AsSpan<T>(this T[] array, int start)
{
if (array == null)
@@ -400,6 +396,7 @@ namespace System
/// </summary>
/// <param name="text">The target string.</param>
/// <remarks>Returns default when <paramref name="text"/> is null.</remarks>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<char> AsSpan(this string text)
{
if (text == null)
@@ -417,6 +414,7 @@ namespace System
/// <exception cref="System.ArgumentOutOfRangeException">
/// Thrown when the specified <paramref name="start"/> index is not in range (&lt;0 or &gt;text.Length).
/// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<char> AsSpan(this string text, int start)
{
if (text == null)
@@ -442,6 +440,7 @@ namespace System
/// <exception cref="System.ArgumentOutOfRangeException">
/// Thrown when the specified <paramref name="start"/> index or <paramref name="length"/> is not in range.
/// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<char> AsSpan(this string text, int start, int length)
{
if (text == null)
diff --git a/src/System.Private.CoreLib/shared/System/MemoryExtensions.cs b/src/System.Private.CoreLib/shared/System/MemoryExtensions.cs
index effdecf92..f0937c448 100644
--- a/src/System.Private.CoreLib/shared/System/MemoryExtensions.cs
+++ b/src/System.Private.CoreLib/shared/System/MemoryExtensions.cs
@@ -6,9 +6,13 @@ using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-#if !netstandard
using Internal.Runtime.CompilerServices;
-#endif
+
+#if BIT64
+using nuint = System.UInt64;
+#else
+using nuint = System.UInt32;
+#endif // BIT64
namespace System
{
@@ -58,7 +62,6 @@ namespace System
/// </summary>
/// <param name="span">The source span from which the character is removed.</param>
/// <param name="trimChar">The specified character to look for and remove.</param>
- //[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<char> Trim(this ReadOnlySpan<char> span, char trimChar)
{
return span.TrimStart(trimChar).TrimEnd(trimChar);
@@ -69,7 +72,6 @@ namespace System
/// </summary>
/// <param name="span">The source span from which the character is removed.</param>
/// <param name="trimChar">The specified character to look for and remove.</param>
- //[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<char> TrimStart(this ReadOnlySpan<char> span, char trimChar)
{
int start = 0;
@@ -103,6 +105,7 @@ namespace System
/// </summary>
/// <param name="span">The source span from which the characters are removed.</param>
/// <param name="trimChars">The span which contains the set of characters to remove.</param>
+ /// <remarks>If <paramref name="trimChars"/> is empty, white-space characters are removed instead.</remarks>
public static ReadOnlySpan<char> Trim(this ReadOnlySpan<char> span, ReadOnlySpan<char> trimChars)
{
return span.TrimStart(trimChars).TrimEnd(trimChars);
@@ -114,8 +117,14 @@ namespace System
/// </summary>
/// <param name="span">The source span from which the characters are removed.</param>
/// <param name="trimChars">The span which contains the set of characters to remove.</param>
+ /// <remarks>If <paramref name="trimChars"/> is empty, white-space characters are removed instead.</remarks>
public static ReadOnlySpan<char> TrimStart(this ReadOnlySpan<char> span, ReadOnlySpan<char> trimChars)
{
+ if (trimChars.IsEmpty)
+ {
+ return span.TrimStart();
+ }
+
int start = 0;
for (; start < span.Length; start++)
{
@@ -137,8 +146,14 @@ namespace System
/// </summary>
/// <param name="span">The source span from which the characters are removed.</param>
/// <param name="trimChars">The span which contains the set of characters to remove.</param>
+ /// <remarks>If <paramref name="trimChars"/> is empty, white-space characters are removed instead.</remarks>
public static ReadOnlySpan<char> TrimEnd(this ReadOnlySpan<char> span, ReadOnlySpan<char> trimChars)
{
+ if (trimChars.IsEmpty)
+ {
+ return span.TrimEnd();
+ }
+
int end = span.Length - 1;
for (; end >= 0; end--)
{
@@ -168,6 +183,56 @@ namespace System
}
/// <summary>
+ /// Searches for the specified value and returns true if found. If not found, returns false. Values are compared using IEquatable{T}.Equals(T).
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="span">The span to search.</param>
+ /// <param name="value">The value to search for.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool Contains<T>(this Span<T> span, T value)
+ where T : IEquatable<T>
+ {
+ if (typeof(T) == typeof(byte))
+ return SpanHelpers.Contains(
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
+ Unsafe.As<T, byte>(ref value),
+ span.Length);
+
+ if (typeof(T) == typeof(char))
+ return SpanHelpers.Contains(
+ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
+ Unsafe.As<T, char>(ref value),
+ span.Length);
+
+ return SpanHelpers.Contains(ref MemoryMarshal.GetReference(span), value, span.Length);
+ }
+
+ /// <summary>
+ /// Searches for the specified value and returns true if found. If not found, returns false. Values are compared using IEquatable{T}.Equals(T).
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="span">The span to search.</param>
+ /// <param name="value">The value to search for.</param>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool Contains<T>(this ReadOnlySpan<T> span, T value)
+ where T : IEquatable<T>
+ {
+ if (typeof(T) == typeof(byte))
+ return SpanHelpers.Contains(
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
+ Unsafe.As<T, byte>(ref value),
+ span.Length);
+
+ if (typeof(T) == typeof(char))
+ return SpanHelpers.Contains(
+ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
+ Unsafe.As<T, char>(ref value),
+ span.Length);
+
+ return SpanHelpers.Contains(ref MemoryMarshal.GetReference(span), value, span.Length);
+ }
+
+ /// <summary>
/// Searches for the specified value and returns the index of its first occurrence. If not found, returns -1. Values are compared using IEquatable{T}.Equals(T).
/// </summary>
/// <param name="span">The span to search.</param>
@@ -181,7 +246,14 @@ namespace System
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value),
span.Length);
- return SpanHelpers.IndexOf<T>(ref MemoryMarshal.GetReference(span), value, span.Length);
+
+ if (typeof(T) == typeof(char))
+ return SpanHelpers.IndexOf(
+ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
+ Unsafe.As<T, char>(ref value),
+ span.Length);
+
+ return SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), value, span.Length);
}
/// <summary>
@@ -199,7 +271,8 @@ namespace System
span.Length,
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
value.Length);
- return SpanHelpers.IndexOf<T>(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length);
+
+ return SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length);
}
/// <summary>
@@ -216,6 +289,13 @@ namespace System
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value),
span.Length);
+
+ if (typeof(T) == typeof(char))
+ return SpanHelpers.LastIndexOf(
+ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
+ Unsafe.As<T, char>(ref value),
+ span.Length);
+
return SpanHelpers.LastIndexOf<T>(ref MemoryMarshal.GetReference(span), value, span.Length);
}
@@ -234,6 +314,7 @@ namespace System
span.Length,
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
value.Length);
+
return SpanHelpers.LastIndexOf<T>(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length);
}
@@ -241,50 +322,42 @@ namespace System
/// Determines whether two sequences are equal by comparing the elements using IEquatable{T}.Equals(T).
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool SequenceEqual<T>(this Span<T> first, ReadOnlySpan<T> second)
+ public static bool SequenceEqual<T>(this Span<T> span, ReadOnlySpan<T> other)
where T : IEquatable<T>
{
- int length = first.Length;
- if (typeof(T) == typeof(byte))
- return length == second.Length &&
+ int length = span.Length;
+
+ if (default(T) != null && IsTypeComparableAsBytes<T>(out nuint size))
+ return length == other.Length &&
SpanHelpers.SequenceEqual(
- ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(first)),
- ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(second)),
- length);
- return length == second.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(first), ref MemoryMarshal.GetReference(second), length);
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)),
+ ((nuint)length) * size); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking.
+
+ return length == other.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other), length);
}
/// <summary>
/// Determines the relative order of the sequences being compared by comparing the elements using IComparable{T}.CompareTo(T).
/// </summary>
- public static int SequenceCompareTo<T>(this Span<T> first, ReadOnlySpan<T> second)
+ public static int SequenceCompareTo<T>(this Span<T> span, ReadOnlySpan<T> other)
where T : IComparable<T>
{
if (typeof(T) == typeof(byte))
return SpanHelpers.SequenceCompareTo(
- ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(first)),
- first.Length,
- ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(second)),
- second.Length);
- return SpanHelpers.SequenceCompareTo(ref MemoryMarshal.GetReference(first), first.Length, ref MemoryMarshal.GetReference(second), second.Length);
- }
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
+ span.Length,
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)),
+ other.Length);
- /// <summary>
- /// Reverses the sequence of the elements in the entire span.
- /// </summary>
- public static void Reverse<T>(this Span<T> span)
- {
- ref T p = ref MemoryMarshal.GetReference(span);
- int i = 0;
- int j = span.Length - 1;
- while (i < j)
- {
- T temp = Unsafe.Add(ref p, i);
- Unsafe.Add(ref p, i) = Unsafe.Add(ref p, j);
- Unsafe.Add(ref p, j) = temp;
- i++;
- j--;
- }
+ if (typeof(T) == typeof(char))
+ return SpanHelpers.SequenceCompareTo(
+ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
+ span.Length,
+ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(other)),
+ other.Length);
+
+ return SpanHelpers.SequenceCompareTo(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(other), other.Length);
}
/// <summary>
@@ -301,7 +374,14 @@ namespace System
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value),
span.Length);
- return SpanHelpers.IndexOf<T>(ref MemoryMarshal.GetReference(span), value, span.Length);
+
+ if (typeof(T) == typeof(char))
+ return SpanHelpers.IndexOf(
+ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
+ Unsafe.As<T, char>(ref value),
+ span.Length);
+
+ return SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), value, span.Length);
}
/// <summary>
@@ -319,7 +399,8 @@ namespace System
span.Length,
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
value.Length);
- return SpanHelpers.IndexOf<T>(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length);
+
+ return SpanHelpers.IndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length);
}
/// <summary>
@@ -336,6 +417,13 @@ namespace System
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
Unsafe.As<T, byte>(ref value),
span.Length);
+
+ if (typeof(T) == typeof(char))
+ return SpanHelpers.LastIndexOf(
+ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
+ Unsafe.As<T, char>(ref value),
+ span.Length);
+
return SpanHelpers.LastIndexOf<T>(ref MemoryMarshal.GetReference(span), value, span.Length);
}
@@ -354,6 +442,7 @@ namespace System
span.Length,
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
value.Length);
+
return SpanHelpers.LastIndexOf<T>(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length);
}
@@ -495,6 +584,7 @@ namespace System
Unsafe.As<T, byte>(ref value0),
Unsafe.As<T, byte>(ref value1),
span.Length);
+
return SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length);
}
@@ -516,6 +606,7 @@ namespace System
Unsafe.As<T, byte>(ref value1),
Unsafe.As<T, byte>(ref value2),
span.Length);
+
return SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length);
}
@@ -534,6 +625,7 @@ namespace System
span.Length,
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)),
values.Length);
+
return SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(values), values.Length);
}
@@ -553,6 +645,7 @@ namespace System
Unsafe.As<T, byte>(ref value0),
Unsafe.As<T, byte>(ref value1),
span.Length);
+
return SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, span.Length);
}
@@ -574,6 +667,7 @@ namespace System
Unsafe.As<T, byte>(ref value1),
Unsafe.As<T, byte>(ref value2),
span.Length);
+
return SpanHelpers.LastIndexOfAny(ref MemoryMarshal.GetReference(span), value0, value1, value2, span.Length);
}
@@ -592,6 +686,7 @@ namespace System
span.Length,
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)),
values.Length);
+
return SpanHelpers.LastIndexOfAny<T>(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(values), values.Length);
}
@@ -599,33 +694,42 @@ namespace System
/// Determines whether two sequences are equal by comparing the elements using IEquatable{T}.Equals(T).
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool SequenceEqual<T>(this ReadOnlySpan<T> first, ReadOnlySpan<T> second)
+ public static bool SequenceEqual<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> other)
where T : IEquatable<T>
{
- int length = first.Length;
- if (typeof(T) == typeof(byte))
- return length == second.Length &&
+ int length = span.Length;
+ if (default(T) != null && IsTypeComparableAsBytes<T>(out nuint size))
+ return length == other.Length &&
SpanHelpers.SequenceEqual(
- ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(first)),
- ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(second)),
- length);
- return length == second.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(first), ref MemoryMarshal.GetReference(second), length);
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)),
+ ((nuint)length) * size); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking.
+
+ return length == other.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(other), length);
}
/// <summary>
/// Determines the relative order of the sequences being compared by comparing the elements using IComparable{T}.CompareTo(T).
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static int SequenceCompareTo<T>(this ReadOnlySpan<T> first, ReadOnlySpan<T> second)
+ public static int SequenceCompareTo<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> other)
where T : IComparable<T>
{
if (typeof(T) == typeof(byte))
return SpanHelpers.SequenceCompareTo(
- ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(first)),
- first.Length,
- ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(second)),
- second.Length);
- return SpanHelpers.SequenceCompareTo(ref MemoryMarshal.GetReference(first), first.Length, ref MemoryMarshal.GetReference(second), second.Length);
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
+ span.Length,
+ ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(other)),
+ other.Length);
+
+ if (typeof(T) == typeof(char))
+ return SpanHelpers.SequenceCompareTo(
+ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(span)),
+ span.Length,
+ ref Unsafe.As<T, char>(ref MemoryMarshal.GetReference(other)),
+ other.Length);
+
+ return SpanHelpers.SequenceCompareTo(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(other), other.Length);
}
/// <summary>
@@ -636,12 +740,13 @@ namespace System
where T : IEquatable<T>
{
int valueLength = value.Length;
- if (typeof(T) == typeof(byte))
+ if (default(T) != null && IsTypeComparableAsBytes<T>(out nuint size))
return valueLength <= span.Length &&
SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
- valueLength);
+ ((nuint)valueLength) * size); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking.
+
return valueLength <= span.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(value), valueLength);
}
@@ -653,12 +758,13 @@ namespace System
where T : IEquatable<T>
{
int valueLength = value.Length;
- if (typeof(T) == typeof(byte))
+ if (default(T) != null && IsTypeComparableAsBytes<T>(out nuint size))
return valueLength <= span.Length &&
SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(span)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
- valueLength);
+ ((nuint)valueLength) * size); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking.
+
return valueLength <= span.Length && SpanHelpers.SequenceEqual(ref MemoryMarshal.GetReference(span), ref MemoryMarshal.GetReference(value), valueLength);
}
@@ -671,12 +777,13 @@ namespace System
{
int spanLength = span.Length;
int valueLength = value.Length;
- if (typeof(T) == typeof(byte))
+ if (default(T) != null && IsTypeComparableAsBytes<T>(out nuint size))
return valueLength <= spanLength &&
SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), spanLength - valueLength)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
- valueLength);
+ ((nuint)valueLength) * size); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking.
+
return valueLength <= spanLength &&
SpanHelpers.SequenceEqual(
ref Unsafe.Add(ref MemoryMarshal.GetReference(span), spanLength - valueLength),
@@ -693,12 +800,13 @@ namespace System
{
int spanLength = span.Length;
int valueLength = value.Length;
- if (typeof(T) == typeof(byte))
+ if (default(T) != null && IsTypeComparableAsBytes<T>(out nuint size))
return valueLength <= spanLength &&
SpanHelpers.SequenceEqual(
ref Unsafe.As<T, byte>(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), spanLength - valueLength)),
ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(value)),
- valueLength);
+ ((nuint)valueLength) * size); // If this multiplication overflows, the Span we got overflows the entire address range. There's no happy outcome for this api in such a case so we choose not to take the overhead of checking.
+
return valueLength <= spanLength &&
SpanHelpers.SequenceEqual(
ref Unsafe.Add(ref MemoryMarshal.GetReference(span), spanLength - valueLength),
@@ -707,7 +815,29 @@ namespace System
}
/// <summary>
- /// Creates a new span over the portion of the target array.
+ /// Reverses the sequence of the elements in the entire span.
+ /// </summary>
+ public static void Reverse<T>(this Span<T> span)
+ {
+ if (span.Length <= 1)
+ {
+ return;
+ }
+
+ ref T first = ref MemoryMarshal.GetReference(span);
+ ref T last = ref Unsafe.Add(ref Unsafe.Add(ref first, span.Length), -1);
+ do
+ {
+ T temp = first;
+ first = last;
+ last = temp;
+ first = ref Unsafe.Add(ref first, 1);
+ last = ref Unsafe.Add(ref last, -1);
+ } while (Unsafe.IsAddressLessThan(ref first, ref last));
+ }
+
+ /// <summary>
+ /// Creates a new span over the target array.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> AsSpan<T>(this T[] array)
@@ -716,62 +846,168 @@ namespace System
}
/// <summary>
- /// Creates a new span over the portion of the target array segment.
+ /// Creates a new Span over the portion of the target array beginning
+ /// at 'start' index and ending at 'end' index (exclusive).
/// </summary>
+ /// <param name="array">The target array.</param>
+ /// <param name="start">The index at which to begin the Span.</param>
+ /// <param name="length">The number of items in the Span.</param>
+ /// <remarks>Returns default when <paramref name="array"/> is null.</remarks>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=Length).
+ /// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Span<T> AsSpan<T>(this ArraySegment<T> arraySegment)
+ public static Span<T> AsSpan<T>(this T[] array, int start, int length)
{
- return new Span<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
+ return new Span<T>(array, start, length);
}
/// <summary>
- /// Creates a new readonly span over the entire target array.
+ /// Creates a new span over the portion of the target array segment.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ReadOnlySpan<T> AsReadOnlySpan<T>(this T[] array)
+ public static Span<T> AsSpan<T>(this ArraySegment<T> segment)
{
- return new ReadOnlySpan<T>(array);
+ return new Span<T>(segment.Array, segment.Offset, segment.Count);
}
/// <summary>
- /// Creates a new readonly span over the entire target span.
+ /// Creates a new Span over the portion of the target array beginning
+ /// at 'start' index and ending at 'end' index (exclusive).
/// </summary>
- public static ReadOnlySpan<T> AsReadOnlySpan<T>(this Span<T> span) => span;
+ /// <param name="segment">The target array.</param>
+ /// <param name="start">The index at which to begin the Span.</param>
+ /// <remarks>Returns default when <paramref name="segment"/> is null.</remarks>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="segment"/> is covariant and array's type is not exactly T[].</exception>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=segment.Count).
+ /// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Span<T> AsSpan<T>(this ArraySegment<T> segment, int start)
+ {
+ if (((uint)start) > segment.Count)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
+
+ return new Span<T>(segment.Array, segment.Offset + start, segment.Count - start);
+ }
/// <summary>
- /// Creates a new readonly span over the target array segment.
+ /// Creates a new Span over the portion of the target array beginning
+ /// at 'start' index and ending at 'end' index (exclusive).
/// </summary>
+ /// <param name="segment">The target array.</param>
+ /// <param name="start">The index at which to begin the Span.</param>
+ /// <param name="length">The number of items in the Span.</param>
+ /// <remarks>Returns default when <paramref name="segment"/> is null.</remarks>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="segment"/> is covariant and array's type is not exactly T[].</exception>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=segment.Count).
+ /// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ReadOnlySpan<T> AsReadOnlySpan<T>(this ArraySegment<T> arraySegment)
+ public static Span<T> AsSpan<T>(this ArraySegment<T> segment, int start, int length)
{
- return new ReadOnlySpan<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
+ if (((uint)start) > segment.Count)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
+ if (((uint)length) > segment.Count - start)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
+
+ return new Span<T>(segment.Array, segment.Offset + start, length);
}
/// <summary>
- /// Creates a new readonly memory over the entire target memory.
+ /// Creates a new memory over the target array.
/// </summary>
- public static ReadOnlyMemory<T> AsReadOnlyMemory<T>(this Memory<T> memory) => memory;
+ public static Memory<T> AsMemory<T>(this T[] array) => new Memory<T>(array);
/// <summary>
- /// Creates a new memory over the portion of the target array.
+ /// Creates a new memory over the portion of the target array beginning
+ /// at 'start' index and ending at 'end' index (exclusive).
/// </summary>
+ /// <param name="array">The target array.</param>
+ /// <param name="start">The index at which to begin the memory.</param>
+ /// <remarks>Returns default when <paramref name="array"/> is null.</remarks>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=array.Length).
+ /// </exception>
public static Memory<T> AsMemory<T>(this T[] array, int start) => new Memory<T>(array, start);
/// <summary>
+ /// Creates a new memory over the portion of the target array beginning
+ /// at 'start' index and ending at 'end' index (exclusive).
+ /// </summary>
+ /// <param name="array">The target array.</param>
+ /// <param name="start">The index at which to begin the memory.</param>
+ /// <param name="length">The number of items in the memory.</param>
+ /// <remarks>Returns default when <paramref name="array"/> is null.</remarks>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=Length).
+ /// </exception>
+ public static Memory<T> AsMemory<T>(this T[] array, int start, int length) => new Memory<T>(array, start, length);
+
+ /// <summary>
+ /// Creates a new memory over the portion of the target array.
+ /// </summary>
+ public static Memory<T> AsMemory<T>(this ArraySegment<T> segment) => new Memory<T>(segment.Array, segment.Offset, segment.Count);
+
+ /// <summary>
+ /// Creates a new memory over the portion of the target array beginning
+ /// at 'start' index and ending at 'end' index (exclusive).
+ /// </summary>
+ /// <param name="segment">The target array.</param>
+ /// <param name="start">The index at which to begin the memory.</param>
+ /// <remarks>Returns default when <paramref name="segment"/> is null.</remarks>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="segment"/> is covariant and array's type is not exactly T[].</exception>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=segment.Count).
+ /// </exception>
+ public static Memory<T> AsMemory<T>(this ArraySegment<T> segment, int start)
+ {
+ if (((uint)start) > segment.Count)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
+
+ return new Memory<T>(segment.Array, segment.Offset + start, segment.Count - start);
+ }
+
+ /// <summary>
+ /// Creates a new memory over the portion of the target array beginning
+ /// at 'start' index and ending at 'end' index (exclusive).
+ /// </summary>
+ /// <param name="segment">The target array.</param>
+ /// <param name="start">The index at which to begin the memory.</param>
+ /// <param name="length">The number of items in the memory.</param>
+ /// <remarks>Returns default when <paramref name="segment"/> is null.</remarks>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="segment"/> is covariant and array's type is not exactly T[].</exception>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=segment.Count).
+ /// </exception>
+ public static Memory<T> AsMemory<T>(this ArraySegment<T> segment, int start, int length)
+ {
+ if (((uint)start) > segment.Count)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
+ if (((uint)length) > segment.Count - start)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
+
+ return new Memory<T>(segment.Array, segment.Offset + start, length);
+ }
+
+ /// <summary>
/// Copies the contents of the array into the span. If the source
/// and destinations overlap, this method behaves as if the original values in
/// a temporary location before the destination is overwritten.
///
- ///<param name="array">The array to copy items from.</param>
+ ///<param name="source">The array to copy items from.</param>
/// <param name="destination">The span to copy items into.</param>
/// <exception cref="System.ArgumentException">
/// Thrown when the destination Span is shorter than the source array.
/// </exception>
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void CopyTo<T>(this T[] array, Span<T> destination)
+ public static void CopyTo<T>(this T[] source, Span<T> destination)
{
- new ReadOnlySpan<T>(array).CopyTo(destination);
+ new ReadOnlySpan<T>(source).CopyTo(destination);
}
/// <summary>
@@ -779,16 +1015,16 @@ namespace System
/// and destinations overlap, this method behaves as if the original values are in
/// a temporary location before the destination is overwritten.
///
- ///<param name="array">The array to copy items from.</param>
+ ///<param name="source">The array to copy items from.</param>
/// <param name="destination">The memory to copy items into.</param>
/// <exception cref="System.ArgumentException">
/// Thrown when the destination is shorter than the source array.
/// </exception>
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void CopyTo<T>(this T[] array, Memory<T> destination)
+ public static void CopyTo<T>(this T[] source, Memory<T> destination)
{
- array.CopyTo(destination.Span);
+ source.CopyTo(destination.Span);
}
//
@@ -923,65 +1159,65 @@ namespace System
/// Determines whether two sequences overlap in memory.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool Overlaps<T>(this Span<T> first, ReadOnlySpan<T> second)
+ public static bool Overlaps<T>(this Span<T> span, ReadOnlySpan<T> other)
{
- return Overlaps((ReadOnlySpan<T>)first, second);
+ return Overlaps((ReadOnlySpan<T>)span, other);
}
/// <summary>
/// Determines whether two sequences overlap in memory and outputs the element offset.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool Overlaps<T>(this Span<T> first, ReadOnlySpan<T> second, out int elementOffset)
+ public static bool Overlaps<T>(this Span<T> span, ReadOnlySpan<T> other, out int elementOffset)
{
- return Overlaps((ReadOnlySpan<T>)first, second, out elementOffset);
+ return Overlaps((ReadOnlySpan<T>)span, other, out elementOffset);
}
/// <summary>
/// Determines whether two sequences overlap in memory.
/// </summary>
- public static bool Overlaps<T>(this ReadOnlySpan<T> first, ReadOnlySpan<T> second)
+ public static bool Overlaps<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> other)
{
- if (first.IsEmpty || second.IsEmpty)
+ if (span.IsEmpty || other.IsEmpty)
{
return false;
}
IntPtr byteOffset = Unsafe.ByteOffset(
- ref MemoryMarshal.GetReference(first),
- ref MemoryMarshal.GetReference(second));
+ ref MemoryMarshal.GetReference(span),
+ ref MemoryMarshal.GetReference(other));
if (Unsafe.SizeOf<IntPtr>() == sizeof(int))
{
- return (uint)byteOffset < (uint)(first.Length * Unsafe.SizeOf<T>()) ||
- (uint)byteOffset > (uint)-(second.Length * Unsafe.SizeOf<T>());
+ return (uint)byteOffset < (uint)(span.Length * Unsafe.SizeOf<T>()) ||
+ (uint)byteOffset > (uint)-(other.Length * Unsafe.SizeOf<T>());
}
else
{
- return (ulong)byteOffset < (ulong)((long)first.Length * Unsafe.SizeOf<T>()) ||
- (ulong)byteOffset > (ulong)-((long)second.Length * Unsafe.SizeOf<T>());
+ return (ulong)byteOffset < (ulong)((long)span.Length * Unsafe.SizeOf<T>()) ||
+ (ulong)byteOffset > (ulong)-((long)other.Length * Unsafe.SizeOf<T>());
}
}
/// <summary>
/// Determines whether two sequences overlap in memory and outputs the element offset.
/// </summary>
- public static bool Overlaps<T>(this ReadOnlySpan<T> first, ReadOnlySpan<T> second, out int elementOffset)
+ public static bool Overlaps<T>(this ReadOnlySpan<T> span, ReadOnlySpan<T> other, out int elementOffset)
{
- if (first.IsEmpty || second.IsEmpty)
+ if (span.IsEmpty || other.IsEmpty)
{
elementOffset = 0;
return false;
}
IntPtr byteOffset = Unsafe.ByteOffset(
- ref MemoryMarshal.GetReference(first),
- ref MemoryMarshal.GetReference(second));
+ ref MemoryMarshal.GetReference(span),
+ ref MemoryMarshal.GetReference(other));
if (Unsafe.SizeOf<IntPtr>() == sizeof(int))
{
- if ((uint)byteOffset < (uint)(first.Length * Unsafe.SizeOf<T>()) ||
- (uint)byteOffset > (uint)-(second.Length * Unsafe.SizeOf<T>()))
+ if ((uint)byteOffset < (uint)(span.Length * Unsafe.SizeOf<T>()) ||
+ (uint)byteOffset > (uint)-(other.Length * Unsafe.SizeOf<T>()))
{
if ((int)byteOffset % Unsafe.SizeOf<T>() != 0)
ThrowHelper.ThrowArgumentException_OverlapAlignmentMismatch();
@@ -997,8 +1233,8 @@ namespace System
}
else
{
- if ((ulong)byteOffset < (ulong)((long)first.Length * Unsafe.SizeOf<T>()) ||
- (ulong)byteOffset > (ulong)-((long)second.Length * Unsafe.SizeOf<T>()))
+ if ((ulong)byteOffset < (ulong)((long)span.Length * Unsafe.SizeOf<T>()) ||
+ (ulong)byteOffset > (ulong)-((long)other.Length * Unsafe.SizeOf<T>()))
{
if ((long)byteOffset % Unsafe.SizeOf<T>() != 0)
ThrowHelper.ThrowArgumentException_OverlapAlignmentMismatch();
@@ -1028,7 +1264,7 @@ namespace System
/// no larger element, the bitwise complement of <see cref="Span{T}.Length"/>.
/// </returns>
/// <exception cref="T:System.ArgumentNullException">
- /// <paramref name = "comparable" /> is <see langword="null"/> .
+ /// <paramref name = "comparable" /> is <see langword="null"/> .
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int BinarySearch<T>(
@@ -1052,7 +1288,7 @@ namespace System
/// no larger element, the bitwise complement of <see cref="Span{T}.Length"/>.
/// </returns>
/// <exception cref="T:System.ArgumentNullException">
- /// <paramref name = "comparable" /> is <see langword="null"/> .
+ /// <paramref name = "comparable" /> is <see langword="null"/> .
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int BinarySearch<T, TComparable>(
@@ -1102,7 +1338,7 @@ namespace System
/// no larger element, the bitwise complement of <see cref="ReadOnlySpan{T}.Length"/>.
/// </returns>
/// <exception cref="T:System.ArgumentNullException">
- /// <paramref name = "comparable" /> is <see langword="null"/> .
+ /// <paramref name = "comparable" /> is <see langword="null"/> .
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int BinarySearch<T>(
@@ -1126,7 +1362,7 @@ namespace System
/// no larger element, the bitwise complement of <see cref="ReadOnlySpan{T}.Length"/>.
/// </returns>
/// <exception cref="T:System.ArgumentNullException">
- /// <paramref name = "comparable" /> is <see langword="null"/> .
+ /// <paramref name = "comparable" /> is <see langword="null"/> .
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int BinarySearch<T, TComparable>(
@@ -1166,5 +1402,36 @@ namespace System
value, comparer);
return BinarySearch(span, comparable);
}
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static bool IsTypeComparableAsBytes<T>(out nuint size)
+ {
+ if (typeof(T) == typeof(byte) || typeof(T) == typeof(sbyte))
+ {
+ size = sizeof(byte);
+ return true;
+ }
+
+ if (typeof(T) == typeof(char) || typeof(T) == typeof(short) || typeof(T) == typeof(ushort))
+ {
+ size = sizeof(char);
+ return true;
+ }
+
+ if (typeof(T) == typeof(int) || typeof(T) == typeof(uint))
+ {
+ size = sizeof(int);
+ return true;
+ }
+
+ if (typeof(T) == typeof(long) || typeof(T) == typeof(ulong))
+ {
+ size = sizeof(long);
+ return true;
+ }
+
+ size = default;
+ return false;
+ }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/MethodAccessException.cs b/src/System.Private.CoreLib/shared/System/MethodAccessException.cs
index 1ca0297b9..f329334b2 100644
--- a/src/System.Private.CoreLib/shared/System/MethodAccessException.cs
+++ b/src/System.Private.CoreLib/shared/System/MethodAccessException.cs
@@ -23,13 +23,13 @@ namespace System
HResult = HResults.COR_E_METHODACCESS;
}
- public MethodAccessException(String message)
+ public MethodAccessException(string message)
: base(message)
{
HResult = HResults.COR_E_METHODACCESS;
}
- public MethodAccessException(String message, Exception inner)
+ public MethodAccessException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_METHODACCESS;
diff --git a/src/System.Private.CoreLib/src/System/MissingFieldException.cs b/src/System.Private.CoreLib/shared/System/MissingFieldException.cs
index edac0614d..51078acbc 100644
--- a/src/System.Private.CoreLib/src/System/MissingFieldException.cs
+++ b/src/System.Private.CoreLib/shared/System/MissingFieldException.cs
@@ -2,13 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-/*=============================================================================
-**
-**
-** Purpose: The exception class for class loading failures.
-**
-=============================================================================*/
-
using System.Runtime.Serialization;
namespace System
@@ -17,7 +10,7 @@ namespace System
#if !MONO
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
#endif
- public class MissingFieldException : MissingMemberException
+ public class MissingFieldException : MissingMemberException, ISerializable
{
public MissingFieldException()
: base(SR.Arg_MissingFieldException)
@@ -25,13 +18,13 @@ namespace System
HResult = HResults.COR_E_MISSINGFIELD;
}
- public MissingFieldException(String message)
+ public MissingFieldException(string message)
: base(message)
{
HResult = HResults.COR_E_MISSINGFIELD;
}
- public MissingFieldException(String message, Exception inner)
+ public MissingFieldException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_MISSINGFIELD;
@@ -48,11 +41,19 @@ namespace System
{
}
- public override String Message
+ public override string Message
{
get
{
- return ClassName == null ? base.Message : SR.Format(SR.MissingField_Name, ClassName + "." + MemberName + (Signature != null ? " " + FormatSignature(Signature) : string.Empty));
+ if (ClassName == null)
+ {
+ return base.Message;
+ }
+ else
+ {
+ // do any desired fixups to classname here.
+ return SR.Format(SR.MissingField_Name, (Signature != null ? FormatSignature(Signature) + " " : "") + ClassName + "." + MemberName);
+ }
}
}
}
diff --git a/src/System.Private.CoreLib/src/System/MissingMemberException.cs b/src/System.Private.CoreLib/shared/System/MissingMemberException.cs
index 3be1cfe6a..7aaa38d31 100644
--- a/src/System.Private.CoreLib/src/System/MissingMemberException.cs
+++ b/src/System.Private.CoreLib/shared/System/MissingMemberException.cs
@@ -2,15 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-/*=============================================================================
-**
-**
-**
-** Purpose: The exception class for versioning problems with DLLS.
-**
-**
-=============================================================================*/
-
using System.Runtime.Serialization;
namespace System
@@ -19,7 +10,7 @@ namespace System
#if !MONO
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
#endif
- public class MissingMemberException : MemberAccessException
+ public partial class MissingMemberException : MemberAccessException
{
public MissingMemberException()
: base(SR.Arg_MissingMemberException)
@@ -27,13 +18,13 @@ namespace System
HResult = HResults.COR_E_MISSINGMEMBER;
}
- public MissingMemberException(String message)
+ public MissingMemberException(string message)
: base(message)
{
HResult = HResults.COR_E_MISSINGMEMBER;
}
- public MissingMemberException(String message, Exception inner)
+ public MissingMemberException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_MISSINGMEMBER;
@@ -65,19 +56,18 @@ namespace System
{
get
{
- return ClassName == null ? base.Message : SR.Format(SR.MissingMember_Name, ClassName + "." + MemberName + (Signature != null ? " " + FormatSignature(Signature) : string.Empty));
+ if (ClassName == null)
+ {
+ return base.Message;
+ }
+ else
+ {
+ // do any desired fixups to classname here.
+ return SR.Format(SR.MissingMember_Name, ClassName + "." + MemberName + (Signature != null ? " " + FormatSignature(Signature) : string.Empty));
+ }
}
}
- internal static string FormatSignature(byte[] signature)
- {
- // This is not the correct implementation, however, it's probably not worth the time to port given that
- // (1) it's for a diagnostic
- // (2) Signature is non-null when this exception is created from the native runtime. Which we don't do in .Net Native.
- // (3) Only other time the signature is non-null is if this exception object is deserialized from a persisted blob from an older runtime.
- return string.Empty;
- }
-
// If ClassName != null, GetMessage will construct on the fly using it
// and the other variables. This allows customization of the
// format depending on the language environment.
diff --git a/src/System.Private.CoreLib/shared/System/MulticastNotSupportedException.cs b/src/System.Private.CoreLib/shared/System/MulticastNotSupportedException.cs
index cc6c77023..cb07ac7d0 100644
--- a/src/System.Private.CoreLib/shared/System/MulticastNotSupportedException.cs
+++ b/src/System.Private.CoreLib/shared/System/MulticastNotSupportedException.cs
@@ -21,13 +21,13 @@ namespace System
HResult = HResults.COR_E_MULTICASTNOTSUPPORTED;
}
- public MulticastNotSupportedException(String message)
+ public MulticastNotSupportedException(string message)
: base(message)
{
HResult = HResults.COR_E_MULTICASTNOTSUPPORTED;
}
- public MulticastNotSupportedException(String message, Exception inner)
+ public MulticastNotSupportedException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_MULTICASTNOTSUPPORTED;
diff --git a/src/System.Private.CoreLib/shared/System/NotFiniteNumberException.cs b/src/System.Private.CoreLib/shared/System/NotFiniteNumberException.cs
index b9c9af06d..9afc10458 100644
--- a/src/System.Private.CoreLib/shared/System/NotFiniteNumberException.cs
+++ b/src/System.Private.CoreLib/shared/System/NotFiniteNumberException.cs
@@ -55,13 +55,13 @@ namespace System
protected NotFiniteNumberException(SerializationInfo info, StreamingContext context) : base(info, context)
{
- _offendingNumber = info.GetInt32("OffendingNumber");
+ _offendingNumber = info.GetDouble("OffendingNumber"); // Do not rename (binary serialization)
}
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
- info.AddValue("OffendingNumber", _offendingNumber, typeof(int));
+ info.AddValue("OffendingNumber", _offendingNumber, typeof(double)); // Do not rename (binary serialization)
}
public double OffendingNumber
diff --git a/src/System.Private.CoreLib/shared/System/NotImplementedException.cs b/src/System.Private.CoreLib/shared/System/NotImplementedException.cs
index 1a3b6afcd..e5f378fed 100644
--- a/src/System.Private.CoreLib/shared/System/NotImplementedException.cs
+++ b/src/System.Private.CoreLib/shared/System/NotImplementedException.cs
@@ -25,12 +25,12 @@ namespace System
{
HResult = HResults.E_NOTIMPL;
}
- public NotImplementedException(String message)
+ public NotImplementedException(string message)
: base(message)
{
HResult = HResults.E_NOTIMPL;
}
- public NotImplementedException(String message, Exception inner)
+ public NotImplementedException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.E_NOTIMPL;
diff --git a/src/System.Private.CoreLib/shared/System/NotSupportedException.cs b/src/System.Private.CoreLib/shared/System/NotSupportedException.cs
index 3180bc283..e3191ea13 100644
--- a/src/System.Private.CoreLib/shared/System/NotSupportedException.cs
+++ b/src/System.Private.CoreLib/shared/System/NotSupportedException.cs
@@ -25,13 +25,13 @@ namespace System
HResult = HResults.COR_E_NOTSUPPORTED;
}
- public NotSupportedException(String message)
+ public NotSupportedException(string message)
: base(message)
{
HResult = HResults.COR_E_NOTSUPPORTED;
}
- public NotSupportedException(String message, Exception innerException)
+ public NotSupportedException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_NOTSUPPORTED;
diff --git a/src/System.Private.CoreLib/shared/System/NullReferenceException.cs b/src/System.Private.CoreLib/shared/System/NullReferenceException.cs
index c2e722470..cfbc0fb78 100644
--- a/src/System.Private.CoreLib/shared/System/NullReferenceException.cs
+++ b/src/System.Private.CoreLib/shared/System/NullReferenceException.cs
@@ -25,13 +25,13 @@ namespace System
HResult = HResults.COR_E_NULLREFERENCE;
}
- public NullReferenceException(String message)
+ public NullReferenceException(string message)
: base(message)
{
HResult = HResults.COR_E_NULLREFERENCE;
}
- public NullReferenceException(String message, Exception innerException)
+ public NullReferenceException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_NULLREFERENCE;
diff --git a/src/System.Private.CoreLib/shared/System/Nullable.cs b/src/System.Private.CoreLib/shared/System/Nullable.cs
index 73ad6056c..3c1cbd510 100644
--- a/src/System.Private.CoreLib/shared/System/Nullable.cs
+++ b/src/System.Private.CoreLib/shared/System/Nullable.cs
@@ -141,7 +141,7 @@ namespace System
{
// instantiated generic type only
Type genericType = nullableType.GetGenericTypeDefinition();
- if (Object.ReferenceEquals(genericType, typeof(Nullable<>)))
+ if (object.ReferenceEquals(genericType, typeof(Nullable<>)))
{
return nullableType.GetGenericArguments()[0];
}
diff --git a/src/System.Private.CoreLib/shared/System/Number.Formatting.cs b/src/System.Private.CoreLib/shared/System/Number.Formatting.cs
index 24d5db1da..3d3c15bf7 100644
--- a/src/System.Private.CoreLib/shared/System/Number.Formatting.cs
+++ b/src/System.Private.CoreLib/shared/System/Number.Formatting.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System.Buffers.Text;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.CompilerServices;
@@ -246,12 +247,12 @@ namespace System
private const int DoublePrecision = 15;
private const int ScaleNAN = unchecked((int)0x80000000);
private const int ScaleINF = 0x7FFFFFFF;
- private const int MaxUInt32HexDigits = 8;
private const int MaxUInt32DecDigits = 10;
- private const int MaxUInt64DecDigits = 20;
private const int CharStackBufferSize = 32;
private const string PosNumberFormat = "#";
+ private static readonly string[] s_singleDigitStringCache = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+
private static readonly string[] s_posCurrencyFormats =
{
"$#", "#$", "$ #", "# $"
@@ -289,7 +290,7 @@ namespace System
char fmt = ParseFormatSpecifier(format, out int digits);
NumberBuffer number = default;
- DecimalToNumber(value, ref number);
+ DecimalToNumber(ref value, ref number);
ValueStringBuilder sb;
unsafe
@@ -300,7 +301,7 @@ namespace System
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, isDecimal:true);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -315,7 +316,7 @@ namespace System
char fmt = ParseFormatSpecifier(format, out int digits);
NumberBuffer number = default;
- DecimalToNumber(value, ref number);
+ DecimalToNumber(ref value, ref number);
ValueStringBuilder sb;
unsafe
@@ -326,7 +327,7 @@ namespace System
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, isDecimal: true);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -336,13 +337,12 @@ namespace System
return sb.TryCopyTo(destination, out charsWritten);
}
- private static unsafe void DecimalToNumber(decimal value, ref NumberBuffer number)
+ private static unsafe void DecimalToNumber(ref decimal d, ref NumberBuffer number)
{
- decimal d = value;
-
char* buffer = number.digits;
number.precision = DecimalPrecision;
number.sign = d.IsNegative;
+ number.kind = NumberBufferKind.Decimal;
char* p = buffer + DecimalPrecision;
while ((d.Mid | d.High) != 0)
@@ -351,7 +351,7 @@ namespace System
}
p = UInt32ToDecChars(p, d.Low, 0);
- int i = (int)(buffer + DecimalPrecision - p);
+ int i = (int)((byte*)(buffer + DecimalPrecision) - (byte*)p) >> 1;
number.scale = i - d.Scale;
char* dst = number.digits;
@@ -389,6 +389,7 @@ namespace System
char fmt = ParseFormatSpecifier(format, out int digits);
int precision = DoublePrecision;
NumberBuffer number = default;
+ number.kind = NumberBufferKind.Double;
switch (fmt)
{
@@ -410,12 +411,12 @@ namespace System
if (NumberToDouble(ref number) == value)
{
- NumberToString(ref sb, ref number, 'G', DoublePrecision, info, isDecimal: false);
+ NumberToString(ref sb, ref number, 'G', DoublePrecision, info);
}
else
{
DoubleToNumber(value, 17, ref number);
- NumberToString(ref sb, ref number, 'G', 17, info, isDecimal: false);
+ NumberToString(ref sb, ref number, 'G', 17, info);
}
return null;
@@ -452,7 +453,7 @@ namespace System
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, isDecimal: false);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -489,6 +490,7 @@ namespace System
char fmt = ParseFormatSpecifier(format, out int digits);
int precision = FloatPrecision;
NumberBuffer number = default;
+ number.kind = NumberBufferKind.Double;
switch (fmt)
{
@@ -510,12 +512,12 @@ namespace System
if ((float)NumberToDouble(ref number) == value)
{
- NumberToString(ref sb, ref number, 'G', FloatPrecision, info, isDecimal: false);
+ NumberToString(ref sb, ref number, 'G', FloatPrecision, info);
}
else
{
DoubleToNumber(value, 9, ref number);
- NumberToString(ref sb, ref number, 'G', 9, info, isDecimal: false);
+ NumberToString(ref sb, ref number, 'G', 9, info);
}
return null;
}
@@ -551,7 +553,7 @@ namespace System
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, false);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -583,14 +585,12 @@ namespace System
}
char fmt = ParseFormatSpecifier(format, out int digits);
- NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
-
char fmtUpper = (char)(fmt & 0xFFDF); // ensure fmt is upper-cased for purposes of comparison
if ((fmtUpper == 'G' && digits < 1) || fmtUpper == 'D')
{
return value >= 0 ?
UInt32ToDecStr((uint)value, digits) :
- NegativeInt32ToDecStr(value, digits, info.NegativeSign);
+ NegativeInt32ToDecStr(value, digits, NumberFormatInfo.GetInstance(provider).NegativeSign);
}
else if (fmtUpper == 'X')
{
@@ -600,6 +600,7 @@ namespace System
}
else
{
+ NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
NumberBuffer number = default;
Int32ToNumber(value, ref number);
ValueStringBuilder sb;
@@ -610,7 +611,7 @@ namespace System
}
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, false);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -629,14 +630,12 @@ namespace System
}
char fmt = ParseFormatSpecifier(format, out int digits);
- NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
-
char fmtUpper = (char)(fmt & 0xFFDF); // ensure fmt is upper-cased for purposes of comparison
if ((fmtUpper == 'G' && digits < 1) || fmtUpper == 'D')
{
return value >= 0 ?
TryUInt32ToDecStr((uint)value, digits, destination, out charsWritten) :
- TryNegativeInt32ToDecStr(value, digits, info.NegativeSign, destination, out charsWritten);
+ TryNegativeInt32ToDecStr(value, digits, NumberFormatInfo.GetInstance(provider).NegativeSign, destination, out charsWritten);
}
else if (fmtUpper == 'X')
{
@@ -646,6 +645,7 @@ namespace System
}
else
{
+ NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
NumberBuffer number = default;
Int32ToNumber(value, ref number);
ValueStringBuilder sb;
@@ -656,7 +656,7 @@ namespace System
}
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, false);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -675,8 +675,6 @@ namespace System
}
char fmt = ParseFormatSpecifier(format, out int digits);
- NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
-
char fmtUpper = (char)(fmt & 0xFFDF); // ensure fmt is upper-cased for purposes of comparison
if ((fmtUpper == 'G' && digits < 1) || fmtUpper == 'D')
{
@@ -690,6 +688,7 @@ namespace System
}
else
{
+ NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
NumberBuffer number = default;
UInt32ToNumber(value, ref number);
ValueStringBuilder sb;
@@ -700,7 +699,7 @@ namespace System
}
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, false);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -719,8 +718,6 @@ namespace System
}
char fmt = ParseFormatSpecifier(format, out int digits);
- NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
-
char fmtUpper = (char)(fmt & 0xFFDF); // ensure fmt is upper-cased for purposes of comparison
if ((fmtUpper == 'G' && digits < 1) || fmtUpper == 'D')
{
@@ -734,6 +731,7 @@ namespace System
}
else
{
+ NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
NumberBuffer number = default;
UInt32ToNumber(value, ref number);
ValueStringBuilder sb;
@@ -744,7 +742,7 @@ namespace System
}
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, false);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -763,14 +761,12 @@ namespace System
}
char fmt = ParseFormatSpecifier(format, out int digits);
- NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
-
char fmtUpper = (char)(fmt & 0xFFDF); // ensure fmt is upper-cased for purposes of comparison
if ((fmtUpper == 'G' && digits < 1) || fmtUpper == 'D')
{
return value >= 0 ?
UInt64ToDecStr((ulong)value, digits) :
- NegativeInt64ToDecStr(value, digits, info.NegativeSign);
+ NegativeInt64ToDecStr(value, digits, NumberFormatInfo.GetInstance(provider).NegativeSign);
}
else if (fmtUpper == 'X')
{
@@ -781,6 +777,7 @@ namespace System
}
else
{
+ NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
NumberBuffer number = default;
Int64ToNumber(value, ref number);
ValueStringBuilder sb;
@@ -791,7 +788,7 @@ namespace System
}
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, false);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -810,14 +807,12 @@ namespace System
}
char fmt = ParseFormatSpecifier(format, out int digits);
- NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
-
char fmtUpper = (char)(fmt & 0xFFDF); // ensure fmt is upper-cased for purposes of comparison
if ((fmtUpper == 'G' && digits < 1) || fmtUpper == 'D')
{
return value >= 0 ?
TryUInt64ToDecStr((ulong)value, digits, destination, out charsWritten) :
- TryNegativeInt64ToDecStr(value, digits, info.NegativeSign, destination, out charsWritten);
+ TryNegativeInt64ToDecStr(value, digits, NumberFormatInfo.GetInstance(provider).NegativeSign, destination, out charsWritten);
}
else if (fmtUpper == 'X')
{
@@ -828,6 +823,7 @@ namespace System
}
else
{
+ NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
NumberBuffer number = default;
Int64ToNumber(value, ref number);
ValueStringBuilder sb;
@@ -838,7 +834,7 @@ namespace System
}
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, false);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -857,8 +853,6 @@ namespace System
}
char fmt = ParseFormatSpecifier(format, out int digits);
- NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
-
char fmtUpper = (char)(fmt & 0xFFDF); // ensure fmt is upper-cased for purposes of comparison
if ((fmtUpper == 'G' && digits < 1) || fmtUpper == 'D')
{
@@ -873,6 +867,7 @@ namespace System
}
else
{
+ NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
NumberBuffer number = default;
UInt64ToNumber(value, ref number);
ValueStringBuilder sb;
@@ -883,7 +878,7 @@ namespace System
}
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, false);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -902,8 +897,6 @@ namespace System
}
char fmt = ParseFormatSpecifier(format, out int digits);
- NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
-
char fmtUpper = (char)(fmt & 0xFFDF); // ensure fmt is upper-cased for purposes of comparison
if ((fmtUpper == 'G' && digits < 1) || fmtUpper == 'D')
{
@@ -918,6 +911,7 @@ namespace System
}
else
{
+ NumberFormatInfo info = NumberFormatInfo.GetInstance(provider);
NumberBuffer number = default;
UInt64ToNumber(value, ref number);
ValueStringBuilder sb;
@@ -928,7 +922,7 @@ namespace System
}
if (fmt != 0)
{
- NumberToString(ref sb, ref number, fmt, digits, info, false);
+ NumberToString(ref sb, ref number, fmt, digits, info);
}
else
{
@@ -958,6 +952,7 @@ namespace System
int i = (int)(buffer + Int32Precision - p);
number.scale = i;
+ number.kind = NumberBufferKind.Integer;
char* dst = number.digits;
while (--i >= 0)
@@ -972,18 +967,20 @@ namespace System
if (digits < 1)
digits = 1;
- int bufferLength = Math.Max(digits, MaxUInt32DecDigits) + sNegative.Length;
- int index = bufferLength;
-
- char* buffer = stackalloc char[bufferLength];
- char* p = UInt32ToDecChars(buffer + bufferLength, (uint)(-value), digits);
- for (int i = sNegative.Length - 1; i >= 0; i--)
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountDigits((uint)(-value))) + sNegative.Length;
+ string result = string.FastAllocateString(bufferLength);
+ fixed (char* buffer = result)
{
- *(--p) = sNegative[i];
- }
+ char* p = UInt32ToDecChars(buffer + bufferLength, (uint)(-value), digits);
+ Debug.Assert(p == buffer + sNegative.Length);
- Debug.Assert(buffer + bufferLength - p >= 0 && buffer <= p);
- return new string(p, 0, (int)(buffer + bufferLength - p));
+ for (int i = sNegative.Length - 1; i >= 0; i--)
+ {
+ *(--p) = sNegative[i];
+ }
+ Debug.Assert(p == buffer);
+ }
+ return result;
}
private static unsafe bool TryNegativeInt32ToDecStr(int value, int digits, string sNegative, Span<char> destination, out int charsWritten)
@@ -993,18 +990,26 @@ namespace System
if (digits < 1)
digits = 1;
- int bufferLength = Math.Max(digits, MaxUInt32DecDigits) + sNegative.Length;
- int index = bufferLength;
-
- char* buffer = stackalloc char[bufferLength];
- char* p = UInt32ToDecChars(buffer + bufferLength, (uint)(-value), digits);
- for (int i = sNegative.Length - 1; i >= 0; i--)
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountDigits((uint)(-value))) + sNegative.Length;
+ if (bufferLength > destination.Length)
{
- *(--p) = sNegative[i];
+ charsWritten = 0;
+ return false;
}
- Debug.Assert(buffer + bufferLength - p >= 0 && buffer <= p);
- return TryCopyTo(p, (int)(buffer + bufferLength - p), destination, out charsWritten);
+ charsWritten = bufferLength;
+ fixed (char* buffer = &MemoryMarshal.GetReference(destination))
+ {
+ char* p = UInt32ToDecChars(buffer + bufferLength, (uint)(-value), digits);
+ Debug.Assert(p == buffer + sNegative.Length);
+
+ for (int i = sNegative.Length - 1; i >= 0; i--)
+ {
+ *(--p) = sNegative[i];
+ }
+ Debug.Assert(p == buffer);
+ }
+ return true;
}
private static unsafe string Int32ToHexStr(int value, char hexBase, int digits)
@@ -1012,11 +1017,14 @@ namespace System
if (digits < 1)
digits = 1;
- int bufferLength = Math.Max(digits, MaxUInt32HexDigits);
- char* buffer = stackalloc char[bufferLength];
-
- char* p = Int32ToHexChars(buffer + bufferLength, (uint)value, hexBase, digits);
- return new string(p, 0, (int)(buffer + bufferLength - p));
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountHexDigits((uint)value));
+ string result = string.FastAllocateString(bufferLength);
+ fixed (char* buffer = result)
+ {
+ char* p = Int32ToHexChars(buffer + bufferLength, (uint)value, hexBase, digits);
+ Debug.Assert(p == buffer);
+ }
+ return result;
}
private static unsafe bool TryInt32ToHexStr(int value, char hexBase, int digits, Span<char> destination, out int charsWritten)
@@ -1024,11 +1032,20 @@ namespace System
if (digits < 1)
digits = 1;
- int bufferLength = Math.Max(digits, MaxUInt32HexDigits);
- char* buffer = stackalloc char[bufferLength];
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountHexDigits((uint)value));
+ if (bufferLength > destination.Length)
+ {
+ charsWritten = 0;
+ return false;
+ }
- char* p = Int32ToHexChars(buffer + bufferLength, (uint)value, hexBase, digits);
- return TryCopyTo(p, (int)(buffer + bufferLength - p), destination, out charsWritten);
+ charsWritten = bufferLength;
+ fixed (char* buffer = &MemoryMarshal.GetReference(destination))
+ {
+ char* p = Int32ToHexChars(buffer + bufferLength, (uint)value, hexBase, digits);
+ Debug.Assert(p == buffer);
+ }
+ return true;
}
private static unsafe char* Int32ToHexChars(char* buffer, uint value, int hexBase, int digits)
@@ -1052,6 +1069,7 @@ namespace System
char* p = UInt32ToDecChars(buffer + UInt32Precision, value, 0);
int i = (int)(buffer + UInt32Precision - p);
number.scale = i;
+ number.kind = NumberBufferKind.Integer;
char* dst = number.digits;
while (--i >= 0)
@@ -1073,56 +1091,69 @@ namespace System
private static unsafe string UInt32ToDecStr(uint value, int digits)
{
- if (digits <= 1)
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountDigits(value));
+
+ // For single-digit values that are very common, especially 0 and 1, just return cached strings.
+ if (bufferLength == 1)
{
- char* buffer = stackalloc char[MaxUInt32DecDigits];
+ return s_singleDigitStringCache[value];
+ }
- char* start = buffer + MaxUInt32DecDigits;
- char* p = start;
- do
+ string result = string.FastAllocateString(bufferLength);
+ fixed (char* buffer = result)
+ {
+ char* p = buffer + bufferLength;
+ if (digits <= 1)
{
- // TODO https://github.com/dotnet/coreclr/issues/3439
- uint div = value / 10;
- *(--p) = (char)('0' + value - (div * 10));
- value = div;
+ do
+ {
+ // TODO https://github.com/dotnet/coreclr/issues/3439
+ uint div = value / 10;
+ *(--p) = (char)('0' + value - (div * 10));
+ value = div;
+ }
+ while (value != 0);
}
- while (value != 0);
-
- return new string(p, 0, (int)(start - p));
- }
- else
- {
- int bufferSize = Math.Max(digits, MaxUInt32DecDigits);
- char* buffer = stackalloc char[bufferSize];
- char* p = UInt32ToDecChars(buffer + bufferSize, value, digits);
- return new string(p, 0, (int)(buffer + bufferSize - p));
+ else
+ {
+ p = UInt32ToDecChars(p, value, digits);
+ }
+ Debug.Assert(p == buffer);
}
+ return result;
}
private static unsafe bool TryUInt32ToDecStr(uint value, int digits, Span<char> destination, out int charsWritten)
{
- if (digits <= 1)
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountDigits(value));
+ if (bufferLength > destination.Length)
{
- char* buffer = stackalloc char[MaxUInt32DecDigits];
- char* start = buffer + MaxUInt32DecDigits;
- char* p = start;
- do
- {
- // TODO https://github.com/dotnet/coreclr/issues/3439
- uint div = value / 10;
- *(--p) = (char)('0' + value - (div * 10));
- value = div;
- }
- while (value != 0);
- return TryCopyTo(p, (int)(start - p), destination, out charsWritten);
+ charsWritten = 0;
+ return false;
}
- else
+
+ charsWritten = bufferLength;
+ fixed (char* buffer = &MemoryMarshal.GetReference(destination))
{
- int bufferSize = Math.Max(digits, MaxUInt32DecDigits);
- char* buffer = stackalloc char[bufferSize];
- char* p = UInt32ToDecChars(buffer + bufferSize, value, digits);
- return TryCopyTo(p, (int)(buffer + bufferSize - p), destination, out charsWritten);
+ char* p = buffer + bufferLength;
+ if (digits <= 1)
+ {
+ do
+ {
+ // TODO https://github.com/dotnet/coreclr/issues/3439
+ uint div = value / 10;
+ *(--p) = (char)('0' + value - (div * 10));
+ value = div;
+ }
+ while (value != 0);
+ }
+ else
+ {
+ p = UInt32ToDecChars(p, value, digits);
+ }
+ Debug.Assert(p == buffer);
}
+ return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -1158,6 +1189,7 @@ namespace System
int i = (int)(buffer + Int64Precision - p);
number.scale = i;
+ number.kind = NumberBufferKind.Integer;
char* dst = number.digits;
while (--i >= 0)
@@ -1176,24 +1208,26 @@ namespace System
ulong value = (ulong)(-input);
- int bufferLength = Math.Max(digits, MaxUInt64DecDigits) + sNegative.Length;
- int index = bufferLength;
-
- char* buffer = stackalloc char[bufferLength];
- char* p = buffer + bufferLength;
- while (High32(value) != 0)
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountDigits(value)) + sNegative.Length;
+ string result = string.FastAllocateString(bufferLength);
+ fixed (char* buffer = result)
{
- p = UInt32ToDecChars(p, Int64DivMod1E9(ref value), 9);
- digits -= 9;
- }
- p = UInt32ToDecChars(p, Low32(value), digits);
+ char* p = buffer + bufferLength;
+ while (High32(value) != 0)
+ {
+ p = UInt32ToDecChars(p, Int64DivMod1E9(ref value), 9);
+ digits -= 9;
+ }
+ p = UInt32ToDecChars(p, Low32(value), digits);
+ Debug.Assert(p == buffer + sNegative.Length);
- for (int i = sNegative.Length - 1; i >= 0; i--)
- {
- *(--p) = sNegative[i];
+ for (int i = sNegative.Length - 1; i >= 0; i--)
+ {
+ *(--p) = sNegative[i];
+ }
+ Debug.Assert(p == buffer);
}
-
- return new string(p, 0, (int)(buffer + bufferLength - p));
+ return result;
}
private static unsafe bool TryNegativeInt64ToDecStr(long input, int digits, string sNegative, Span<char> destination, out int charsWritten)
@@ -1207,64 +1241,80 @@ namespace System
ulong value = (ulong)(-input);
- int bufferLength = Math.Max(digits, MaxUInt64DecDigits) + sNegative.Length;
- int index = bufferLength;
-
- char* buffer = stackalloc char[bufferLength];
- char* p = buffer + bufferLength;
- while (High32(value) != 0)
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountDigits((ulong)(-input))) + sNegative.Length;
+ if (bufferLength > destination.Length)
{
- p = UInt32ToDecChars(p, Int64DivMod1E9(ref value), 9);
- digits -= 9;
+ charsWritten = 0;
+ return false;
}
- p = UInt32ToDecChars(p, Low32(value), digits);
- for (int i = sNegative.Length - 1; i >= 0; i--)
+ charsWritten = bufferLength;
+ fixed (char* buffer = &MemoryMarshal.GetReference(destination))
{
- *(--p) = sNegative[i];
- }
+ char* p = buffer + bufferLength;
+ while (High32(value) != 0)
+ {
+ p = UInt32ToDecChars(p, Int64DivMod1E9(ref value), 9);
+ digits -= 9;
+ }
+ p = UInt32ToDecChars(p, Low32(value), digits);
+ Debug.Assert(p == buffer + sNegative.Length);
- return TryCopyTo(p, (int)(buffer + bufferLength - p), destination, out charsWritten);
+ for (int i = sNegative.Length - 1; i >= 0; i--)
+ {
+ *(--p) = sNegative[i];
+ }
+ Debug.Assert(p == buffer);
+ }
+ return true;
}
private static unsafe string Int64ToHexStr(long value, char hexBase, int digits)
{
- int bufferLength = Math.Max(digits, MaxUInt32HexDigits * 2);
- char* buffer = stackalloc char[bufferLength];
- int index = bufferLength;
-
- char* p;
- if (High32((ulong)value) != 0)
- {
- p = Int32ToHexChars(buffer + index, Low32((ulong)value), hexBase, 8);
- p = Int32ToHexChars(p, High32((ulong)value), hexBase, digits - 8);
- }
- else
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountHexDigits((ulong)value));
+ string result = string.FastAllocateString(bufferLength);
+ fixed (char* buffer = result)
{
- p = Int32ToHexChars(buffer + index, Low32((ulong)value), hexBase, Math.Max(digits, 1));
+ char* p = buffer + bufferLength;
+ if (High32((ulong)value) != 0)
+ {
+ p = Int32ToHexChars(p, Low32((ulong)value), hexBase, 8);
+ p = Int32ToHexChars(p, High32((ulong)value), hexBase, digits - 8);
+ }
+ else
+ {
+ p = Int32ToHexChars(p, Low32((ulong)value), hexBase, Math.Max(digits, 1));
+ }
+ Debug.Assert(p == buffer);
}
-
- return new string(p, 0, (int)(buffer + bufferLength - p));
+ return result;
}
private static unsafe bool TryInt64ToHexStr(long value, char hexBase, int digits, Span<char> destination, out int charsWritten)
{
- int bufferLength = Math.Max(digits, MaxUInt32HexDigits * 2);
- char* buffer = stackalloc char[bufferLength];
- int index = bufferLength;
-
- char* p;
- if (High32((ulong)value) != 0)
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountHexDigits((ulong)value));
+ if (bufferLength > destination.Length)
{
- p = Int32ToHexChars(buffer + index, Low32((ulong)value), hexBase, 8);
- p = Int32ToHexChars(p, High32((ulong)value), hexBase, digits - 8);
+ charsWritten = 0;
+ return false;
}
- else
+
+ charsWritten = bufferLength;
+ fixed (char* buffer = &MemoryMarshal.GetReference(destination))
{
- p = Int32ToHexChars(buffer + index, Low32((ulong)value), hexBase, Math.Max(digits, 1));
+ char* p = buffer + bufferLength;
+ if (High32((ulong)value) != 0)
+ {
+ p = Int32ToHexChars(p, Low32((ulong)value), hexBase, 8);
+ p = Int32ToHexChars(p, High32((ulong)value), hexBase, digits - 8);
+ }
+ else
+ {
+ p = Int32ToHexChars(p, Low32((ulong)value), hexBase, Math.Max(digits, 1));
+ }
+ Debug.Assert(p == buffer);
}
-
- return TryCopyTo(p, (int)(buffer + bufferLength - p), destination, out charsWritten);
+ return true;
}
private static unsafe void UInt64ToNumber(ulong value, ref NumberBuffer number)
@@ -1281,6 +1331,7 @@ namespace System
int i = (int)(buffer + UInt64Precision - p);
number.scale = i;
+ number.kind = NumberBufferKind.Integer;
char* dst = number.digits;
while (--i >= 0)
@@ -1293,17 +1344,27 @@ namespace System
if (digits < 1)
digits = 1;
- int bufferSize = Math.Max(digits, MaxUInt64DecDigits);
- char* buffer = stackalloc char[bufferSize];
- char* p = buffer + bufferSize;
- while (High32(value) != 0)
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountDigits(value));
+
+ // For single-digit values that are very common, especially 0 and 1, just return cached strings.
+ if (bufferLength == 1)
{
- p = UInt32ToDecChars(p, Int64DivMod1E9(ref value), 9);
- digits -= 9;
+ return s_singleDigitStringCache[value];
}
- p = UInt32ToDecChars(p, Low32(value), digits);
- return new string(p, 0, (int)(buffer + bufferSize - p));
+ string result = string.FastAllocateString(bufferLength);
+ fixed (char* buffer = result)
+ {
+ char* p = buffer + bufferLength;
+ while (High32(value) != 0)
+ {
+ p = UInt32ToDecChars(p, Int64DivMod1E9(ref value), 9);
+ digits -= 9;
+ }
+ p = UInt32ToDecChars(p, Low32(value), digits);
+ Debug.Assert(p == buffer);
+ }
+ return result;
}
private static unsafe bool TryUInt64ToDecStr(ulong value, int digits, Span<char> destination, out int charsWritten)
@@ -1311,17 +1372,26 @@ namespace System
if (digits < 1)
digits = 1;
- int bufferSize = Math.Max(digits, MaxUInt64DecDigits);
- char* buffer = stackalloc char[bufferSize];
- char* p = buffer + bufferSize;
- while (High32(value) != 0)
+ int bufferLength = Math.Max(digits, FormattingHelpers.CountDigits(value));
+ if (bufferLength > destination.Length)
{
- p = UInt32ToDecChars(p, Int64DivMod1E9(ref value), 9);
- digits -= 9;
+ charsWritten = 0;
+ return false;
}
- p = UInt32ToDecChars(p, Low32(value), digits);
- return TryCopyTo(p, (int)(buffer + bufferSize - p), destination, out charsWritten);
+ charsWritten = bufferLength;
+ fixed (char* buffer = &MemoryMarshal.GetReference(destination))
+ {
+ char* p = buffer + bufferLength;
+ while (High32(value) != 0)
+ {
+ p = UInt32ToDecChars(p, Int64DivMod1E9(ref value), 9);
+ digits -= 9;
+ }
+ p = UInt32ToDecChars(p, Low32(value), digits);
+ Debug.Assert(p == buffer);
+ }
+ return true;
}
internal static unsafe char ParseFormatSpecifier(ReadOnlySpan<char> format, out int digits)
@@ -1390,22 +1460,21 @@ namespace System
'\0';
}
- internal static unsafe void NumberToString(ref ValueStringBuilder sb, ref NumberBuffer number, char format, int nMaxDigits, NumberFormatInfo info, bool isDecimal)
+ internal static unsafe void NumberToString(ref ValueStringBuilder sb, ref NumberBuffer number, char format, int nMaxDigits, NumberFormatInfo info)
{
- int nMinDigits = -1;
+ Debug.Assert(number.kind != NumberBufferKind.Unknown);
switch (format)
{
case 'C':
case 'c':
{
- nMinDigits = nMaxDigits >= 0 ? nMaxDigits : info.CurrencyDecimalDigits;
if (nMaxDigits < 0)
nMaxDigits = info.CurrencyDecimalDigits;
RoundNumber(ref number, number.scale + nMaxDigits); // Don't change this line to use digPos since digCount could have its sign changed.
- FormatCurrency(ref sb, ref number, nMinDigits, nMaxDigits, info);
+ FormatCurrency(ref sb, ref number, nMaxDigits, info);
break;
}
@@ -1414,16 +1483,14 @@ namespace System
case 'f':
{
if (nMaxDigits < 0)
- nMaxDigits = nMinDigits = info.NumberDecimalDigits;
- else
- nMinDigits = nMaxDigits;
+ nMaxDigits = info.NumberDecimalDigits;
RoundNumber(ref number, number.scale + nMaxDigits);
if (number.sign)
sb.Append(info.NegativeSign);
- FormatFixed(ref sb, ref number, nMinDigits, nMaxDigits, info, null, info.NumberDecimalSeparator, null);
+ FormatFixed(ref sb, ref number, nMaxDigits, info, null, info.NumberDecimalSeparator, null);
break;
}
@@ -1432,13 +1499,11 @@ namespace System
case 'n':
{
if (nMaxDigits < 0)
- nMaxDigits = nMinDigits = info.NumberDecimalDigits; // Since we are using digits in our calculation
- else
- nMinDigits = nMaxDigits;
+ nMaxDigits = info.NumberDecimalDigits; // Since we are using digits in our calculation
RoundNumber(ref number, number.scale + nMaxDigits);
- FormatNumber(ref sb, ref number, nMinDigits, nMaxDigits, info);
+ FormatNumber(ref sb, ref number, nMaxDigits, info);
break;
}
@@ -1447,9 +1512,7 @@ namespace System
case 'e':
{
if (nMaxDigits < 0)
- nMaxDigits = nMinDigits = 6;
- else
- nMinDigits = nMaxDigits;
+ nMaxDigits = 6;
nMaxDigits++;
RoundNumber(ref number, nMaxDigits);
@@ -1457,7 +1520,7 @@ namespace System
if (number.sign)
sb.Append(info.NegativeSign);
- FormatScientific(ref sb, ref number, nMinDigits, nMaxDigits, info, format);
+ FormatScientific(ref sb, ref number, nMaxDigits, info, format);
break;
}
@@ -1465,40 +1528,28 @@ namespace System
case 'G':
case 'g':
{
- bool enableRounding = true;
+ bool noRounding = false;
if (nMaxDigits < 1)
{
- if (isDecimal && (nMaxDigits == -1))
+ if ((number.kind == NumberBufferKind.Decimal) && (nMaxDigits == -1))
{
- // Default to 29 digits precision only for G formatting without a precision specifier
- // This ensures that the PAL code pads out to the correct place even when we use the default precision
- nMaxDigits = nMinDigits = DecimalPrecision;
- enableRounding = false; // Turn off rounding for ECMA compliance to output trailing 0's after decimal as significant
+ noRounding = true; // Turn off rounding for ECMA compliance to output trailing 0's after decimal as significant
+ goto SkipRounding;
}
else
{
// This ensures that the PAL code pads out to the correct place even when we use the default precision
- nMaxDigits = nMinDigits = number.precision;
+ nMaxDigits = number.precision;
}
}
- else
- nMinDigits = nMaxDigits;
- if (enableRounding) // Don't round for G formatting without precision
- RoundNumber(ref number, nMaxDigits); // This also fixes up the minus zero case
- else
- {
- if (isDecimal && (number.digits[0] == 0))
- {
- // Minus zero should be formatted as 0
- number.sign = false;
- }
- }
+ RoundNumber(ref number, nMaxDigits);
+SkipRounding:
if (number.sign)
sb.Append(info.NegativeSign);
- FormatGeneral(ref sb, ref number, nMinDigits, nMaxDigits, info, (char)(format - ('G' - 'E')), !enableRounding);
+ FormatGeneral(ref sb, ref number, nMaxDigits, info, (char)(format - ('G' - 'E')), noRounding);
break;
}
@@ -1507,14 +1558,12 @@ namespace System
case 'p':
{
if (nMaxDigits < 0)
- nMaxDigits = nMinDigits = info.PercentDecimalDigits;
- else
- nMinDigits = nMaxDigits;
+ nMaxDigits = info.PercentDecimalDigits;
number.scale += 2;
RoundNumber(ref number, number.scale + nMaxDigits);
- FormatPercent(ref sb, ref number, nMinDigits, nMaxDigits, info);
+ FormatPercent(ref sb, ref number, nMaxDigits, info);
break;
}
@@ -1526,6 +1575,8 @@ namespace System
internal static unsafe void NumberToStringFormat(ref ValueStringBuilder sb, ref NumberBuffer number, ReadOnlySpan<char> format, NumberFormatInfo info)
{
+ Debug.Assert(number.kind != NumberBufferKind.Unknown);
+
int digitCount;
int decimalPos;
int firstDigit;
@@ -1648,7 +1699,6 @@ namespace System
}
else
{
- number.sign = false; // We need to format -0 without the sign set.
number.scale = 0; // Decimals with scale ('0.00') should be rounded.
}
@@ -1881,7 +1931,7 @@ namespace System
}
}
- private static void FormatCurrency(ref ValueStringBuilder sb, ref NumberBuffer number, int nMinDigits, int nMaxDigits, NumberFormatInfo info)
+ private static void FormatCurrency(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info)
{
string fmt = number.sign ?
s_negCurrencyFormats[info.CurrencyNegativePattern] :
@@ -1892,7 +1942,7 @@ namespace System
switch (ch)
{
case '#':
- FormatFixed(ref sb, ref number, nMinDigits, nMaxDigits, info, info.currencyGroupSizes, info.CurrencyDecimalSeparator, info.CurrencyGroupSeparator);
+ FormatFixed(ref sb, ref number, nMaxDigits, info, info.currencyGroupSizes, info.CurrencyDecimalSeparator, info.CurrencyGroupSeparator);
break;
case '-':
sb.Append(info.NegativeSign);
@@ -1907,7 +1957,7 @@ namespace System
}
}
- private static unsafe void FormatFixed(ref ValueStringBuilder sb, ref NumberBuffer number, int nMinDigits, int nMaxDigits, NumberFormatInfo info, int[] groupDigits, string sDecimal, string sGroup)
+ private static unsafe void FormatFixed(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info, int[] groupDigits, string sDecimal, string sGroup)
{
int digPos = number.scale;
char* dig = number.digits;
@@ -1917,13 +1967,14 @@ namespace System
if (groupDigits != null)
{
int groupSizeIndex = 0; // Index into the groupDigits array.
- int groupSizeCount = groupDigits[groupSizeIndex]; // The current total of group size.
int bufferSize = digPos; // The length of the result buffer string.
int groupSize = 0; // The current group size.
// Find out the size of the string buffer for the result.
if (groupDigits.Length != 0) // You can pass in 0 length arrays
{
+ int groupSizeCount = groupDigits[groupSizeIndex]; // The current total of group size.
+
while (digPos > groupSizeCount)
{
groupSize = groupDigits[groupSizeIndex];
@@ -2008,7 +2059,7 @@ namespace System
}
}
- private static void FormatNumber(ref ValueStringBuilder sb, ref NumberBuffer number, int nMinDigits, int nMaxDigits, NumberFormatInfo info)
+ private static void FormatNumber(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info)
{
string fmt = number.sign ?
s_negNumberFormats[info.NumberNegativePattern] :
@@ -2019,7 +2070,7 @@ namespace System
switch (ch)
{
case '#':
- FormatFixed(ref sb, ref number, nMinDigits, nMaxDigits, info, info.numberGroupSizes, info.NumberDecimalSeparator, info.NumberGroupSeparator);
+ FormatFixed(ref sb, ref number, nMaxDigits, info, info.numberGroupSizes, info.NumberDecimalSeparator, info.NumberGroupSeparator);
break;
case '-':
sb.Append(info.NegativeSign);
@@ -2031,7 +2082,7 @@ namespace System
}
}
- private static unsafe void FormatScientific(ref ValueStringBuilder sb, ref NumberBuffer number, int nMinDigits, int nMaxDigits, NumberFormatInfo info, char expChar)
+ private static unsafe void FormatScientific(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info, char expChar)
{
char* dig = number.digits;
@@ -2068,7 +2119,7 @@ namespace System
sb.Append(p, (int)(digits + MaxUInt32DecDigits - p));
}
- private static unsafe void FormatGeneral(ref ValueStringBuilder sb, ref NumberBuffer number, int nMinDigits, int nMaxDigits, NumberFormatInfo info, char expChar, bool bSuppressScientific)
+ private static unsafe void FormatGeneral(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info, char expChar, bool bSuppressScientific)
{
int digPos = number.scale;
bool scientific = false;
@@ -2115,7 +2166,7 @@ namespace System
FormatExponent(ref sb, info, number.scale - 1, expChar, 2, true);
}
- private static void FormatPercent(ref ValueStringBuilder sb, ref NumberBuffer number, int nMinDigits, int nMaxDigits, NumberFormatInfo info)
+ private static void FormatPercent(ref ValueStringBuilder sb, ref NumberBuffer number, int nMaxDigits, NumberFormatInfo info)
{
string fmt = number.sign ?
s_negPercentFormats[info.PercentNegativePattern] :
@@ -2126,7 +2177,7 @@ namespace System
switch (ch)
{
case '#':
- FormatFixed(ref sb, ref number, nMinDigits, nMaxDigits, info, info.percentGroupSizes, info.PercentDecimalSeparator, info.PercentGroupSeparator);
+ FormatFixed(ref sb, ref number, nMaxDigits, info, info.percentGroupSizes, info.PercentDecimalSeparator, info.PercentGroupSeparator);
break;
case '-':
sb.Append(info.NegativeSign);
@@ -2173,7 +2224,11 @@ namespace System
if (i == 0)
{
number.scale = 0;
- number.sign = false;
+
+ if (number.kind == NumberBufferKind.Integer)
+ {
+ number.sign = false;
+ }
}
dig[i] = '\0';
}
diff --git a/src/System.Private.CoreLib/shared/System/Number.NumberBuffer.cs b/src/System.Private.CoreLib/shared/System/Number.NumberBuffer.cs
index 2316f99bd..1730cf18f 100644
--- a/src/System.Private.CoreLib/shared/System/Number.NumberBuffer.cs
+++ b/src/System.Private.CoreLib/shared/System/Number.NumberBuffer.cs
@@ -15,17 +15,27 @@ namespace System
[StructLayout(LayoutKind.Sequential, Pack = 1)]
internal unsafe ref struct NumberBuffer // needs to match layout of NUMBER in coreclr's src/classlibnative/bcltype/number.h
{
- public int precision;
- public int scale;
- private int _sign;
- private DigitsAndNullTerminator _digits;
- private char* _allDigits;
+ public int precision; // 0
+ public int scale; // 4
+ private int _sign; // 8
+ private NumberBufferKind _kind; // 12
+ private char* _allDigits; // 16
+ private DigitsAndNullTerminator _digits; // 20 or 24
public bool sign { get => _sign != 0; set => _sign = value ? 1 : 0; }
public char* digits => (char*)Unsafe.AsPointer(ref _digits);
+ public NumberBufferKind kind { get => _kind; set => _kind = value; }
[StructLayout(LayoutKind.Sequential, Size = (NumberMaxDigits + 1) * sizeof(char))]
private struct DigitsAndNullTerminator { }
}
+
+ internal enum NumberBufferKind // needs to match NUMBER_KIND in coreclr's src/classlibnative/bcltype/number.h
+ {
+ Unknown = 0,
+ Integer = 1,
+ Decimal = 2,
+ Double = 3
+ }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Number.Parsing.cs b/src/System.Private.CoreLib/shared/System/Number.Parsing.cs
index 46951094e..7c7866a90 100644
--- a/src/System.Private.CoreLib/shared/System/Number.Parsing.cs
+++ b/src/System.Private.CoreLib/shared/System/Number.Parsing.cs
@@ -5,6 +5,11 @@
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
+#if MONO
+using System.Runtime.CompilerServices;
+#else
+using Internal.Runtime.CompilerServices;
+#endif
namespace System
{
@@ -30,129 +35,26 @@ namespace System
private const int Int64Precision = 19;
private const int UInt64Precision = 20;
- private static bool HexNumberToInt32(ref NumberBuffer number, ref int value)
+ /// <summary>256-element map from an ASCII char to its hex value, e.g. arr['b'] == 11. 0xFF means it's not a hex digit.</summary>
+ private static readonly int[] s_charToHexLookup =
{
- uint passedValue = 0;
- bool returnValue = HexNumberToUInt32(ref number, ref passedValue);
- value = (int)passedValue;
- return returnValue;
- }
-
- private static bool HexNumberToInt64(ref NumberBuffer number, ref long value)
- {
- ulong passedValue = 0;
- bool returnValue = HexNumberToUInt64(ref number, ref passedValue);
- value = (long)passedValue;
- return returnValue;
- }
-
- private static unsafe bool HexNumberToUInt32(ref NumberBuffer number, ref uint value)
- {
- int i = number.scale;
- if (i > UInt32Precision || i < number.precision)
- {
- return false;
- }
- char* p = number.digits;
- Debug.Assert(p != null);
-
- uint n = 0;
- while (--i >= 0)
- {
- if (n > ((uint)0xFFFFFFFF / 16))
- {
- return false;
- }
- n *= 16;
- if (*p != '\0')
- {
- uint newN = n;
- if (*p != '\0')
- {
- if (*p >= '0' && *p <= '9')
- {
- newN += (uint)(*p - '0');
- }
- else
- {
- if (*p >= 'A' && *p <= 'F')
- {
- newN += (uint)((*p - 'A') + 10);
- }
- else
- {
- Debug.Assert(*p >= 'a' && *p <= 'f');
- newN += (uint)((*p - 'a') + 10);
- }
- }
- p++;
- }
-
- // Detect an overflow here...
- if (newN < n)
- {
- return false;
- }
- n = newN;
- }
- }
- value = n;
- return true;
- }
-
- private static unsafe bool HexNumberToUInt64(ref NumberBuffer number, ref ulong value)
- {
- int i = number.scale;
- if (i > UInt64Precision || i < number.precision)
- {
- return false;
- }
- char* p = number.digits;
- Debug.Assert(p != null);
-
- ulong n = 0;
- while (--i >= 0)
- {
- if (n > (0xFFFFFFFFFFFFFFFF / 16))
- {
- return false;
- }
- n *= 16;
- if (*p != '\0')
- {
- ulong newN = n;
- if (*p != '\0')
- {
- if (*p >= '0' && *p <= '9')
- {
- newN += (ulong)(*p - '0');
- }
- else
- {
- if (*p >= 'A' && *p <= 'F')
- {
- newN += (ulong)((*p - 'A') + 10);
- }
- else
- {
- Debug.Assert(*p >= 'a' && *p <= 'f');
- newN += (ulong)((*p - 'a') + 10);
- }
- }
- p++;
- }
-
- // Detect an overflow here...
- if (newN < n)
- {
- return false;
- }
- n = newN;
- }
- }
- value = n;
- return true;
- }
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 15
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 31
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 47
+ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 63
+ 0xFF, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 79
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 95
+ 0xFF, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 111
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 127
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 143
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 159
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 175
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 191
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 207
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 223
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 239
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF // 255
+ };
private static unsafe bool NumberToInt32(ref NumberBuffer number, ref int value)
{
@@ -173,7 +75,7 @@ namespace System
n *= 10;
if (*p != '\0')
{
- n += (int)(*p++ - '0');
+ n += (*p++ - '0');
}
}
if (number.sign)
@@ -214,7 +116,7 @@ namespace System
n *= 10;
if (*p != '\0')
{
- n += (int)(*p++ - '0');
+ n += (*p++ - '0');
}
}
if (number.sign)
@@ -300,104 +202,147 @@ namespace System
return true;
}
- internal unsafe static int ParseInt32(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info)
+ internal static int ParseInt32(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info)
{
- NumberBuffer number = default;
- int i = 0;
-
- StringToNumber(s, style, ref number, info, false);
-
- if ((style & NumberStyles.AllowHexSpecifier) != 0)
+ if ((styles & ~NumberStyles.Integer) == 0)
{
- if (!HexNumberToInt32(ref number, ref i))
+ // Optimized path for the common case of anything that's allowed for integer style.
+ bool overflow = false;
+ if (!TryParseInt32IntegerStyle(value, styles, info, out int intResult, ref overflow))
{
- throw new OverflowException(SR.Overflow_Int32);
+ ThrowOverflowOrFormatException(overflow, nameof(SR.Overflow_Int32));
}
+ return intResult;
}
- else
+
+ if ((styles & NumberStyles.AllowHexSpecifier) != 0)
{
- if (!NumberToInt32(ref number, ref i))
+ bool overflow = false;
+ if (!TryParseUInt32HexNumberStyle(value, styles, info, out uint hexResult, ref overflow))
{
- throw new OverflowException(SR.Overflow_Int32);
+ ThrowOverflowOrFormatException(overflow, nameof(SR.Overflow_Int32));
}
+ return (int)hexResult;
}
- return i;
- }
- internal unsafe static long ParseInt64(ReadOnlySpan<char> value, NumberStyles options, NumberFormatInfo numfmt)
- {
NumberBuffer number = default;
- long i = 0;
-
- StringToNumber(value, options, ref number, numfmt, false);
+ int result = 0;
+ StringToNumber(value, styles, ref number, info, false);
+ if (!NumberToInt32(ref number, ref result))
+ {
+ ThrowOverflowOrFormatException(overflow: true, nameof(SR.Overflow_Int32));
+ }
+ return result;
+ }
- if ((options & NumberStyles.AllowHexSpecifier) != 0)
+ internal static long ParseInt64(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info)
+ {
+ if ((styles & ~NumberStyles.Integer) == 0)
{
- if (!HexNumberToInt64(ref number, ref i))
+ // Optimized path for the common case of anything that's allowed for integer style.
+ bool overflow = false;
+ if (!TryParseInt64IntegerStyle(value, styles, info, out long intResult, ref overflow))
{
- throw new OverflowException(SR.Overflow_Int64);
+ ThrowOverflowOrFormatException(overflow, nameof(SR.Overflow_Int64));
}
+ return intResult;
}
- else
+
+ if ((styles & NumberStyles.AllowHexSpecifier) != 0)
{
- if (!NumberToInt64(ref number, ref i))
+ bool overflow = false;
+ if (!TryParseUInt64HexNumberStyle(value, styles, info, out ulong hexResult, ref overflow))
{
- throw new OverflowException(SR.Overflow_Int64);
+ ThrowOverflowOrFormatException(overflow, nameof(SR.Overflow_Int64));
}
+ return (long)hexResult;
}
- return i;
- }
- internal unsafe static uint ParseUInt32(ReadOnlySpan<char> value, NumberStyles options, NumberFormatInfo numfmt)
- {
NumberBuffer number = default;
- uint i = 0;
+ long result = 0;
+ StringToNumber(value, styles, ref number, info, false);
+ if (!NumberToInt64(ref number, ref result))
+ {
+ ThrowOverflowOrFormatException(overflow: true, nameof(SR.Overflow_Int64));
+ }
+ return result;
+ }
- StringToNumber(value, options, ref number, numfmt, false);
+ internal static uint ParseUInt32(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info)
+ {
+ uint result = 0;
- if ((options & NumberStyles.AllowHexSpecifier) != 0)
+ if ((styles & ~NumberStyles.Integer) == 0)
{
- if (!HexNumberToUInt32(ref number, ref i))
+ // Optimized path for the common case of anything that's allowed for integer style.
+ bool overflow = false;
+ if (!TryParseUInt32IntegerStyle(value, styles, info, out result, ref overflow))
{
- throw new OverflowException(SR.Overflow_UInt32);
+ ThrowOverflowOrFormatException(overflow, nameof(SR.Overflow_UInt32));
}
+ return result;
}
- else
+
+ if ((styles & NumberStyles.AllowHexSpecifier) != 0)
{
- if (!NumberToUInt32(ref number, ref i))
+ bool overflow = false;
+ if (!TryParseUInt32HexNumberStyle(value, styles, info, out result, ref overflow))
{
- throw new OverflowException(SR.Overflow_UInt32);
+ ThrowOverflowOrFormatException(overflow, nameof(SR.Overflow_UInt32));
}
+ return result;
}
- return i;
+ NumberBuffer number = default;
+ StringToNumber(value, styles, ref number, info, false);
+ if (!NumberToUInt32(ref number, ref result))
+ {
+ ThrowOverflowOrFormatException(overflow: true, nameof(SR.Overflow_UInt32));
+ }
+ return result;
}
- internal unsafe static ulong ParseUInt64(ReadOnlySpan<char> value, NumberStyles options, NumberFormatInfo numfmt)
+ internal static ulong ParseUInt64(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info)
{
- NumberBuffer number = default;
- ulong i = 0;
+ ulong result = 0;
- StringToNumber(value, options, ref number, numfmt, false);
- if ((options & NumberStyles.AllowHexSpecifier) != 0)
+ if ((styles & ~NumberStyles.Integer) == 0)
{
- if (!HexNumberToUInt64(ref number, ref i))
+ // Optimized path for the common case of anything that's allowed for integer style.
+ bool overflow = false;
+ if (!TryParseUInt64IntegerStyle(value, styles, info, out result, ref overflow))
{
- throw new OverflowException(SR.Overflow_UInt64);
+ ThrowOverflowOrFormatException(overflow, nameof(SR.Overflow_UInt64));
}
+ return result;
}
- else
+
+ if ((styles & NumberStyles.AllowHexSpecifier) != 0)
{
- if (!NumberToUInt64(ref number, ref i))
+ bool overflow = false;
+ if (!TryParseUInt64HexNumberStyle(value, styles, info, out result, ref overflow))
{
- throw new OverflowException(SR.Overflow_UInt64);
+ ThrowOverflowOrFormatException(overflow, nameof(SR.Overflow_UInt64));
}
+ return result;
}
- return i;
+
+ NumberBuffer number = default;
+ StringToNumber(value, styles, ref number, info, false);
+ if (!NumberToUInt64(ref number, ref result))
+ {
+ ThrowOverflowOrFormatException(overflow: true, nameof(SR.Overflow_UInt64));
+ }
+ return result;
}
- private unsafe static bool ParseNumber(ref char* str, NumberStyles options, ref NumberBuffer number, NumberFormatInfo numfmt, bool parseDecimal)
+ private static unsafe bool ParseNumber(ref char* str, char* strEnd, NumberStyles styles, ref NumberBuffer number, NumberFormatInfo info, bool parseDecimal)
{
+ Debug.Assert(str != null);
+ Debug.Assert(strEnd != null);
+ Debug.Assert(str <= strEnd);
+ Debug.Assert((styles & NumberStyles.AllowHexSpecifier) == 0);
+
const int StateSign = 0x0001;
const int StateParens = 0x0002;
const int StateDigits = 0x0004;
@@ -412,44 +357,44 @@ namespace System
string currSymbol = null; // currency symbol from NumberFormatInfo.
bool parsingCurrency = false;
- if ((options & NumberStyles.AllowCurrencySymbol) != 0)
+ if ((styles & NumberStyles.AllowCurrencySymbol) != 0)
{
- currSymbol = numfmt.CurrencySymbol;
+ currSymbol = info.CurrencySymbol;
// The idea here is to match the currency separators and on failure match the number separators to keep the perf of VB's IsNumeric fast.
// The values of decSep are setup to use the correct relevant separator (currency in the if part and decimal in the else part).
- decSep = numfmt.CurrencyDecimalSeparator;
- groupSep = numfmt.CurrencyGroupSeparator;
+ decSep = info.CurrencyDecimalSeparator;
+ groupSep = info.CurrencyGroupSeparator;
parsingCurrency = true;
}
else
{
- decSep = numfmt.NumberDecimalSeparator;
- groupSep = numfmt.NumberGroupSeparator;
+ decSep = info.NumberDecimalSeparator;
+ groupSep = info.NumberGroupSeparator;
}
int state = 0;
char* p = str;
- char ch = *p;
+ char ch = p < strEnd ? *p : '\0';
char* next;
while (true)
{
// Eat whitespace unless we've found a sign which isn't followed by a currency symbol.
// "-Kr 1231.47" is legal but "- 1231.47" is not.
- if (!IsWhite(ch) || (options & NumberStyles.AllowLeadingWhite) == 0 || ((state & StateSign) != 0 && ((state & StateCurrency) == 0 && numfmt.NumberNegativePattern != 2)))
+ if (!IsWhite(ch) || (styles & NumberStyles.AllowLeadingWhite) == 0 || ((state & StateSign) != 0 && ((state & StateCurrency) == 0 && info.NumberNegativePattern != 2)))
{
- if ((((options & NumberStyles.AllowLeadingSign) != 0) && (state & StateSign) == 0) && ((next = MatchChars(p, numfmt.PositiveSign)) != null || ((next = MatchChars(p, numfmt.NegativeSign)) != null && (number.sign = true))))
+ if ((((styles & NumberStyles.AllowLeadingSign) != 0) && (state & StateSign) == 0) && ((next = MatchChars(p, strEnd, info.PositiveSign)) != null || ((next = MatchChars(p, strEnd, info.NegativeSign)) != null && (number.sign = true))))
{
state |= StateSign;
p = next - 1;
}
- else if (ch == '(' && ((options & NumberStyles.AllowParentheses) != 0) && ((state & StateSign) == 0))
+ else if (ch == '(' && ((styles & NumberStyles.AllowParentheses) != 0) && ((state & StateSign) == 0))
{
state |= StateSign | StateParens;
number.sign = true;
}
- else if (currSymbol != null && (next = MatchChars(p, currSymbol)) != null)
+ else if (currSymbol != null && (next = MatchChars(p, strEnd, currSymbol)) != null)
{
state |= StateCurrency;
currSymbol = null;
@@ -462,13 +407,13 @@ namespace System
break;
}
}
- ch = *++p;
+ ch = ++p < strEnd ? *p : '\0';
}
int digCount = 0;
int digEnd = 0;
while (true)
{
- if ((ch >= '0' && ch <= '9') || (((options & NumberStyles.AllowHexSpecifier) != 0) && ((ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'))))
+ if (IsDigit(ch))
{
state |= StateDigits;
@@ -493,12 +438,12 @@ namespace System
number.scale--;
}
}
- else if (((options & NumberStyles.AllowDecimalPoint) != 0) && ((state & StateDecimal) == 0) && ((next = MatchChars(p, decSep)) != null || ((parsingCurrency) && (state & StateCurrency) == 0) && (next = MatchChars(p, numfmt.NumberDecimalSeparator)) != null))
+ else if (((styles & NumberStyles.AllowDecimalPoint) != 0) && ((state & StateDecimal) == 0) && ((next = MatchChars(p, strEnd, decSep)) != null || ((parsingCurrency) && (state & StateCurrency) == 0) && (next = MatchChars(p, strEnd, info.NumberDecimalSeparator)) != null))
{
state |= StateDecimal;
p = next - 1;
}
- else if (((options & NumberStyles.AllowThousands) != 0) && ((state & StateDigits) != 0) && ((state & StateDecimal) == 0) && ((next = MatchChars(p, groupSep)) != null || ((parsingCurrency) && (state & StateCurrency) == 0) && (next = MatchChars(p, numfmt.NumberGroupSeparator)) != null))
+ else if (((styles & NumberStyles.AllowThousands) != 0) && ((state & StateDigits) != 0) && ((state & StateDecimal) == 0) && ((next = MatchChars(p, strEnd, groupSep)) != null || ((parsingCurrency) && (state & StateCurrency) == 0) && (next = MatchChars(p, strEnd, info.NumberGroupSeparator)) != null))
{
p = next - 1;
}
@@ -506,7 +451,7 @@ namespace System
{
break;
}
- ch = *++p;
+ ch = ++p < strEnd ? *p : '\0';
}
bool negExp = false;
@@ -514,35 +459,35 @@ namespace System
number.digits[digEnd] = '\0';
if ((state & StateDigits) != 0)
{
- if ((ch == 'E' || ch == 'e') && ((options & NumberStyles.AllowExponent) != 0))
+ if ((ch == 'E' || ch == 'e') && ((styles & NumberStyles.AllowExponent) != 0))
{
char* temp = p;
- ch = *++p;
- if ((next = MatchChars(p, numfmt.positiveSign)) != null)
+ ch = ++p < strEnd ? *p : '\0';
+ if ((next = MatchChars(p, strEnd, info.positiveSign)) != null)
{
- ch = *(p = next);
+ ch = (p = next) < strEnd ? *p : '\0';
}
- else if ((next = MatchChars(p, numfmt.negativeSign)) != null)
+ else if ((next = MatchChars(p, strEnd, info.negativeSign)) != null)
{
- ch = *(p = next);
+ ch = (p = next) < strEnd ? *p : '\0';
negExp = true;
}
- if (ch >= '0' && ch <= '9')
+ if (IsDigit(ch))
{
int exp = 0;
do
{
exp = exp * 10 + (ch - '0');
- ch = *++p;
+ ch = ++p < strEnd ? *p : '\0';
if (exp > 1000)
{
exp = 9999;
- while (ch >= '0' && ch <= '9')
+ while (IsDigit(ch))
{
- ch = *++p;
+ ch = ++p < strEnd ? *p : '\0';
}
}
- } while (ch >= '0' && ch <= '9');
+ } while (IsDigit(ch));
if (negExp)
{
exp = -exp;
@@ -552,14 +497,14 @@ namespace System
else
{
p = temp;
- ch = *p;
+ ch = p < strEnd ? *p : '\0';
}
}
while (true)
{
- if (!IsWhite(ch) || (options & NumberStyles.AllowTrailingWhite) == 0)
+ if (!IsWhite(ch) || (styles & NumberStyles.AllowTrailingWhite) == 0)
{
- if (((options & NumberStyles.AllowTrailingSign) != 0 && ((state & StateSign) == 0)) && ((next = MatchChars(p, numfmt.PositiveSign)) != null || (((next = MatchChars(p, numfmt.NegativeSign)) != null) && (number.sign = true))))
+ if (((styles & NumberStyles.AllowTrailingSign) != 0 && ((state & StateSign) == 0)) && ((next = MatchChars(p, strEnd, info.PositiveSign)) != null || (((next = MatchChars(p, strEnd, info.NegativeSign)) != null) && (number.sign = true))))
{
state |= StateSign;
p = next - 1;
@@ -568,7 +513,7 @@ namespace System
{
state &= ~StateParens;
}
- else if (currSymbol != null && (next = MatchChars(p, currSymbol)) != null)
+ else if (currSymbol != null && (next = MatchChars(p, strEnd, currSymbol)) != null)
{
currSymbol = null;
p = next - 1;
@@ -578,7 +523,7 @@ namespace System
break;
}
}
- ch = *++p;
+ ch = ++p < strEnd ? *p : '\0';
}
if ((state & StateParens) == 0)
{
@@ -601,206 +546,1109 @@ namespace System
return false;
}
- internal unsafe static bool TryParseInt32(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out int result)
+ internal static bool TryParseInt32(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out int result)
{
- NumberBuffer number = default;
+ if ((styles & ~NumberStyles.Integer) == 0)
+ {
+ // Optimized path for the common case of anything that's allowed for integer style.
+ bool overflow = false;
+ return TryParseInt32IntegerStyle(value, styles, info, out result, ref overflow);
+ }
+
result = 0;
- if (!TryStringToNumber(s, style, ref number, info, false))
+ if ((styles & NumberStyles.AllowHexSpecifier) != 0)
{
- return false;
+ bool overflow = false;
+ return TryParseUInt32HexNumberStyle(value, styles, info, out Unsafe.As<int, uint>(ref result), ref overflow);
}
- if ((style & NumberStyles.AllowHexSpecifier) != 0)
+ NumberBuffer number = default;
+ return
+ TryStringToNumber(value, styles, ref number, info, false) &&
+ NumberToInt32(ref number, ref result);
+ }
+
+ /// <summary>Parses int limited to styles that make up NumberStyles.Integer.</summary>
+ private static bool TryParseInt32IntegerStyle(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out int result, ref bool failureIsOverflow)
+ {
+ Debug.Assert((styles & ~NumberStyles.Integer) == 0, "Only handles subsets of Integer format");
+ Debug.Assert(!failureIsOverflow, $"failureIsOverflow should have been initialized to false");
+
+ if ((uint)value.Length < 1) goto FalseExit;
+
+ bool overflow = false;
+ int sign = 1;
+ int index = 0;
+ int num = value[0];
+
+ // Skip past any whitespace at the beginning.
+ if ((styles & NumberStyles.AllowLeadingWhite) != 0 && IsWhite(num))
{
- if (!HexNumberToInt32(ref number, ref result))
+ do
{
- return false;
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
}
+ while (IsWhite(num));
}
- else
+
+ // Parse leading sign.
+ if ((styles & NumberStyles.AllowLeadingSign) != 0)
{
- if (!NumberToInt32(ref number, ref result))
+ string positiveSign = info.PositiveSign, negativeSign = info.NegativeSign;
+
+ if (positiveSign == "+" && negativeSign == "-")
{
- return false;
+ if (num == '-')
+ {
+ sign = -1;
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ else if (num == '+')
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ }
+ else
+ {
+ value = value.Slice(index);
+ index = 0;
+ if (!string.IsNullOrEmpty(positiveSign) && value.StartsWith(positiveSign))
+ {
+ index += positiveSign.Length;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ else if (!string.IsNullOrEmpty(negativeSign) && value.StartsWith(negativeSign))
+ {
+ sign = -1;
+ index += negativeSign.Length;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ }
+ }
+
+ int answer = 0;
+
+ if (IsDigit(num))
+ {
+ // Skip past leading zeros.
+ if (num == '0')
+ {
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ } while (num == '0');
+ if (!IsDigit(num)) goto HasTrailingChars;
+ }
+
+ // Parse most digits, up to the potential for overflow, which can't happen until after 9 digits.
+ answer = num - '0'; // first digit
+ index++;
+ for (int i = 0; i < 8; i++) // next 8 digits can't overflow
+ {
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ if (!IsDigit(num)) goto HasTrailingChars;
+ index++;
+ answer = 10 * answer + num - '0';
+ }
+
+ // Potential overflow now processing the 10th digit.
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ if (!IsDigit(num)) goto HasTrailingChars;
+ index++;
+ if (answer > int.MaxValue / 10)
+ {
+ overflow = true;
+ }
+ answer = answer * 10 + num - '0';
+ if ((uint)answer > (uint)int.MaxValue + (-1 * sign + 1) / 2)
+ {
+ overflow = true;
+ }
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+
+ // At this point, we're either overflowing or hitting a formatting error.
+ // Format errors take precedence for compatibility.
+ num = value[index];
+ while (IsDigit(num))
+ {
+ overflow = true;
+ index++;
+ if ((uint)index >= (uint)value.Length)
+ goto DoneAtEndButPotentialOverflow;
+ num = value[index];
}
+ goto HasTrailingChars;
+ }
+
+ FalseExit: // parsing failed
+ result = 0;
+ return false;
+
+ DoneAtEndButPotentialOverflow:
+ if (overflow)
+ {
+ failureIsOverflow = true;
+ goto FalseExit;
}
+ result = answer * sign;
return true;
+
+ HasTrailingChars: // we've successfully parsed, but there are still remaining characters in the span
+ // Skip past trailing whitespace, then past trailing zeros, and if anything else remains, fail.
+ if (IsWhite(num))
+ {
+ if ((styles & NumberStyles.AllowTrailingWhite) == 0) goto FalseExit;
+ for (index++; index < value.Length; index++)
+ {
+ if (!IsWhite(value[index])) break;
+ }
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ }
+
+ if (!TrailingZeros(value, index)) goto FalseExit;
+
+ goto DoneAtEndButPotentialOverflow;
}
- internal unsafe static bool TryParseInt64(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out long result)
+ /// <summary>Parses long inputs limited to styles that make up NumberStyles.Integer.</summary>
+ private static bool TryParseInt64IntegerStyle(
+ ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out long result, ref bool failureIsOverflow)
{
- NumberBuffer number = default;
- result = 0;
+ Debug.Assert((styles & ~NumberStyles.Integer) == 0, "Only handles subsets of Integer format");
+ Debug.Assert(!failureIsOverflow, $"failureIsOverflow should have been initialized to false");
+
+ if ((uint)value.Length < 1) goto FalseExit;
- if (!TryStringToNumber(s, style, ref number, info, false))
+ bool overflow = false;
+ int sign = 1;
+ int index = 0;
+ int num = value[0];
+
+ // Skip past any whitespace at the beginning.
+ if ((styles & NumberStyles.AllowLeadingWhite) != 0 && IsWhite(num))
{
- return false;
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ while (IsWhite(num));
}
- if ((style & NumberStyles.AllowHexSpecifier) != 0)
+ // Parse leading sign.
+ if ((styles & NumberStyles.AllowLeadingSign) != 0)
{
- if (!HexNumberToInt64(ref number, ref result))
+ string positiveSign = info.PositiveSign, negativeSign = info.NegativeSign;
+
+ if (positiveSign == "+" && negativeSign == "-")
{
- return false;
+ if (num == '-')
+ {
+ sign = -1;
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ else if (num == '+')
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ }
+ else
+ {
+ value = value.Slice(index);
+ index = 0;
+ if (!string.IsNullOrEmpty(positiveSign) && value.StartsWith(positiveSign))
+ {
+ index += positiveSign.Length;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ else if (!string.IsNullOrEmpty(negativeSign) && value.StartsWith(negativeSign))
+ {
+ sign = -1;
+ index += negativeSign.Length;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
}
}
- else
+
+ long answer = 0;
+
+ if (IsDigit(num))
{
- if (!NumberToInt64(ref number, ref result))
+ // Skip past leading zeros.
+ if (num == '0')
{
- return false;
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ } while (num == '0');
+ if (!IsDigit(num)) goto HasTrailingChars;
+ }
+
+ // Parse most digits, up to the potential for overflow, which can't happen until after 18 digits.
+ answer = num - '0'; // first digit
+ index++;
+ for (int i = 0; i < 17; i++) // next 17 digits can't overflow
+ {
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ if (!IsDigit(num)) goto HasTrailingChars;
+ index++;
+ answer = 10 * answer + num - '0';
+ }
+
+ // Potential overflow now processing the 19th digit.
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ if (!IsDigit(num)) goto HasTrailingChars;
+ index++;
+ if (answer > long.MaxValue / 10)
+ {
+ overflow = true;
+ }
+ answer = answer * 10 + num - '0';
+ if ((ulong)answer > (ulong)long.MaxValue + (ulong)((-1 * sign + 1) / 2)) // + sign => 0, - sign => 1
+ {
+ overflow = true;
}
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+
+ // At this point, we're either overflowing or hitting a formatting error.
+ // Format errors take precedence for compatibility.
+ num = value[index];
+ while (IsDigit(num))
+ {
+ overflow = true;
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ }
+ goto HasTrailingChars;
+ }
+
+ FalseExit: // parsing failed
+ result = 0;
+ return false;
+
+ DoneAtEndButPotentialOverflow:
+ if (overflow)
+ {
+ failureIsOverflow = true;
+ goto FalseExit;
}
+ result = answer * sign;
return true;
+
+ HasTrailingChars: // we've successfully parsed, but there are still remaining characters in the span
+ // Skip past trailing whitespace, then past trailing zeros, and if anything else remains, fail.
+ if (IsWhite(num))
+ {
+ if ((styles & NumberStyles.AllowTrailingWhite) == 0) goto FalseExit;
+ for (index++; index < value.Length; index++)
+ {
+ if (!IsWhite(value[index])) break;
+ }
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ }
+
+ if (!TrailingZeros(value, index)) goto FalseExit;
+
+ goto DoneAtEndButPotentialOverflow;
}
- internal unsafe static bool TryParseUInt32(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out uint result)
+ internal static bool TryParseInt64(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out long result)
{
+ if ((styles & ~NumberStyles.Integer) == 0)
+ {
+ // Optimized path for the common case of anything that's allowed for integer style.
+ bool overflow = false;
+ return TryParseInt64IntegerStyle(value, styles, info, out result, ref overflow);
+ }
+
+ result = 0;
+
+ if ((styles & NumberStyles.AllowHexSpecifier) != 0)
+ {
+ bool overflow = false;
+ return TryParseUInt64HexNumberStyle(value, styles, info, out Unsafe.As<long, ulong>(ref result), ref overflow);
+ }
+
+ NumberBuffer number = default;
+ return
+ TryStringToNumber(value, styles, ref number, info, false) &&
+ NumberToInt64(ref number, ref result);
+ }
+
+ internal static bool TryParseUInt32(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out uint result)
+ {
+ if ((styles & ~NumberStyles.Integer) == 0)
+ {
+ // Optimized path for the common case of anything that's allowed for integer style.
+ bool overflow = false;
+ return TryParseUInt32IntegerStyle(value, styles, info, out result, ref overflow);
+ }
+
+ if ((styles & NumberStyles.AllowHexSpecifier) != 0)
+ {
+ bool overflow = false;
+ return TryParseUInt32HexNumberStyle(value, styles, info, out result, ref overflow);
+ }
+
NumberBuffer number = default;
result = 0;
+ return
+ TryStringToNumber(value, styles, ref number, info, false) &&
+ NumberToUInt32(ref number, ref result);
+ }
+
+ /// <summary>Parses uint limited to styles that make up NumberStyles.Integer.</summary>
+ private static bool TryParseUInt32IntegerStyle(
+ ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out uint result, ref bool failureIsOverflow)
+ {
+ Debug.Assert((styles & ~NumberStyles.Integer) == 0, "Only handles subsets of Integer format");
+ Debug.Assert(!failureIsOverflow, $"failureIsOverflow should have been initialized to false");
+
+ if ((uint)value.Length < 1) goto FalseExit;
- if (!TryStringToNumber(s, style, ref number, info, false))
+ bool overflow = false;
+ bool hasNegativeSign = false;
+ int index = 0;
+ int num = value[0];
+
+ // Skip past any whitespace at the beginning.
+ if ((styles & NumberStyles.AllowLeadingWhite) != 0 && IsWhite(num))
{
- return false;
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ while (IsWhite(num));
}
- if ((style & NumberStyles.AllowHexSpecifier) != 0)
+ // Parse leading sign.
+ if ((styles & NumberStyles.AllowLeadingSign) != 0)
{
- if (!HexNumberToUInt32(ref number, ref result))
+ string positiveSign = info.PositiveSign, negativeSign = info.NegativeSign;
+
+ if (positiveSign == "+" && negativeSign == "-")
{
- return false;
+ if (num == '+')
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ else if (num == '-')
+ {
+ hasNegativeSign = true;
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ }
+ else
+ {
+ value = value.Slice(index);
+ index = 0;
+ if (!string.IsNullOrEmpty(positiveSign) && value.StartsWith(positiveSign))
+ {
+ index += positiveSign.Length;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ else if (!string.IsNullOrEmpty(negativeSign) && value.StartsWith(negativeSign))
+ {
+ hasNegativeSign = true;
+ index += negativeSign.Length;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
}
}
- else
+
+ int answer = 0;
+
+ if (IsDigit(num))
{
- if (!NumberToUInt32(ref number, ref result))
+ // Skip past leading zeros.
+ if (num == '0')
{
- return false;
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ } while (num == '0');
+ if (!IsDigit(num)) goto HasTrailingChars;
+ }
+
+ // Parse most digits, up to the potential for overflow, which can't happen until after 9 digits.
+ answer = num - '0'; // first digit
+ index++;
+ for (int i = 0; i < 8; i++) // next 8 digits can't overflow
+ {
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ if (!IsDigit(num)) goto HasTrailingChars;
+ index++;
+ answer = 10 * answer + num - '0';
+ }
+
+ // Potential overflow now processing the 10th digit.
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ if (!IsDigit(num)) goto HasTrailingChars;
+ index++;
+ if ((uint)answer > uint.MaxValue / 10 || ((uint)answer == uint.MaxValue / 10 && num > '5'))
+ {
+ overflow = true;
}
+ answer = answer * 10 + num - '0';
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+
+ // At this point, we're either overflowing or hitting a formatting error.
+ // Format errors take precedence for compatibility.
+ num = value[index];
+ while (IsDigit(num))
+ {
+ overflow = true;
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ }
+ goto HasTrailingChars;
}
+
+ FalseExit: // parsing failed
+ result = 0;
+ return false;
+
+ DoneAtEndButPotentialOverflow:
+ if (overflow || (hasNegativeSign && answer != 0))
+ {
+ failureIsOverflow = true;
+ goto FalseExit;
+ }
+ result = (uint)answer;
return true;
+
+ HasTrailingChars: // we've successfully parsed, but there are still remaining characters in the span
+ // Skip past trailing whitespace, then past trailing zeros, and if anything else remains, fail.
+ if (IsWhite(num))
+ {
+ if ((styles & NumberStyles.AllowTrailingWhite) == 0) goto FalseExit;
+ for (index++; index < value.Length; index++)
+ {
+ if (!IsWhite(value[index])) break;
+ }
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ }
+
+ if (!TrailingZeros(value, index)) goto FalseExit;
+
+ goto DoneAtEndButPotentialOverflow;
}
- internal unsafe static bool TryParseUInt64(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out ulong result)
+ /// <summary>Parses uint limited to styles that make up NumberStyles.HexNumber.</summary>
+ private static bool TryParseUInt32HexNumberStyle(
+ ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out uint result, ref bool failureIsOverflow)
+ {
+ Debug.Assert((styles & ~NumberStyles.HexNumber) == 0, "Only handles subsets of HexNumber format");
+ Debug.Assert(!failureIsOverflow, $"failureIsOverflow should have been initialized to false");
+
+ if ((uint)value.Length < 1) goto FalseExit;
+
+ bool overflow = false;
+ int index = 0;
+ int num = value[0];
+ int numValue = 0;
+
+ // Skip past any whitespace at the beginning.
+ if ((styles & NumberStyles.AllowLeadingWhite) != 0 && IsWhite(num))
+ {
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ while (IsWhite(num));
+ }
+
+ int answer = 0;
+ int[] charToHexLookup = s_charToHexLookup;
+
+ if ((uint)num < (uint)charToHexLookup.Length && charToHexLookup[num] != 0xFF)
+ {
+ // Skip past leading zeros.
+ if (num == '0')
+ {
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEnd;
+ num = value[index];
+ } while (num == '0');
+ if ((uint)num >= (uint)charToHexLookup.Length || charToHexLookup[num] == 0xFF) goto HasTrailingChars;
+ }
+
+ // Parse up through 8 digits, as no overflow is possible
+ answer = charToHexLookup[num]; // first digit
+ index++;
+ for (int i = 0; i < 7; i++) // next 7 digits can't overflow
+ {
+ if ((uint)index >= (uint)value.Length) goto DoneAtEnd;
+ num = value[index];
+ if ((uint)num >= (uint)charToHexLookup.Length || (numValue = charToHexLookup[num]) == 0xFF) goto HasTrailingChars;
+ index++;
+ answer = 16 * answer + numValue;
+ }
+
+ // If there's another digit, it's an overflow.
+ if ((uint)index >= (uint)value.Length) goto DoneAtEnd;
+ num = value[index];
+ if ((uint)num >= (uint)charToHexLookup.Length || (numValue = charToHexLookup[num]) == 0xFF) goto HasTrailingChars;
+ index++;
+ overflow = true;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+
+ // At this point, we're either overflowing or hitting a formatting error.
+ // Format errors take precedence for compatibility. Read through any remaining digits.
+ num = value[index];
+ while ((uint)num < (uint)charToHexLookup.Length && charToHexLookup[num] != 0xFF)
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ }
+ goto HasTrailingChars;
+ }
+
+ FalseExit: // parsing failed
+ result = 0;
+ return false;
+
+ DoneAtEndButPotentialOverflow:
+ if (overflow)
+ {
+ failureIsOverflow = true;
+ goto FalseExit;
+ }
+ DoneAtEnd:
+ result = (uint)answer;
+ return true;
+
+ HasTrailingChars: // we've successfully parsed, but there are still remaining characters in the span
+ // Skip past trailing whitespace, then past trailing zeros, and if anything else remains, fail.
+ if (IsWhite(num))
+ {
+ if ((styles & NumberStyles.AllowTrailingWhite) == 0) goto FalseExit;
+ for (index++; index < value.Length; index++)
+ {
+ if (!IsWhite(value[index])) break;
+ }
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ }
+
+ if (!TrailingZeros(value, index)) goto FalseExit;
+
+ goto DoneAtEndButPotentialOverflow;
+ }
+
+ internal static bool TryParseUInt64(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out ulong result)
{
+ if ((styles & ~NumberStyles.Integer) == 0)
+ {
+ // Optimized path for the common case of anything that's allowed for integer style.
+ bool overflow = false;
+ return TryParseUInt64IntegerStyle(value, styles, info, out result, ref overflow);
+ }
+
+ if ((styles & NumberStyles.AllowHexSpecifier) != 0)
+ {
+ bool overflow = false;
+ return TryParseUInt64HexNumberStyle(value, styles, info, out result, ref overflow);
+ }
+
NumberBuffer number = default;
result = 0;
+ return
+ TryStringToNumber(value, styles, ref number, info, false) &&
+ NumberToUInt64(ref number, ref result);
+ }
- if (!TryStringToNumber(s, style, ref number, info, false))
+ /// <summary>Parses ulong limited to styles that make up NumberStyles.Integer.</summary>
+ private static bool TryParseUInt64IntegerStyle(
+ ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out ulong result, ref bool failureIsOverflow)
+ {
+ Debug.Assert((styles & ~NumberStyles.Integer) == 0, "Only handles subsets of Integer format");
+ Debug.Assert(!failureIsOverflow, $"failureIsOverflow should have been initialized to false");
+
+ if ((uint)value.Length < 1) goto FalseExit;
+
+ bool overflow = false;
+ bool hasNegativeSign = false;
+ int index = 0;
+ int num = value[0];
+
+ // Skip past any whitespace at the beginning.
+ if ((styles & NumberStyles.AllowLeadingWhite) != 0 && IsWhite(num))
{
- return false;
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ while (IsWhite(num));
}
- if ((style & NumberStyles.AllowHexSpecifier) != 0)
+ // Parse leading sign.
+ if ((styles & NumberStyles.AllowLeadingSign) != 0)
{
- if (!HexNumberToUInt64(ref number, ref result))
+ string positiveSign = info.PositiveSign, negativeSign = info.NegativeSign;
+
+ if (positiveSign == "+" && negativeSign == "-")
{
- return false;
+ if (num == '+')
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ else if (num == '-')
+ {
+ hasNegativeSign = true;
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ }
+ else
+ {
+ value = value.Slice(index);
+ index = 0;
+ if (!string.IsNullOrEmpty(positiveSign) && value.StartsWith(positiveSign))
+ {
+ index += positiveSign.Length;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ else if (!string.IsNullOrEmpty(negativeSign) && value.StartsWith(negativeSign))
+ {
+ hasNegativeSign = true;
+ index += negativeSign.Length;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
}
}
- else
+
+ long answer = 0;
+
+ if (IsDigit(num))
{
- if (!NumberToUInt64(ref number, ref result))
+ // Skip past leading zeros.
+ if (num == '0')
{
- return false;
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ } while (num == '0');
+ if (!IsDigit(num)) goto HasTrailingChars;
+ }
+
+ // Parse most digits, up to the potential for overflow, which can't happen until after 19 digits.
+ answer = num - '0'; // first digit
+ index++;
+ for (int i = 0; i < 18; i++) // next 18 digits can't overflow
+ {
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ if (!IsDigit(num)) goto HasTrailingChars;
+ index++;
+ answer = 10 * answer + num - '0';
}
+
+ // Potential overflow now processing the 20th digit.
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ if (!IsDigit(num)) goto HasTrailingChars;
+ index++;
+ if ((ulong)answer > ulong.MaxValue / 10 || ((ulong)answer == ulong.MaxValue / 10 && num > '5'))
+ {
+ overflow = true;
+ }
+ answer = answer * 10 + num - '0';
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+
+ // At this point, we're either overflowing or hitting a formatting error.
+ // Format errors take precedence for compatibility.
+ num = value[index];
+ while (IsDigit(num))
+ {
+ overflow = true;
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ }
+ goto HasTrailingChars;
+ }
+
+ FalseExit: // parsing failed
+ result = 0;
+ return false;
+
+ DoneAtEndButPotentialOverflow:
+ if (overflow || (hasNegativeSign && answer != 0))
+ {
+ failureIsOverflow = true;
+ goto FalseExit;
+ }
+ result = (ulong)answer;
+ return true;
+
+ HasTrailingChars: // we've successfully parsed, but there are still remaining characters in the span
+ // Skip past trailing whitespace, then past trailing zeros, and if anything else remains, fail.
+ if (IsWhite(num))
+ {
+ if ((styles & NumberStyles.AllowTrailingWhite) == 0) goto FalseExit;
+ for (index++; index < value.Length; index++)
+ {
+ if (!IsWhite(value[index])) break;
+ }
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ }
+
+ if (!TrailingZeros(value, index)) goto FalseExit;
+
+ goto DoneAtEndButPotentialOverflow;
+ }
+
+ /// <summary>Parses ulong limited to styles that make up NumberStyles.HexNumber.</summary>
+ private static bool TryParseUInt64HexNumberStyle(
+ ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out ulong result, ref bool failureIsOverflow)
+ {
+ Debug.Assert((styles & ~NumberStyles.HexNumber) == 0, "Only handles subsets of HexNumber format");
+ Debug.Assert(!failureIsOverflow, $"failureIsOverflow should have been initialized to false");
+
+ if ((uint)value.Length < 1) goto FalseExit;
+
+ bool overflow = false;
+ int index = 0;
+ int num = value[0];
+ int numValue = 0;
+
+ // Skip past any whitespace at the beginning.
+ if ((styles & NumberStyles.AllowLeadingWhite) != 0 && IsWhite(num))
+ {
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto FalseExit;
+ num = value[index];
+ }
+ while (IsWhite(num));
+ }
+
+ long answer = 0;
+ int[] charToHexLookup = s_charToHexLookup;
+
+ if ((uint)num < (uint)charToHexLookup.Length && charToHexLookup[num] != 0xFF)
+ {
+ // Skip past leading zeros.
+ if (num == '0')
+ {
+ do
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEnd;
+ num = value[index];
+ } while (num == '0');
+ if ((uint)num >= (uint)charToHexLookup.Length || charToHexLookup[num] == 0xFF) goto HasTrailingChars;
+ }
+
+ // Parse up through 16 digits, as no overflow is possible
+ answer = charToHexLookup[num]; // first digit
+ index++;
+ for (int i = 0; i < 15; i++) // next 15 digits can't overflow
+ {
+ if ((uint)index >= (uint)value.Length) goto DoneAtEnd;
+ num = value[index];
+ if ((uint)num >= (uint)charToHexLookup.Length || (numValue = charToHexLookup[num]) == 0xFF) goto HasTrailingChars;
+ index++;
+ answer = 16 * answer + numValue;
+ }
+
+ // If there's another digit, it's an overflow.
+ if ((uint)index >= (uint)value.Length) goto DoneAtEnd;
+ num = value[index];
+ if ((uint)num >= (uint)charToHexLookup.Length || (numValue = charToHexLookup[num]) == 0xFF) goto HasTrailingChars;
+ index++;
+ overflow = true;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+
+ // At this point, we're either overflowing or hitting a formatting error.
+ // Format errors take precedence for compatibility. Read through any remaining digits.
+ num = value[index];
+ while ((uint)num < (uint)charToHexLookup.Length && charToHexLookup[num] != 0xFF)
+ {
+ index++;
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ num = value[index];
+ }
+ goto HasTrailingChars;
}
+
+ FalseExit: // parsing failed
+ result = 0;
+ return false;
+
+ DoneAtEndButPotentialOverflow:
+ if (overflow)
+ {
+ failureIsOverflow = true;
+ goto FalseExit;
+ }
+ DoneAtEnd:
+ result = (ulong)answer;
return true;
+
+ HasTrailingChars: // we've successfully parsed, but there are still remaining characters in the span
+ // Skip past trailing whitespace, then past trailing zeros, and if anything else remains, fail.
+ if (IsWhite(num))
+ {
+ if ((styles & NumberStyles.AllowTrailingWhite) == 0) goto FalseExit;
+ for (index++; index < value.Length; index++)
+ {
+ if (!IsWhite(value[index])) break;
+ }
+ if ((uint)index >= (uint)value.Length) goto DoneAtEndButPotentialOverflow;
+ }
+
+ if (!TrailingZeros(value, index)) goto FalseExit;
+
+ goto DoneAtEndButPotentialOverflow;
}
- internal unsafe static decimal ParseDecimal(ReadOnlySpan<char> value, NumberStyles options, NumberFormatInfo numfmt)
+ internal static decimal ParseDecimal(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info)
{
NumberBuffer number = default;
decimal result = 0;
- StringToNumber(value, options, ref number, numfmt, true);
+ StringToNumber(value, styles, ref number, info, true);
if (!NumberBufferToDecimal(ref number, ref result))
{
- throw new OverflowException(SR.Overflow_Decimal);
+ ThrowOverflowOrFormatException(overflow: true, nameof(SR.Overflow_Decimal));
}
return result;
}
- internal unsafe static double ParseDouble(ReadOnlySpan<char> value, NumberStyles options, NumberFormatInfo numfmt)
+ private static unsafe bool NumberBufferToDecimal(ref NumberBuffer number, ref decimal value)
+ {
+ char* p = number.digits;
+ int e = number.scale;
+ bool sign = number.sign;
+ uint c = *p;
+ if (c == 0)
+ {
+ // To avoid risking an app-compat issue with pre 4.5 (where some app was illegally using Reflection to examine the internal scale bits), we'll only force
+ // the scale to 0 if the scale was previously positive (previously, such cases were unparsable to a bug.)
+ value = new decimal(0, 0, 0, sign, (byte)Math.Clamp(-e, 0, 28));
+ return true;
+ }
+
+ if (e > DecimalPrecision)
+ return false;
+
+ ulong low64 = 0;
+ while (e > -28)
+ {
+ e--;
+ low64 *= 10;
+ low64 += c - '0';
+ c = *++p;
+ if (low64 >= ulong.MaxValue / 10)
+ break;
+ if (c == 0)
+ {
+ while (e > 0)
+ {
+ e--;
+ low64 *= 10;
+ if (low64 >= ulong.MaxValue / 10)
+ break;
+ }
+ break;
+ }
+ }
+
+ uint high = 0;
+ while ((e > 0 || (c != 0 && e > -28)) &&
+ (high < uint.MaxValue / 10 || (high == uint.MaxValue / 10 && (low64 < 0x99999999_99999999 || (low64 == 0x99999999_99999999 && c <= '5')))))
+ {
+ // multiply by 10
+ ulong tmpLow = (uint)low64 * 10UL;
+ ulong tmp64 = (uint)(low64 >> 32) * 10UL + (tmpLow >> 32);
+ low64 = (uint)tmpLow + (tmp64 << 32);
+ high = (uint)(tmp64 >> 32) + high * 10;
+
+ if (c != 0)
+ {
+ c -= '0';
+ low64 += c;
+ if (low64 < c)
+ high++;
+ c = *++p;
+ }
+ e--;
+ }
+
+ if (c >= '5')
+ {
+ // If the next digit is 5, round up if the number is odd or any following digit is non-zero
+ if (c == '5' && (low64 & 1) == 0)
+ {
+ c = *++p;
+ int count = 20; // Look at the next 20 digits to check to round
+ while (c == '0' && count != 0)
+ {
+ c = *++p;
+ count--;
+ }
+ if (c == 0 || count == 0)
+ goto NoRounding;// Do nothing
+ }
+
+ if (++low64 == 0 && ++high == 0)
+ {
+ low64 = 0x99999999_9999999A;
+ high = uint.MaxValue / 10;
+ e++;
+ }
+ }
+ NoRounding:
+
+ if (e > 0)
+ return false;
+
+ if (e <= -DecimalPrecision)
+ {
+ // Parsing a large scale zero can give you more precision than fits in the decimal.
+ // This should only happen for actual zeros or very small numbers that round to zero.
+ value = new decimal(0, 0, 0, sign, DecimalPrecision - 1);
+ }
+ else
+ {
+ value = new decimal((int)low64, (int)(low64 >> 32), (int)high, sign, (byte)-e);
+ }
+ return true;
+ }
+
+ internal static double ParseDouble(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info)
{
NumberBuffer number = default;
double d = 0;
- if (!TryStringToNumber(value, options, ref number, numfmt, false))
+ if (!TryStringToNumber(value, styles, ref number, info, false))
{
//If we failed TryStringToNumber, it may be from one of our special strings.
//Check the three with which we're concerned and rethrow if it's not one of
//those strings.
ReadOnlySpan<char> sTrim = value.Trim();
- if (StringSpanHelpers.Equals(sTrim, numfmt.PositiveInfinitySymbol))
+ if (sTrim.EqualsOrdinal(info.PositiveInfinitySymbol))
{
return double.PositiveInfinity;
}
- if (StringSpanHelpers.Equals(sTrim, numfmt.NegativeInfinitySymbol))
+ if (sTrim.EqualsOrdinal(info.NegativeInfinitySymbol))
{
return double.NegativeInfinity;
}
- if (StringSpanHelpers.Equals(sTrim, numfmt.NaNSymbol))
+ if (sTrim.EqualsOrdinal(info.NaNSymbol))
{
return double.NaN;
}
- throw new FormatException(SR.Format_InvalidString);
+ ThrowOverflowOrFormatException(overflow: false, null);
}
if (!NumberBufferToDouble(ref number, ref d))
{
- throw new OverflowException(SR.Overflow_Double);
+ ThrowOverflowOrFormatException(overflow: true, nameof(SR.Overflow_Double));
}
return d;
}
- internal unsafe static float ParseSingle(ReadOnlySpan<char> value, NumberStyles options, NumberFormatInfo numfmt)
+ internal static float ParseSingle(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info)
{
NumberBuffer number = default;
double d = 0;
- if (!TryStringToNumber(value, options, ref number, numfmt, false))
+ if (!TryStringToNumber(value, styles, ref number, info, false))
{
//If we failed TryStringToNumber, it may be from one of our special strings.
//Check the three with which we're concerned and rethrow if it's not one of
//those strings.
ReadOnlySpan<char> sTrim = value.Trim();
- if (StringSpanHelpers.Equals(sTrim, numfmt.PositiveInfinitySymbol))
+ if (sTrim.EqualsOrdinal(info.PositiveInfinitySymbol))
{
return float.PositiveInfinity;
}
- if (StringSpanHelpers.Equals(sTrim, numfmt.NegativeInfinitySymbol))
+ if (sTrim.EqualsOrdinal(info.NegativeInfinitySymbol))
{
return float.NegativeInfinity;
}
- if (StringSpanHelpers.Equals(sTrim, numfmt.NaNSymbol))
+ if (sTrim.EqualsOrdinal(info.NaNSymbol))
{
return float.NaN;
}
- throw new FormatException(SR.Format_InvalidString);
+ ThrowOverflowOrFormatException(overflow: false, null);
}
if (!NumberBufferToDouble(ref number, ref d))
{
- throw new OverflowException(SR.Overflow_Single);
+ ThrowOverflowOrFormatException(overflow: true, nameof(SR.Overflow_Single));
}
float castSingle = (float)d;
if (float.IsInfinity(castSingle))
{
- throw new OverflowException(SR.Overflow_Single);
+ ThrowOverflowOrFormatException(overflow: true, nameof(SR.Overflow_Single));
}
return castSingle;
}
- internal unsafe static bool TryParseDecimal(ReadOnlySpan<char> value, NumberStyles options, NumberFormatInfo numfmt, out decimal result)
+ internal static bool TryParseDecimal(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out decimal result)
{
NumberBuffer number = default;
result = 0;
- if (!TryStringToNumber(value, options, ref number, numfmt, true))
+ if (!TryStringToNumber(value, styles, ref number, info, true))
{
return false;
}
@@ -812,13 +1660,12 @@ namespace System
return true;
}
- internal unsafe static bool TryParseDouble(ReadOnlySpan<char> value, NumberStyles options, NumberFormatInfo numfmt, out double result)
+ internal static bool TryParseDouble(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out double result)
{
NumberBuffer number = default;
result = 0;
-
- if (!TryStringToNumber(value, options, ref number, numfmt, false))
+ if (!TryStringToNumber(value, styles, ref number, info, false))
{
return false;
}
@@ -829,13 +1676,13 @@ namespace System
return true;
}
- internal unsafe static bool TryParseSingle(ReadOnlySpan<char> value, NumberStyles options, NumberFormatInfo numfmt, out float result)
+ internal static bool TryParseSingle(ReadOnlySpan<char> value, NumberStyles styles, NumberFormatInfo info, out float result)
{
NumberBuffer number = default;
result = 0;
double d = 0;
- if (!TryStringToNumber(value, options, ref number, numfmt, false))
+ if (!TryStringToNumber(value, styles, ref number, info, false))
{
return false;
}
@@ -853,28 +1700,28 @@ namespace System
return true;
}
- private static unsafe void StringToNumber(ReadOnlySpan<char> str, NumberStyles options, ref NumberBuffer number, NumberFormatInfo info, bool parseDecimal)
+ private static unsafe void StringToNumber(ReadOnlySpan<char> value, NumberStyles styles, ref NumberBuffer number, NumberFormatInfo info, bool parseDecimal)
{
Debug.Assert(info != null);
- fixed (char* stringPointer = &MemoryMarshal.GetReference(str))
+ fixed (char* stringPointer = &MemoryMarshal.GetReference(value))
{
char* p = stringPointer;
- if (!ParseNumber(ref p, options, ref number, info, parseDecimal)
- || (p - stringPointer < str.Length && !TrailingZeros(str, (int)(p - stringPointer))))
+ if (!ParseNumber(ref p, p + value.Length, styles, ref number, info, parseDecimal)
+ || (p - stringPointer < value.Length && !TrailingZeros(value, (int)(p - stringPointer))))
{
- throw new FormatException(SR.Format_InvalidString);
+ ThrowOverflowOrFormatException(overflow: false, null);
}
}
}
- internal static unsafe bool TryStringToNumber(ReadOnlySpan<char> str, NumberStyles options, ref NumberBuffer number, NumberFormatInfo numfmt, bool parseDecimal)
+ internal static unsafe bool TryStringToNumber(ReadOnlySpan<char> value, NumberStyles styles, ref NumberBuffer number, NumberFormatInfo info, bool parseDecimal)
{
- Debug.Assert(numfmt != null);
- fixed (char* stringPointer = &MemoryMarshal.GetReference(str))
+ Debug.Assert(info != null);
+ fixed (char* stringPointer = &MemoryMarshal.GetReference(value))
{
char* p = stringPointer;
- if (!ParseNumber(ref p, options, ref number, numfmt, parseDecimal)
- || (p - stringPointer < str.Length && !TrailingZeros(str, (int)(p - stringPointer))))
+ if (!ParseNumber(ref p, p + value.Length, styles, ref number, info, parseDecimal)
+ || (p - stringPointer < value.Length && !TrailingZeros(value, (int)(p - stringPointer))))
{
return false;
}
@@ -883,12 +1730,12 @@ namespace System
return true;
}
- private static bool TrailingZeros(ReadOnlySpan<char> s, int index)
+ private static bool TrailingZeros(ReadOnlySpan<char> value, int index)
{
// For compatibility, we need to allow trailing zeros at the end of a number string
- for (int i = index; i < s.Length; i++)
+ for (int i = index; i < value.Length; i++)
{
- if (s[i] != '\0')
+ if (value[i] != '\0')
{
return false;
}
@@ -897,68 +1744,62 @@ namespace System
return true;
}
- private unsafe static char* MatchChars(char* p, string str)
+ private static unsafe char* MatchChars(char* p, char* pEnd, string value)
{
- fixed (char* stringPointer = str)
+ Debug.Assert(p != null && pEnd != null && p <= pEnd && value != null);
+ fixed (char* stringPointer = value)
{
- return MatchChars(p, stringPointer);
+ char* str = stringPointer;
+ if (*str != '\0')
+ {
+ // We only hurt the failure case
+ // This fix is for French or Kazakh cultures. Since a user cannot type 0xA0 as a
+ // space character we use 0x20 space character instead to mean the same.
+ while (true)
+ {
+ char cp = p < pEnd ? *p : '\0';
+ if (cp != *str && !(*str == '\u00a0' && cp == '\u0020'))
+ {
+ break;
+ }
+ p++;
+ str++;
+ if (*str == '\0') return p;
+ }
+ }
}
+
+ return null;
}
- private unsafe static char* MatchChars(char* p, char* str)
- {
- Debug.Assert(p != null && str != null);
+ private static bool IsWhite(int ch) => ch == 0x20 || ((uint)(ch - 0x09) <= (0x0D - 0x09));
- if (*str == '\0')
- {
- return null;
- }
-
- // We only hurt the failure case
- // This fix is for French or Kazakh cultures. Since a user cannot type 0xA0 as a
- // space character we use 0x20 space character instead to mean the same.
- while (*p == *str || (*str == '\u00a0' && *p == '\u0020'))
- {
- p++;
- str++;
- if (*str == '\0') return p;
- }
+ private static bool IsDigit(int ch) => ((uint)ch - '0') <= 9;
- return null;
+ private static void ThrowOverflowOrFormatException(bool overflow, string overflowResourceKey)
+ {
+ throw overflow ?
+ new OverflowException(SR.GetResourceString(overflowResourceKey)) :
+ (Exception)new FormatException(SR.Format_InvalidString);
}
- private static bool IsWhite(char ch) => ch == 0x20 || (ch >= 0x09 && ch <= 0x0D);
-
private static bool NumberBufferToDouble(ref NumberBuffer number, ref double value)
{
double d = NumberToDouble(ref number);
- uint e = DoubleHelper.Exponent(d);
- ulong m = DoubleHelper.Mantissa(d);
-
- if (e == 0x7FF)
+ if (!double.IsFinite(d))
{
+ value = default;
return false;
}
- if (e == 0 && m == 0)
+ if (d == 0.0)
{
- d = 0;
+ // normalize -0.0 to 0.0
+ d = 0.0;
}
value = d;
return true;
}
-
- private static class DoubleHelper
- {
- public static unsafe uint Exponent(double d) =>
- (*((uint*)&d + 1) >> 20) & 0x000007ff;
-
- public static unsafe ulong Mantissa(double d) =>
- *((ulong*)&d) & 0x000fffffffffffff;
-
- public static unsafe bool Sign(double d) =>
- (*((uint*)&d + 1) >> 31) != 0;
- }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.cs b/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.cs
index ea32ed380..3fb3086b2 100644
--- a/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.cs
+++ b/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.cs
@@ -9,131 +9,131 @@ namespace System.Numerics
internal class ConstantHelper
{
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Byte GetByteWithAllBitsSet()
+ public static byte GetByteWithAllBitsSet()
{
- Byte value = 0;
+ byte value = 0;
unsafe
{
unchecked
{
- *((Byte*)&value) = (Byte)0xff;
+ *((byte*)&value) = (byte)0xff;
}
}
return value;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static SByte GetSByteWithAllBitsSet()
+ public static sbyte GetSByteWithAllBitsSet()
{
- SByte value = 0;
+ sbyte value = 0;
unsafe
{
unchecked
{
- *((SByte*)&value) = (SByte)0xff;
+ *((sbyte*)&value) = (sbyte)0xff;
}
}
return value;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static UInt16 GetUInt16WithAllBitsSet()
+ public static ushort GetUInt16WithAllBitsSet()
{
- UInt16 value = 0;
+ ushort value = 0;
unsafe
{
unchecked
{
- *((UInt16*)&value) = (UInt16)0xffff;
+ *((ushort*)&value) = (ushort)0xffff;
}
}
return value;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Int16 GetInt16WithAllBitsSet()
+ public static short GetInt16WithAllBitsSet()
{
- Int16 value = 0;
+ short value = 0;
unsafe
{
unchecked
{
- *((Int16*)&value) = (Int16)0xffff;
+ *((short*)&value) = (short)0xffff;
}
}
return value;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static UInt32 GetUInt32WithAllBitsSet()
+ public static uint GetUInt32WithAllBitsSet()
{
- UInt32 value = 0;
+ uint value = 0;
unsafe
{
unchecked
{
- *((UInt32*)&value) = (UInt32)0xffffffff;
+ *((uint*)&value) = (uint)0xffffffff;
}
}
return value;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Int32 GetInt32WithAllBitsSet()
+ public static int GetInt32WithAllBitsSet()
{
- Int32 value = 0;
+ int value = 0;
unsafe
{
unchecked
{
- *((Int32*)&value) = (Int32)0xffffffff;
+ *((int*)&value) = (int)0xffffffff;
}
}
return value;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static UInt64 GetUInt64WithAllBitsSet()
+ public static ulong GetUInt64WithAllBitsSet()
{
- UInt64 value = 0;
+ ulong value = 0;
unsafe
{
unchecked
{
- *((UInt64*)&value) = (UInt64)0xffffffffffffffff;
+ *((ulong*)&value) = (ulong)0xffffffffffffffff;
}
}
return value;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Int64 GetInt64WithAllBitsSet()
+ public static long GetInt64WithAllBitsSet()
{
- Int64 value = 0;
+ long value = 0;
unsafe
{
unchecked
{
- *((Int64*)&value) = (Int64)0xffffffffffffffff;
+ *((long*)&value) = (long)0xffffffffffffffff;
}
}
return value;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Single GetSingleWithAllBitsSet()
+ public static float GetSingleWithAllBitsSet()
{
- Single value = 0;
+ float value = 0;
unsafe
{
unchecked
{
- *((Int32*)&value) = (Int32)0xffffffff;
+ *((int*)&value) = (int)0xffffffff;
}
}
return value;
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Double GetDoubleWithAllBitsSet()
+ public static double GetDoubleWithAllBitsSet()
{
- Double value = 0;
+ double value = 0;
unsafe
{
unchecked
{
- *((Int64*)&value) = (Int64)0xffffffffffffffff;
+ *((long*)&value) = (long)0xffffffffffffffff;
}
}
return value;
diff --git a/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.tt b/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.tt
index 4b1c67757..dd823abc0 100644
--- a/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.tt
+++ b/src/System.Private.CoreLib/shared/System/Numerics/ConstantHelper.tt
@@ -20,19 +20,20 @@ namespace System.Numerics
{
internal class ConstantHelper
{
-<# foreach (var type in supportedTypes)
+<#
+ foreach (var type in supportedTypes)
{
string hexValue = "0x" + new string('f', Marshal.SizeOf(type) * 2);
#>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static <#= type.Name #> Get<#= type.Name #>WithAllBitsSet()
+ public static <#= typeAliases[type] #> Get<#= type.Name #>WithAllBitsSet()
{
- <#= type.Name #> value = 0;
+ <#= typeAliases[type] #> value = 0;
unsafe
{
unchecked
{
- *((<#= GetIntegralEquivalent(type).Name #>*)&value) = (<#=GetIntegralEquivalent(type).Name#>)<#= hexValue #>;
+ *((<#= typeAliases[GetIntegralEquivalent(type)] #>*)&value) = (<#= typeAliases[GetIntegralEquivalent(type)] #>)<#= hexValue #>;
}
}
return value;
@@ -44,17 +45,17 @@ namespace System.Numerics
}<#+
public Type GetIntegralEquivalent(Type type)
{
- if (type == typeof(Single))
+ if (type == typeof(float))
{
- return typeof(Int32);
+ return typeof(int);
}
else if (type == typeof(double))
{
- return typeof(Int64);
+ return typeof(long);
}
else
{
return type;
}
}
-#> \ No newline at end of file
+#>
diff --git a/src/System.Private.CoreLib/shared/System/Numerics/GenerationConfig.ttinclude b/src/System.Private.CoreLib/shared/System/Numerics/GenerationConfig.ttinclude
index cdd9c9521..a4466e1a8 100644
--- a/src/System.Private.CoreLib/shared/System/Numerics/GenerationConfig.ttinclude
+++ b/src/System.Private.CoreLib/shared/System/Numerics/GenerationConfig.ttinclude
@@ -1,5 +1,6 @@
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections.Generic" #>
+<#@ import namespace="System.Text" #>
<#+
/* This file includes static data used as compilation configuration for the rest of the code generation.
It is shared here to ensure that all generated code compiles with the same constants and configurations. */
@@ -7,27 +8,40 @@
// The set of supported numeric types to compile
public static Type[] supportedTypes = new[]
{
- typeof(Byte), typeof(SByte), typeof(UInt16), typeof(Int16),
- typeof(UInt32), typeof(Int32), typeof(UInt64), typeof(Int64),
- typeof(Single), typeof(Double)
+ typeof(byte), typeof(sbyte), typeof(ushort), typeof(short),
+ typeof(uint), typeof(int), typeof(ulong), typeof(long),
+ typeof(float), typeof(double)
};
// The set of unsigned types, a subset of the above. Used for excluding from certain methods, i.e. Abs and Negate
public static Type[] unsignedTypes = new[]
{
- typeof(Byte), typeof(UInt16), typeof(UInt32), typeof(UInt64)
+ typeof(byte), typeof(ushort), typeof(uint), typeof(ulong)
};
public static Type[] integralTypes = new[]
{
- typeof(Byte), typeof(SByte), typeof(UInt16), typeof(Int16),
- typeof(UInt32), typeof(Int32), typeof(UInt64), typeof(Int64)
+ typeof(byte), typeof(sbyte), typeof(ushort), typeof(short),
+ typeof(uint), typeof(int), typeof(ulong), typeof(long)
};
public static Type[] nonClsCompliantTypes = new[]
{
- typeof(SByte), typeof(UInt16),
- typeof(UInt32), typeof(UInt64)
+ typeof(sbyte), typeof(ushort), typeof(uint), typeof(ulong)
+ };
+
+ public static Dictionary<Type, string> typeAliases = new Dictionary<Type, string>()
+ {
+ { typeof(byte), "byte" },
+ { typeof(sbyte), "sbyte" },
+ { typeof(ushort), "ushort" },
+ { typeof(short), "short" },
+ { typeof(uint), "uint" },
+ { typeof(int), "int" },
+ { typeof(ulong), "ulong" },
+ { typeof(long), "long" },
+ { typeof(float), "float" },
+ { typeof(double), "double" }
};
// The total register size, in bytes. 16 for SSE2, 32 for AVX, 64 for AVX512
@@ -136,12 +150,37 @@
public string GenerateIfStatementHeader(Type type)
{
string keyword = (type == supportedTypes[0]) ? "if" : "else if";
- return string.Format("{0} (typeof(T) == typeof({1}))", keyword, type.Name);
+ return string.Format("{0} (typeof(T) == typeof({1}))", keyword, typeAliases[type]);
}
public string GenerateIfStatementHeader(Type type, IEnumerable<Type> allTypes)
{
string keyword = (type == allTypes.ToArray()[0]) ? "if" : "else if";
- return string.Format("{0} (typeof(T) == typeof({1}))", keyword, type.Name);
+ return string.Format("{0} (typeof(T) == typeof({1}))", keyword, typeAliases[type]);
+ }
+
+ public string MakeTypeComparisonCondition(Type type)
+ {
+ return string.Format("(typeof(T) == typeof({0}))", typeAliases[type]);
+ }
+
+ public string GenerateIfConditionAllTypes(IEnumerable<Type> allTypes)
+ {
+ StringBuilder sbuilder = new StringBuilder();
+ bool firstTime = true;
+ foreach (var type in allTypes)
+ {
+ if (firstTime)
+ {
+ sbuilder.Append("if (").Append(MakeTypeComparisonCondition(type));
+ firstTime = false;
+ }
+ else
+ {
+ sbuilder.AppendLine().Append(" || ").Append(MakeTypeComparisonCondition(type));
+ }
+ }
+ sbuilder.Append(")");
+ return sbuilder.ToString();
}
-#> \ No newline at end of file
+#>
diff --git a/src/System.Private.CoreLib/shared/System/Numerics/Register.cs b/src/System.Private.CoreLib/shared/System/Numerics/Register.cs
index a27e922b9..8efa85b19 100644
--- a/src/System.Private.CoreLib/shared/System/Numerics/Register.cs
+++ b/src/System.Private.CoreLib/shared/System/Numerics/Register.cs
@@ -17,155 +17,155 @@ namespace System.Numerics
#region Internal Storage Fields
// Internal System.Byte Fields
[FieldOffset(0)]
- internal Byte byte_0;
+ internal byte byte_0;
[FieldOffset(1)]
- internal Byte byte_1;
+ internal byte byte_1;
[FieldOffset(2)]
- internal Byte byte_2;
+ internal byte byte_2;
[FieldOffset(3)]
- internal Byte byte_3;
+ internal byte byte_3;
[FieldOffset(4)]
- internal Byte byte_4;
+ internal byte byte_4;
[FieldOffset(5)]
- internal Byte byte_5;
+ internal byte byte_5;
[FieldOffset(6)]
- internal Byte byte_6;
+ internal byte byte_6;
[FieldOffset(7)]
- internal Byte byte_7;
+ internal byte byte_7;
[FieldOffset(8)]
- internal Byte byte_8;
+ internal byte byte_8;
[FieldOffset(9)]
- internal Byte byte_9;
+ internal byte byte_9;
[FieldOffset(10)]
- internal Byte byte_10;
+ internal byte byte_10;
[FieldOffset(11)]
- internal Byte byte_11;
+ internal byte byte_11;
[FieldOffset(12)]
- internal Byte byte_12;
+ internal byte byte_12;
[FieldOffset(13)]
- internal Byte byte_13;
+ internal byte byte_13;
[FieldOffset(14)]
- internal Byte byte_14;
+ internal byte byte_14;
[FieldOffset(15)]
- internal Byte byte_15;
+ internal byte byte_15;
// Internal System.SByte Fields
[FieldOffset(0)]
- internal SByte sbyte_0;
+ internal sbyte sbyte_0;
[FieldOffset(1)]
- internal SByte sbyte_1;
+ internal sbyte sbyte_1;
[FieldOffset(2)]
- internal SByte sbyte_2;
+ internal sbyte sbyte_2;
[FieldOffset(3)]
- internal SByte sbyte_3;
+ internal sbyte sbyte_3;
[FieldOffset(4)]
- internal SByte sbyte_4;
+ internal sbyte sbyte_4;
[FieldOffset(5)]
- internal SByte sbyte_5;
+ internal sbyte sbyte_5;
[FieldOffset(6)]
- internal SByte sbyte_6;
+ internal sbyte sbyte_6;
[FieldOffset(7)]
- internal SByte sbyte_7;
+ internal sbyte sbyte_7;
[FieldOffset(8)]
- internal SByte sbyte_8;
+ internal sbyte sbyte_8;
[FieldOffset(9)]
- internal SByte sbyte_9;
+ internal sbyte sbyte_9;
[FieldOffset(10)]
- internal SByte sbyte_10;
+ internal sbyte sbyte_10;
[FieldOffset(11)]
- internal SByte sbyte_11;
+ internal sbyte sbyte_11;
[FieldOffset(12)]
- internal SByte sbyte_12;
+ internal sbyte sbyte_12;
[FieldOffset(13)]
- internal SByte sbyte_13;
+ internal sbyte sbyte_13;
[FieldOffset(14)]
- internal SByte sbyte_14;
+ internal sbyte sbyte_14;
[FieldOffset(15)]
- internal SByte sbyte_15;
+ internal sbyte sbyte_15;
// Internal System.UInt16 Fields
[FieldOffset(0)]
- internal UInt16 uint16_0;
+ internal ushort uint16_0;
[FieldOffset(2)]
- internal UInt16 uint16_1;
+ internal ushort uint16_1;
[FieldOffset(4)]
- internal UInt16 uint16_2;
+ internal ushort uint16_2;
[FieldOffset(6)]
- internal UInt16 uint16_3;
+ internal ushort uint16_3;
[FieldOffset(8)]
- internal UInt16 uint16_4;
+ internal ushort uint16_4;
[FieldOffset(10)]
- internal UInt16 uint16_5;
+ internal ushort uint16_5;
[FieldOffset(12)]
- internal UInt16 uint16_6;
+ internal ushort uint16_6;
[FieldOffset(14)]
- internal UInt16 uint16_7;
+ internal ushort uint16_7;
// Internal System.Int16 Fields
[FieldOffset(0)]
- internal Int16 int16_0;
+ internal short int16_0;
[FieldOffset(2)]
- internal Int16 int16_1;
+ internal short int16_1;
[FieldOffset(4)]
- internal Int16 int16_2;
+ internal short int16_2;
[FieldOffset(6)]
- internal Int16 int16_3;
+ internal short int16_3;
[FieldOffset(8)]
- internal Int16 int16_4;
+ internal short int16_4;
[FieldOffset(10)]
- internal Int16 int16_5;
+ internal short int16_5;
[FieldOffset(12)]
- internal Int16 int16_6;
+ internal short int16_6;
[FieldOffset(14)]
- internal Int16 int16_7;
+ internal short int16_7;
// Internal System.UInt32 Fields
[FieldOffset(0)]
- internal UInt32 uint32_0;
+ internal uint uint32_0;
[FieldOffset(4)]
- internal UInt32 uint32_1;
+ internal uint uint32_1;
[FieldOffset(8)]
- internal UInt32 uint32_2;
+ internal uint uint32_2;
[FieldOffset(12)]
- internal UInt32 uint32_3;
+ internal uint uint32_3;
// Internal System.Int32 Fields
[FieldOffset(0)]
- internal Int32 int32_0;
+ internal int int32_0;
[FieldOffset(4)]
- internal Int32 int32_1;
+ internal int int32_1;
[FieldOffset(8)]
- internal Int32 int32_2;
+ internal int int32_2;
[FieldOffset(12)]
- internal Int32 int32_3;
+ internal int int32_3;
// Internal System.UInt64 Fields
[FieldOffset(0)]
- internal UInt64 uint64_0;
+ internal ulong uint64_0;
[FieldOffset(8)]
- internal UInt64 uint64_1;
+ internal ulong uint64_1;
// Internal System.Int64 Fields
[FieldOffset(0)]
- internal Int64 int64_0;
+ internal long int64_0;
[FieldOffset(8)]
- internal Int64 int64_1;
+ internal long int64_1;
// Internal System.Single Fields
[FieldOffset(0)]
- internal Single single_0;
+ internal float single_0;
[FieldOffset(4)]
- internal Single single_1;
+ internal float single_1;
[FieldOffset(8)]
- internal Single single_2;
+ internal float single_2;
[FieldOffset(12)]
- internal Single single_3;
+ internal float single_3;
// Internal System.Double Fields
[FieldOffset(0)]
- internal Double double_0;
+ internal double double_0;
[FieldOffset(8)]
- internal Double double_1;
+ internal double double_1;
#endregion Internal Storage Fields
}
diff --git a/src/System.Private.CoreLib/shared/System/Numerics/Register.tt b/src/System.Private.CoreLib/shared/System/Numerics/Register.tt
index a9de3b974..676b89f54 100644
--- a/src/System.Private.CoreLib/shared/System/Numerics/Register.tt
+++ b/src/System.Private.CoreLib/shared/System/Numerics/Register.tt
@@ -34,7 +34,7 @@ namespace System.Numerics
{
#>
[FieldOffset(<#=Marshal.SizeOf(type) * g#>)]
- internal <#=type.Name#> <#= type.Name.ToLowerInvariant() + "_" + g #>;
+ internal <#= typeAliases[type] #> <#= type.Name.ToLowerInvariant() + "_" + g #>;
<#
}
#>
diff --git a/src/System.Private.CoreLib/shared/System/Numerics/Vector.cs b/src/System.Private.CoreLib/shared/System/Numerics/Vector.cs
index 5fd286732..31a9114e3 100644
--- a/src/System.Private.CoreLib/shared/System/Numerics/Vector.cs
+++ b/src/System.Private.CoreLib/shared/System/Numerics/Vector.cs
@@ -2,9 +2,13 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+#if netcoreapp
+using Internal.Runtime.CompilerServices;
+#endif
using System.Globalization;
using System.Numerics.Hashing;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using System.Text;
namespace System.Numerics
@@ -12,8 +16,8 @@ namespace System.Numerics
/* Note: The following patterns are used throughout the code here and are described here
*
* PATTERN:
- * if (typeof(T) == typeof(Int32)) { ... }
- * else if (typeof(T) == typeof(Single)) { ... }
+ * if (typeof(T) == typeof(int)) { ... }
+ * else if (typeof(T) == typeof(float)) { ... }
* EXPLANATION:
* At runtime, each instantiation of Vector<T> will be type-specific, and each of these typeof blocks will be eliminated,
* as typeof(T) is a (JIT) compile-time constant for each instantiation. This design was chosen to eliminate any overhead from
@@ -96,7 +100,7 @@ namespace System.Numerics
internal byte _byte;
}
- // Calculates the size of this struct in bytes, by computing the offset of a field in a structure
+ // Calculates the size of this struct in bytes, by computing the offset of a field in a structure
private static unsafe int InitializeCount()
{
VectorSizeHelper vsh;
@@ -105,45 +109,45 @@ namespace System.Numerics
int vectorSizeInBytes = (int)(byteBase - vectorBase);
int typeSizeInBytes = -1;
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- typeSizeInBytes = sizeof(Byte);
+ typeSizeInBytes = sizeof(byte);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- typeSizeInBytes = sizeof(SByte);
+ typeSizeInBytes = sizeof(sbyte);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- typeSizeInBytes = sizeof(UInt16);
+ typeSizeInBytes = sizeof(ushort);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- typeSizeInBytes = sizeof(Int16);
+ typeSizeInBytes = sizeof(short);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- typeSizeInBytes = sizeof(UInt32);
+ typeSizeInBytes = sizeof(uint);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- typeSizeInBytes = sizeof(Int32);
+ typeSizeInBytes = sizeof(int);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- typeSizeInBytes = sizeof(UInt64);
+ typeSizeInBytes = sizeof(ulong);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- typeSizeInBytes = sizeof(Int64);
+ typeSizeInBytes = sizeof(long);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- typeSizeInBytes = sizeof(Single);
+ typeSizeInBytes = sizeof(float);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- typeSizeInBytes = sizeof(Double);
+ typeSizeInBytes = sizeof(double);
}
else
{
@@ -164,204 +168,204 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- fixed (Byte* basePtr = &this.register.byte_0)
+ fixed (byte* basePtr = &this.register.byte_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Byte)(object)value;
+ *(basePtr + g) = (byte)(object)value;
}
}
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- fixed (SByte* basePtr = &this.register.sbyte_0)
+ fixed (sbyte* basePtr = &this.register.sbyte_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (SByte)(object)value;
+ *(basePtr + g) = (sbyte)(object)value;
}
}
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- fixed (UInt16* basePtr = &this.register.uint16_0)
+ fixed (ushort* basePtr = &this.register.uint16_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (UInt16)(object)value;
+ *(basePtr + g) = (ushort)(object)value;
}
}
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- fixed (Int16* basePtr = &this.register.int16_0)
+ fixed (short* basePtr = &this.register.int16_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Int16)(object)value;
+ *(basePtr + g) = (short)(object)value;
}
}
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- fixed (UInt32* basePtr = &this.register.uint32_0)
+ fixed (uint* basePtr = &this.register.uint32_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (UInt32)(object)value;
+ *(basePtr + g) = (uint)(object)value;
}
}
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- fixed (Int32* basePtr = &this.register.int32_0)
+ fixed (int* basePtr = &this.register.int32_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Int32)(object)value;
+ *(basePtr + g) = (int)(object)value;
}
}
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- fixed (UInt64* basePtr = &this.register.uint64_0)
+ fixed (ulong* basePtr = &this.register.uint64_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (UInt64)(object)value;
+ *(basePtr + g) = (ulong)(object)value;
}
}
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- fixed (Int64* basePtr = &this.register.int64_0)
+ fixed (long* basePtr = &this.register.int64_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Int64)(object)value;
+ *(basePtr + g) = (long)(object)value;
}
}
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- fixed (Single* basePtr = &this.register.single_0)
+ fixed (float* basePtr = &this.register.single_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Single)(object)value;
+ *(basePtr + g) = (float)(object)value;
}
}
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- fixed (Double* basePtr = &this.register.double_0)
+ fixed (double* basePtr = &this.register.double_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Double)(object)value;
+ *(basePtr + g) = (double)(object)value;
}
}
}
}
else
{
- if (typeof(T) == typeof(Byte))
- {
- register.byte_0 = (Byte)(object)value;
- register.byte_1 = (Byte)(object)value;
- register.byte_2 = (Byte)(object)value;
- register.byte_3 = (Byte)(object)value;
- register.byte_4 = (Byte)(object)value;
- register.byte_5 = (Byte)(object)value;
- register.byte_6 = (Byte)(object)value;
- register.byte_7 = (Byte)(object)value;
- register.byte_8 = (Byte)(object)value;
- register.byte_9 = (Byte)(object)value;
- register.byte_10 = (Byte)(object)value;
- register.byte_11 = (Byte)(object)value;
- register.byte_12 = (Byte)(object)value;
- register.byte_13 = (Byte)(object)value;
- register.byte_14 = (Byte)(object)value;
- register.byte_15 = (Byte)(object)value;
- }
- else if (typeof(T) == typeof(SByte))
- {
- register.sbyte_0 = (SByte)(object)value;
- register.sbyte_1 = (SByte)(object)value;
- register.sbyte_2 = (SByte)(object)value;
- register.sbyte_3 = (SByte)(object)value;
- register.sbyte_4 = (SByte)(object)value;
- register.sbyte_5 = (SByte)(object)value;
- register.sbyte_6 = (SByte)(object)value;
- register.sbyte_7 = (SByte)(object)value;
- register.sbyte_8 = (SByte)(object)value;
- register.sbyte_9 = (SByte)(object)value;
- register.sbyte_10 = (SByte)(object)value;
- register.sbyte_11 = (SByte)(object)value;
- register.sbyte_12 = (SByte)(object)value;
- register.sbyte_13 = (SByte)(object)value;
- register.sbyte_14 = (SByte)(object)value;
- register.sbyte_15 = (SByte)(object)value;
- }
- else if (typeof(T) == typeof(UInt16))
- {
- register.uint16_0 = (UInt16)(object)value;
- register.uint16_1 = (UInt16)(object)value;
- register.uint16_2 = (UInt16)(object)value;
- register.uint16_3 = (UInt16)(object)value;
- register.uint16_4 = (UInt16)(object)value;
- register.uint16_5 = (UInt16)(object)value;
- register.uint16_6 = (UInt16)(object)value;
- register.uint16_7 = (UInt16)(object)value;
- }
- else if (typeof(T) == typeof(Int16))
- {
- register.int16_0 = (Int16)(object)value;
- register.int16_1 = (Int16)(object)value;
- register.int16_2 = (Int16)(object)value;
- register.int16_3 = (Int16)(object)value;
- register.int16_4 = (Int16)(object)value;
- register.int16_5 = (Int16)(object)value;
- register.int16_6 = (Int16)(object)value;
- register.int16_7 = (Int16)(object)value;
- }
- else if (typeof(T) == typeof(UInt32))
- {
- register.uint32_0 = (UInt32)(object)value;
- register.uint32_1 = (UInt32)(object)value;
- register.uint32_2 = (UInt32)(object)value;
- register.uint32_3 = (UInt32)(object)value;
- }
- else if (typeof(T) == typeof(Int32))
- {
- register.int32_0 = (Int32)(object)value;
- register.int32_1 = (Int32)(object)value;
- register.int32_2 = (Int32)(object)value;
- register.int32_3 = (Int32)(object)value;
- }
- else if (typeof(T) == typeof(UInt64))
- {
- register.uint64_0 = (UInt64)(object)value;
- register.uint64_1 = (UInt64)(object)value;
- }
- else if (typeof(T) == typeof(Int64))
- {
- register.int64_0 = (Int64)(object)value;
- register.int64_1 = (Int64)(object)value;
- }
- else if (typeof(T) == typeof(Single))
- {
- register.single_0 = (Single)(object)value;
- register.single_1 = (Single)(object)value;
- register.single_2 = (Single)(object)value;
- register.single_3 = (Single)(object)value;
- }
- else if (typeof(T) == typeof(Double))
- {
- register.double_0 = (Double)(object)value;
- register.double_1 = (Double)(object)value;
+ if (typeof(T) == typeof(byte))
+ {
+ register.byte_0 = (byte)(object)value;
+ register.byte_1 = (byte)(object)value;
+ register.byte_2 = (byte)(object)value;
+ register.byte_3 = (byte)(object)value;
+ register.byte_4 = (byte)(object)value;
+ register.byte_5 = (byte)(object)value;
+ register.byte_6 = (byte)(object)value;
+ register.byte_7 = (byte)(object)value;
+ register.byte_8 = (byte)(object)value;
+ register.byte_9 = (byte)(object)value;
+ register.byte_10 = (byte)(object)value;
+ register.byte_11 = (byte)(object)value;
+ register.byte_12 = (byte)(object)value;
+ register.byte_13 = (byte)(object)value;
+ register.byte_14 = (byte)(object)value;
+ register.byte_15 = (byte)(object)value;
+ }
+ else if (typeof(T) == typeof(sbyte))
+ {
+ register.sbyte_0 = (sbyte)(object)value;
+ register.sbyte_1 = (sbyte)(object)value;
+ register.sbyte_2 = (sbyte)(object)value;
+ register.sbyte_3 = (sbyte)(object)value;
+ register.sbyte_4 = (sbyte)(object)value;
+ register.sbyte_5 = (sbyte)(object)value;
+ register.sbyte_6 = (sbyte)(object)value;
+ register.sbyte_7 = (sbyte)(object)value;
+ register.sbyte_8 = (sbyte)(object)value;
+ register.sbyte_9 = (sbyte)(object)value;
+ register.sbyte_10 = (sbyte)(object)value;
+ register.sbyte_11 = (sbyte)(object)value;
+ register.sbyte_12 = (sbyte)(object)value;
+ register.sbyte_13 = (sbyte)(object)value;
+ register.sbyte_14 = (sbyte)(object)value;
+ register.sbyte_15 = (sbyte)(object)value;
+ }
+ else if (typeof(T) == typeof(ushort))
+ {
+ register.uint16_0 = (ushort)(object)value;
+ register.uint16_1 = (ushort)(object)value;
+ register.uint16_2 = (ushort)(object)value;
+ register.uint16_3 = (ushort)(object)value;
+ register.uint16_4 = (ushort)(object)value;
+ register.uint16_5 = (ushort)(object)value;
+ register.uint16_6 = (ushort)(object)value;
+ register.uint16_7 = (ushort)(object)value;
+ }
+ else if (typeof(T) == typeof(short))
+ {
+ register.int16_0 = (short)(object)value;
+ register.int16_1 = (short)(object)value;
+ register.int16_2 = (short)(object)value;
+ register.int16_3 = (short)(object)value;
+ register.int16_4 = (short)(object)value;
+ register.int16_5 = (short)(object)value;
+ register.int16_6 = (short)(object)value;
+ register.int16_7 = (short)(object)value;
+ }
+ else if (typeof(T) == typeof(uint))
+ {
+ register.uint32_0 = (uint)(object)value;
+ register.uint32_1 = (uint)(object)value;
+ register.uint32_2 = (uint)(object)value;
+ register.uint32_3 = (uint)(object)value;
+ }
+ else if (typeof(T) == typeof(int))
+ {
+ register.int32_0 = (int)(object)value;
+ register.int32_1 = (int)(object)value;
+ register.int32_2 = (int)(object)value;
+ register.int32_3 = (int)(object)value;
+ }
+ else if (typeof(T) == typeof(ulong))
+ {
+ register.uint64_0 = (ulong)(object)value;
+ register.uint64_1 = (ulong)(object)value;
+ }
+ else if (typeof(T) == typeof(long))
+ {
+ register.int64_0 = (long)(object)value;
+ register.int64_1 = (long)(object)value;
+ }
+ else if (typeof(T) == typeof(float))
+ {
+ register.single_0 = (float)(object)value;
+ register.single_1 = (float)(object)value;
+ register.single_2 = (float)(object)value;
+ register.single_3 = (float)(object)value;
+ }
+ else if (typeof(T) == typeof(double))
+ {
+ register.double_0 = (double)(object)value;
+ register.double_1 = (double)(object)value;
}
}
}
@@ -386,238 +390,238 @@ namespace System.Numerics
}
if (index < 0 || (values.Length - index) < Count)
{
- throw new IndexOutOfRangeException();
+ throw new IndexOutOfRangeException(SR.Format(SR.Arg_InsufficientNumberOfElements, Vector<T>.Count, nameof(values)));
}
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- fixed (Byte* basePtr = &this.register.byte_0)
+ fixed (byte* basePtr = &this.register.byte_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Byte)(object)values[g + index];
+ *(basePtr + g) = (byte)(object)values[g + index];
}
}
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- fixed (SByte* basePtr = &this.register.sbyte_0)
+ fixed (sbyte* basePtr = &this.register.sbyte_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (SByte)(object)values[g + index];
+ *(basePtr + g) = (sbyte)(object)values[g + index];
}
}
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- fixed (UInt16* basePtr = &this.register.uint16_0)
+ fixed (ushort* basePtr = &this.register.uint16_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (UInt16)(object)values[g + index];
+ *(basePtr + g) = (ushort)(object)values[g + index];
}
}
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- fixed (Int16* basePtr = &this.register.int16_0)
+ fixed (short* basePtr = &this.register.int16_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Int16)(object)values[g + index];
+ *(basePtr + g) = (short)(object)values[g + index];
}
}
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- fixed (UInt32* basePtr = &this.register.uint32_0)
+ fixed (uint* basePtr = &this.register.uint32_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (UInt32)(object)values[g + index];
+ *(basePtr + g) = (uint)(object)values[g + index];
}
}
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- fixed (Int32* basePtr = &this.register.int32_0)
+ fixed (int* basePtr = &this.register.int32_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Int32)(object)values[g + index];
+ *(basePtr + g) = (int)(object)values[g + index];
}
}
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- fixed (UInt64* basePtr = &this.register.uint64_0)
+ fixed (ulong* basePtr = &this.register.uint64_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (UInt64)(object)values[g + index];
+ *(basePtr + g) = (ulong)(object)values[g + index];
}
}
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- fixed (Int64* basePtr = &this.register.int64_0)
+ fixed (long* basePtr = &this.register.int64_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Int64)(object)values[g + index];
+ *(basePtr + g) = (long)(object)values[g + index];
}
}
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- fixed (Single* basePtr = &this.register.single_0)
+ fixed (float* basePtr = &this.register.single_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Single)(object)values[g + index];
+ *(basePtr + g) = (float)(object)values[g + index];
}
}
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- fixed (Double* basePtr = &this.register.double_0)
+ fixed (double* basePtr = &this.register.double_0)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (Double)(object)values[g + index];
+ *(basePtr + g) = (double)(object)values[g + index];
}
}
}
}
else
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- fixed (Byte* basePtr = &this.register.byte_0)
+ fixed (byte* basePtr = &this.register.byte_0)
{
- *(basePtr + 0) = (Byte)(object)values[0 + index];
- *(basePtr + 1) = (Byte)(object)values[1 + index];
- *(basePtr + 2) = (Byte)(object)values[2 + index];
- *(basePtr + 3) = (Byte)(object)values[3 + index];
- *(basePtr + 4) = (Byte)(object)values[4 + index];
- *(basePtr + 5) = (Byte)(object)values[5 + index];
- *(basePtr + 6) = (Byte)(object)values[6 + index];
- *(basePtr + 7) = (Byte)(object)values[7 + index];
- *(basePtr + 8) = (Byte)(object)values[8 + index];
- *(basePtr + 9) = (Byte)(object)values[9 + index];
- *(basePtr + 10) = (Byte)(object)values[10 + index];
- *(basePtr + 11) = (Byte)(object)values[11 + index];
- *(basePtr + 12) = (Byte)(object)values[12 + index];
- *(basePtr + 13) = (Byte)(object)values[13 + index];
- *(basePtr + 14) = (Byte)(object)values[14 + index];
- *(basePtr + 15) = (Byte)(object)values[15 + index];
+ *(basePtr + 0) = (byte)(object)values[0 + index];
+ *(basePtr + 1) = (byte)(object)values[1 + index];
+ *(basePtr + 2) = (byte)(object)values[2 + index];
+ *(basePtr + 3) = (byte)(object)values[3 + index];
+ *(basePtr + 4) = (byte)(object)values[4 + index];
+ *(basePtr + 5) = (byte)(object)values[5 + index];
+ *(basePtr + 6) = (byte)(object)values[6 + index];
+ *(basePtr + 7) = (byte)(object)values[7 + index];
+ *(basePtr + 8) = (byte)(object)values[8 + index];
+ *(basePtr + 9) = (byte)(object)values[9 + index];
+ *(basePtr + 10) = (byte)(object)values[10 + index];
+ *(basePtr + 11) = (byte)(object)values[11 + index];
+ *(basePtr + 12) = (byte)(object)values[12 + index];
+ *(basePtr + 13) = (byte)(object)values[13 + index];
+ *(basePtr + 14) = (byte)(object)values[14 + index];
+ *(basePtr + 15) = (byte)(object)values[15 + index];
}
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- fixed (SByte* basePtr = &this.register.sbyte_0)
+ fixed (sbyte* basePtr = &this.register.sbyte_0)
{
- *(basePtr + 0) = (SByte)(object)values[0 + index];
- *(basePtr + 1) = (SByte)(object)values[1 + index];
- *(basePtr + 2) = (SByte)(object)values[2 + index];
- *(basePtr + 3) = (SByte)(object)values[3 + index];
- *(basePtr + 4) = (SByte)(object)values[4 + index];
- *(basePtr + 5) = (SByte)(object)values[5 + index];
- *(basePtr + 6) = (SByte)(object)values[6 + index];
- *(basePtr + 7) = (SByte)(object)values[7 + index];
- *(basePtr + 8) = (SByte)(object)values[8 + index];
- *(basePtr + 9) = (SByte)(object)values[9 + index];
- *(basePtr + 10) = (SByte)(object)values[10 + index];
- *(basePtr + 11) = (SByte)(object)values[11 + index];
- *(basePtr + 12) = (SByte)(object)values[12 + index];
- *(basePtr + 13) = (SByte)(object)values[13 + index];
- *(basePtr + 14) = (SByte)(object)values[14 + index];
- *(basePtr + 15) = (SByte)(object)values[15 + index];
+ *(basePtr + 0) = (sbyte)(object)values[0 + index];
+ *(basePtr + 1) = (sbyte)(object)values[1 + index];
+ *(basePtr + 2) = (sbyte)(object)values[2 + index];
+ *(basePtr + 3) = (sbyte)(object)values[3 + index];
+ *(basePtr + 4) = (sbyte)(object)values[4 + index];
+ *(basePtr + 5) = (sbyte)(object)values[5 + index];
+ *(basePtr + 6) = (sbyte)(object)values[6 + index];
+ *(basePtr + 7) = (sbyte)(object)values[7 + index];
+ *(basePtr + 8) = (sbyte)(object)values[8 + index];
+ *(basePtr + 9) = (sbyte)(object)values[9 + index];
+ *(basePtr + 10) = (sbyte)(object)values[10 + index];
+ *(basePtr + 11) = (sbyte)(object)values[11 + index];
+ *(basePtr + 12) = (sbyte)(object)values[12 + index];
+ *(basePtr + 13) = (sbyte)(object)values[13 + index];
+ *(basePtr + 14) = (sbyte)(object)values[14 + index];
+ *(basePtr + 15) = (sbyte)(object)values[15 + index];
}
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- fixed (UInt16* basePtr = &this.register.uint16_0)
+ fixed (ushort* basePtr = &this.register.uint16_0)
{
- *(basePtr + 0) = (UInt16)(object)values[0 + index];
- *(basePtr + 1) = (UInt16)(object)values[1 + index];
- *(basePtr + 2) = (UInt16)(object)values[2 + index];
- *(basePtr + 3) = (UInt16)(object)values[3 + index];
- *(basePtr + 4) = (UInt16)(object)values[4 + index];
- *(basePtr + 5) = (UInt16)(object)values[5 + index];
- *(basePtr + 6) = (UInt16)(object)values[6 + index];
- *(basePtr + 7) = (UInt16)(object)values[7 + index];
+ *(basePtr + 0) = (ushort)(object)values[0 + index];
+ *(basePtr + 1) = (ushort)(object)values[1 + index];
+ *(basePtr + 2) = (ushort)(object)values[2 + index];
+ *(basePtr + 3) = (ushort)(object)values[3 + index];
+ *(basePtr + 4) = (ushort)(object)values[4 + index];
+ *(basePtr + 5) = (ushort)(object)values[5 + index];
+ *(basePtr + 6) = (ushort)(object)values[6 + index];
+ *(basePtr + 7) = (ushort)(object)values[7 + index];
}
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- fixed (Int16* basePtr = &this.register.int16_0)
+ fixed (short* basePtr = &this.register.int16_0)
{
- *(basePtr + 0) = (Int16)(object)values[0 + index];
- *(basePtr + 1) = (Int16)(object)values[1 + index];
- *(basePtr + 2) = (Int16)(object)values[2 + index];
- *(basePtr + 3) = (Int16)(object)values[3 + index];
- *(basePtr + 4) = (Int16)(object)values[4 + index];
- *(basePtr + 5) = (Int16)(object)values[5 + index];
- *(basePtr + 6) = (Int16)(object)values[6 + index];
- *(basePtr + 7) = (Int16)(object)values[7 + index];
+ *(basePtr + 0) = (short)(object)values[0 + index];
+ *(basePtr + 1) = (short)(object)values[1 + index];
+ *(basePtr + 2) = (short)(object)values[2 + index];
+ *(basePtr + 3) = (short)(object)values[3 + index];
+ *(basePtr + 4) = (short)(object)values[4 + index];
+ *(basePtr + 5) = (short)(object)values[5 + index];
+ *(basePtr + 6) = (short)(object)values[6 + index];
+ *(basePtr + 7) = (short)(object)values[7 + index];
}
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- fixed (UInt32* basePtr = &this.register.uint32_0)
+ fixed (uint* basePtr = &this.register.uint32_0)
{
- *(basePtr + 0) = (UInt32)(object)values[0 + index];
- *(basePtr + 1) = (UInt32)(object)values[1 + index];
- *(basePtr + 2) = (UInt32)(object)values[2 + index];
- *(basePtr + 3) = (UInt32)(object)values[3 + index];
+ *(basePtr + 0) = (uint)(object)values[0 + index];
+ *(basePtr + 1) = (uint)(object)values[1 + index];
+ *(basePtr + 2) = (uint)(object)values[2 + index];
+ *(basePtr + 3) = (uint)(object)values[3 + index];
}
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- fixed (Int32* basePtr = &this.register.int32_0)
+ fixed (int* basePtr = &this.register.int32_0)
{
- *(basePtr + 0) = (Int32)(object)values[0 + index];
- *(basePtr + 1) = (Int32)(object)values[1 + index];
- *(basePtr + 2) = (Int32)(object)values[2 + index];
- *(basePtr + 3) = (Int32)(object)values[3 + index];
+ *(basePtr + 0) = (int)(object)values[0 + index];
+ *(basePtr + 1) = (int)(object)values[1 + index];
+ *(basePtr + 2) = (int)(object)values[2 + index];
+ *(basePtr + 3) = (int)(object)values[3 + index];
}
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- fixed (UInt64* basePtr = &this.register.uint64_0)
+ fixed (ulong* basePtr = &this.register.uint64_0)
{
- *(basePtr + 0) = (UInt64)(object)values[0 + index];
- *(basePtr + 1) = (UInt64)(object)values[1 + index];
+ *(basePtr + 0) = (ulong)(object)values[0 + index];
+ *(basePtr + 1) = (ulong)(object)values[1 + index];
}
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- fixed (Int64* basePtr = &this.register.int64_0)
+ fixed (long* basePtr = &this.register.int64_0)
{
- *(basePtr + 0) = (Int64)(object)values[0 + index];
- *(basePtr + 1) = (Int64)(object)values[1 + index];
+ *(basePtr + 0) = (long)(object)values[0 + index];
+ *(basePtr + 1) = (long)(object)values[1 + index];
}
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- fixed (Single* basePtr = &this.register.single_0)
+ fixed (float* basePtr = &this.register.single_0)
{
- *(basePtr + 0) = (Single)(object)values[0 + index];
- *(basePtr + 1) = (Single)(object)values[1 + index];
- *(basePtr + 2) = (Single)(object)values[2 + index];
- *(basePtr + 3) = (Single)(object)values[3 + index];
+ *(basePtr + 0) = (float)(object)values[0 + index];
+ *(basePtr + 1) = (float)(object)values[1 + index];
+ *(basePtr + 2) = (float)(object)values[2 + index];
+ *(basePtr + 3) = (float)(object)values[3 + index];
}
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- fixed (Double* basePtr = &this.register.double_0)
+ fixed (double* basePtr = &this.register.double_0)
{
- *(basePtr + 0) = (Double)(object)values[0 + index];
- *(basePtr + 1) = (Double)(object)values[1 + index];
+ *(basePtr + 0) = (double)(object)values[0 + index];
+ *(basePtr + 1) = (double)(object)values[1 + index];
}
}
}
@@ -632,11 +636,11 @@ namespace System.Numerics
internal unsafe Vector(void* dataPointer, int offset)
: this()
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* castedPtr = (Byte*)dataPointer;
+ byte* castedPtr = (byte*)dataPointer;
castedPtr += offset;
- fixed (Byte* registerBase = &this.register.byte_0)
+ fixed (byte* registerBase = &this.register.byte_0)
{
for (int g = 0; g < Count; g++)
{
@@ -644,11 +648,11 @@ namespace System.Numerics
}
}
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* castedPtr = (SByte*)dataPointer;
+ sbyte* castedPtr = (sbyte*)dataPointer;
castedPtr += offset;
- fixed (SByte* registerBase = &this.register.sbyte_0)
+ fixed (sbyte* registerBase = &this.register.sbyte_0)
{
for (int g = 0; g < Count; g++)
{
@@ -656,11 +660,11 @@ namespace System.Numerics
}
}
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* castedPtr = (UInt16*)dataPointer;
+ ushort* castedPtr = (ushort*)dataPointer;
castedPtr += offset;
- fixed (UInt16* registerBase = &this.register.uint16_0)
+ fixed (ushort* registerBase = &this.register.uint16_0)
{
for (int g = 0; g < Count; g++)
{
@@ -668,11 +672,11 @@ namespace System.Numerics
}
}
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* castedPtr = (Int16*)dataPointer;
+ short* castedPtr = (short*)dataPointer;
castedPtr += offset;
- fixed (Int16* registerBase = &this.register.int16_0)
+ fixed (short* registerBase = &this.register.int16_0)
{
for (int g = 0; g < Count; g++)
{
@@ -680,11 +684,11 @@ namespace System.Numerics
}
}
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* castedPtr = (UInt32*)dataPointer;
+ uint* castedPtr = (uint*)dataPointer;
castedPtr += offset;
- fixed (UInt32* registerBase = &this.register.uint32_0)
+ fixed (uint* registerBase = &this.register.uint32_0)
{
for (int g = 0; g < Count; g++)
{
@@ -692,11 +696,11 @@ namespace System.Numerics
}
}
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* castedPtr = (Int32*)dataPointer;
+ int* castedPtr = (int*)dataPointer;
castedPtr += offset;
- fixed (Int32* registerBase = &this.register.int32_0)
+ fixed (int* registerBase = &this.register.int32_0)
{
for (int g = 0; g < Count; g++)
{
@@ -704,11 +708,11 @@ namespace System.Numerics
}
}
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* castedPtr = (UInt64*)dataPointer;
+ ulong* castedPtr = (ulong*)dataPointer;
castedPtr += offset;
- fixed (UInt64* registerBase = &this.register.uint64_0)
+ fixed (ulong* registerBase = &this.register.uint64_0)
{
for (int g = 0; g < Count; g++)
{
@@ -716,11 +720,11 @@ namespace System.Numerics
}
}
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* castedPtr = (Int64*)dataPointer;
+ long* castedPtr = (long*)dataPointer;
castedPtr += offset;
- fixed (Int64* registerBase = &this.register.int64_0)
+ fixed (long* registerBase = &this.register.int64_0)
{
for (int g = 0; g < Count; g++)
{
@@ -728,11 +732,11 @@ namespace System.Numerics
}
}
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* castedPtr = (Single*)dataPointer;
+ float* castedPtr = (float*)dataPointer;
castedPtr += offset;
- fixed (Single* registerBase = &this.register.single_0)
+ fixed (float* registerBase = &this.register.single_0)
{
for (int g = 0; g < Count; g++)
{
@@ -740,11 +744,11 @@ namespace System.Numerics
}
}
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* castedPtr = (Double*)dataPointer;
+ double* castedPtr = (double*)dataPointer;
castedPtr += offset;
- fixed (Double* registerBase = &this.register.double_0)
+ fixed (double* registerBase = &this.register.double_0)
{
for (int g = 0; g < Count; g++)
{
@@ -763,6 +767,37 @@ namespace System.Numerics
{
this.register = existingRegister;
}
+
+#if netcoreapp
+ /// <summary>
+ /// Constructs a vector from the given span. The span must contain at least Vector'T.Count elements.
+ /// </summary>
+ public Vector(Span<T> values)
+ : this()
+ {
+ if ((typeof(T) == typeof(byte))
+ || (typeof(T) == typeof(sbyte))
+ || (typeof(T) == typeof(ushort))
+ || (typeof(T) == typeof(short))
+ || (typeof(T) == typeof(uint))
+ || (typeof(T) == typeof(int))
+ || (typeof(T) == typeof(ulong))
+ || (typeof(T) == typeof(long))
+ || (typeof(T) == typeof(float))
+ || (typeof(T) == typeof(double)))
+ {
+ if (values.Length < Count)
+ {
+ throw new IndexOutOfRangeException(SR.Format(SR.Arg_InsufficientNumberOfElements, Vector<T>.Count, nameof(values)));
+ }
+ this = Unsafe.ReadUnaligned<Vector<T>>(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)));
+ }
+ else
+ {
+ throw new NotSupportedException(SR.Arg_TypeNotSupported);
+ }
+ }
+#endif
#endregion Constructors
#region Public Instance Methods
@@ -805,123 +840,123 @@ namespace System.Numerics
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte[] byteArray = (Byte[])(object)destination;
- fixed (Byte* destinationBase = byteArray)
+ byte[] byteArray = (byte[])(object)destination;
+ fixed (byte* destinationBase = byteArray)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (Byte)(object)this[g];
+ destinationBase[startIndex + g] = (byte)(object)this[g];
}
}
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte[] sbyteArray = (SByte[])(object)destination;
- fixed (SByte* destinationBase = sbyteArray)
+ sbyte[] sbyteArray = (sbyte[])(object)destination;
+ fixed (sbyte* destinationBase = sbyteArray)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (SByte)(object)this[g];
+ destinationBase[startIndex + g] = (sbyte)(object)this[g];
}
}
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16[] uint16Array = (UInt16[])(object)destination;
- fixed (UInt16* destinationBase = uint16Array)
+ ushort[] uint16Array = (ushort[])(object)destination;
+ fixed (ushort* destinationBase = uint16Array)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (UInt16)(object)this[g];
+ destinationBase[startIndex + g] = (ushort)(object)this[g];
}
}
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16[] int16Array = (Int16[])(object)destination;
- fixed (Int16* destinationBase = int16Array)
+ short[] int16Array = (short[])(object)destination;
+ fixed (short* destinationBase = int16Array)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (Int16)(object)this[g];
+ destinationBase[startIndex + g] = (short)(object)this[g];
}
}
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32[] uint32Array = (UInt32[])(object)destination;
- fixed (UInt32* destinationBase = uint32Array)
+ uint[] uint32Array = (uint[])(object)destination;
+ fixed (uint* destinationBase = uint32Array)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (UInt32)(object)this[g];
+ destinationBase[startIndex + g] = (uint)(object)this[g];
}
}
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32[] int32Array = (Int32[])(object)destination;
- fixed (Int32* destinationBase = int32Array)
+ int[] int32Array = (int[])(object)destination;
+ fixed (int* destinationBase = int32Array)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (Int32)(object)this[g];
+ destinationBase[startIndex + g] = (int)(object)this[g];
}
}
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64[] uint64Array = (UInt64[])(object)destination;
- fixed (UInt64* destinationBase = uint64Array)
+ ulong[] uint64Array = (ulong[])(object)destination;
+ fixed (ulong* destinationBase = uint64Array)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (UInt64)(object)this[g];
+ destinationBase[startIndex + g] = (ulong)(object)this[g];
}
}
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64[] int64Array = (Int64[])(object)destination;
- fixed (Int64* destinationBase = int64Array)
+ long[] int64Array = (long[])(object)destination;
+ fixed (long* destinationBase = int64Array)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (Int64)(object)this[g];
+ destinationBase[startIndex + g] = (long)(object)this[g];
}
}
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single[] singleArray = (Single[])(object)destination;
- fixed (Single* destinationBase = singleArray)
+ float[] singleArray = (float[])(object)destination;
+ fixed (float* destinationBase = singleArray)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (Single)(object)this[g];
+ destinationBase[startIndex + g] = (float)(object)this[g];
}
}
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double[] doubleArray = (Double[])(object)destination;
- fixed (Double* destinationBase = doubleArray)
+ double[] doubleArray = (double[])(object)destination;
+ fixed (double* destinationBase = doubleArray)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (Double)(object)this[g];
+ destinationBase[startIndex + g] = (double)(object)this[g];
}
}
}
}
else
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte[] byteArray = (Byte[])(object)destination;
- fixed (Byte* destinationBase = byteArray)
+ byte[] byteArray = (byte[])(object)destination;
+ fixed (byte* destinationBase = byteArray)
{
destinationBase[startIndex + 0] = this.register.byte_0;
destinationBase[startIndex + 1] = this.register.byte_1;
@@ -941,10 +976,10 @@ namespace System.Numerics
destinationBase[startIndex + 15] = this.register.byte_15;
}
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte[] sbyteArray = (SByte[])(object)destination;
- fixed (SByte* destinationBase = sbyteArray)
+ sbyte[] sbyteArray = (sbyte[])(object)destination;
+ fixed (sbyte* destinationBase = sbyteArray)
{
destinationBase[startIndex + 0] = this.register.sbyte_0;
destinationBase[startIndex + 1] = this.register.sbyte_1;
@@ -964,10 +999,10 @@ namespace System.Numerics
destinationBase[startIndex + 15] = this.register.sbyte_15;
}
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16[] uint16Array = (UInt16[])(object)destination;
- fixed (UInt16* destinationBase = uint16Array)
+ ushort[] uint16Array = (ushort[])(object)destination;
+ fixed (ushort* destinationBase = uint16Array)
{
destinationBase[startIndex + 0] = this.register.uint16_0;
destinationBase[startIndex + 1] = this.register.uint16_1;
@@ -979,10 +1014,10 @@ namespace System.Numerics
destinationBase[startIndex + 7] = this.register.uint16_7;
}
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16[] int16Array = (Int16[])(object)destination;
- fixed (Int16* destinationBase = int16Array)
+ short[] int16Array = (short[])(object)destination;
+ fixed (short* destinationBase = int16Array)
{
destinationBase[startIndex + 0] = this.register.int16_0;
destinationBase[startIndex + 1] = this.register.int16_1;
@@ -994,10 +1029,10 @@ namespace System.Numerics
destinationBase[startIndex + 7] = this.register.int16_7;
}
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32[] uint32Array = (UInt32[])(object)destination;
- fixed (UInt32* destinationBase = uint32Array)
+ uint[] uint32Array = (uint[])(object)destination;
+ fixed (uint* destinationBase = uint32Array)
{
destinationBase[startIndex + 0] = this.register.uint32_0;
destinationBase[startIndex + 1] = this.register.uint32_1;
@@ -1005,10 +1040,10 @@ namespace System.Numerics
destinationBase[startIndex + 3] = this.register.uint32_3;
}
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32[] int32Array = (Int32[])(object)destination;
- fixed (Int32* destinationBase = int32Array)
+ int[] int32Array = (int[])(object)destination;
+ fixed (int* destinationBase = int32Array)
{
destinationBase[startIndex + 0] = this.register.int32_0;
destinationBase[startIndex + 1] = this.register.int32_1;
@@ -1016,28 +1051,28 @@ namespace System.Numerics
destinationBase[startIndex + 3] = this.register.int32_3;
}
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64[] uint64Array = (UInt64[])(object)destination;
- fixed (UInt64* destinationBase = uint64Array)
+ ulong[] uint64Array = (ulong[])(object)destination;
+ fixed (ulong* destinationBase = uint64Array)
{
destinationBase[startIndex + 0] = this.register.uint64_0;
destinationBase[startIndex + 1] = this.register.uint64_1;
}
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64[] int64Array = (Int64[])(object)destination;
- fixed (Int64* destinationBase = int64Array)
+ long[] int64Array = (long[])(object)destination;
+ fixed (long* destinationBase = int64Array)
{
destinationBase[startIndex + 0] = this.register.int64_0;
destinationBase[startIndex + 1] = this.register.int64_1;
}
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single[] singleArray = (Single[])(object)destination;
- fixed (Single* destinationBase = singleArray)
+ float[] singleArray = (float[])(object)destination;
+ fixed (float* destinationBase = singleArray)
{
destinationBase[startIndex + 0] = this.register.single_0;
destinationBase[startIndex + 1] = this.register.single_1;
@@ -1045,10 +1080,10 @@ namespace System.Numerics
destinationBase[startIndex + 3] = this.register.single_3;
}
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double[] doubleArray = (Double[])(object)destination;
- fixed (Double* destinationBase = doubleArray)
+ double[] doubleArray = (double[])(object)destination;
+ fixed (double* destinationBase = doubleArray)
{
destinationBase[startIndex + 0] = this.register.double_0;
destinationBase[startIndex + 1] = this.register.double_1;
@@ -1069,72 +1104,72 @@ namespace System.Numerics
{
throw new IndexOutOfRangeException(SR.Format(SR.Arg_ArgumentOutOfRangeException, index));
}
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- fixed (Byte* basePtr = &this.register.byte_0)
+ fixed (byte* basePtr = &this.register.byte_0)
{
return (T)(object)*(basePtr + index);
}
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- fixed (SByte* basePtr = &this.register.sbyte_0)
+ fixed (sbyte* basePtr = &this.register.sbyte_0)
{
return (T)(object)*(basePtr + index);
}
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- fixed (UInt16* basePtr = &this.register.uint16_0)
+ fixed (ushort* basePtr = &this.register.uint16_0)
{
return (T)(object)*(basePtr + index);
}
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- fixed (Int16* basePtr = &this.register.int16_0)
+ fixed (short* basePtr = &this.register.int16_0)
{
return (T)(object)*(basePtr + index);
}
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- fixed (UInt32* basePtr = &this.register.uint32_0)
+ fixed (uint* basePtr = &this.register.uint32_0)
{
return (T)(object)*(basePtr + index);
}
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- fixed (Int32* basePtr = &this.register.int32_0)
+ fixed (int* basePtr = &this.register.int32_0)
{
return (T)(object)*(basePtr + index);
}
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- fixed (UInt64* basePtr = &this.register.uint64_0)
+ fixed (ulong* basePtr = &this.register.uint64_0)
{
return (T)(object)*(basePtr + index);
}
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- fixed (Int64* basePtr = &this.register.int64_0)
+ fixed (long* basePtr = &this.register.int64_0)
{
return (T)(object)*(basePtr + index);
}
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- fixed (Single* basePtr = &this.register.single_0)
+ fixed (float* basePtr = &this.register.single_0)
{
return (T)(object)*(basePtr + index);
}
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- fixed (Double* basePtr = &this.register.double_0)
+ fixed (double* basePtr = &this.register.double_0)
{
return (T)(object)*(basePtr + index);
}
@@ -1182,7 +1217,7 @@ namespace System.Numerics
}
else
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
return
this.register.byte_0 == other.register.byte_0
@@ -1202,7 +1237,7 @@ namespace System.Numerics
&& this.register.byte_14 == other.register.byte_14
&& this.register.byte_15 == other.register.byte_15;
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
return
this.register.sbyte_0 == other.register.sbyte_0
@@ -1222,7 +1257,7 @@ namespace System.Numerics
&& this.register.sbyte_14 == other.register.sbyte_14
&& this.register.sbyte_15 == other.register.sbyte_15;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
return
this.register.uint16_0 == other.register.uint16_0
@@ -1234,7 +1269,7 @@ namespace System.Numerics
&& this.register.uint16_6 == other.register.uint16_6
&& this.register.uint16_7 == other.register.uint16_7;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
return
this.register.int16_0 == other.register.int16_0
@@ -1246,7 +1281,7 @@ namespace System.Numerics
&& this.register.int16_6 == other.register.int16_6
&& this.register.int16_7 == other.register.int16_7;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
return
this.register.uint32_0 == other.register.uint32_0
@@ -1254,7 +1289,7 @@ namespace System.Numerics
&& this.register.uint32_2 == other.register.uint32_2
&& this.register.uint32_3 == other.register.uint32_3;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
return
this.register.int32_0 == other.register.int32_0
@@ -1262,19 +1297,19 @@ namespace System.Numerics
&& this.register.int32_2 == other.register.int32_2
&& this.register.int32_3 == other.register.int32_3;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
return
this.register.uint64_0 == other.register.uint64_0
&& this.register.uint64_1 == other.register.uint64_1;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
return
this.register.int64_0 == other.register.int64_0
&& this.register.int64_1 == other.register.int64_1;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
return
this.register.single_0 == other.register.single_0
@@ -1282,7 +1317,7 @@ namespace System.Numerics
&& this.register.single_2 == other.register.single_2
&& this.register.single_3 == other.register.single_3;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
return
this.register.double_0 == other.register.double_0
@@ -1305,83 +1340,83 @@ namespace System.Numerics
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((Byte)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((byte)(object)this[g]).GetHashCode());
}
return hash;
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((SByte)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((sbyte)(object)this[g]).GetHashCode());
}
return hash;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((UInt16)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((ushort)(object)this[g]).GetHashCode());
}
return hash;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((Int16)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((short)(object)this[g]).GetHashCode());
}
return hash;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((UInt32)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((uint)(object)this[g]).GetHashCode());
}
return hash;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((Int32)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((int)(object)this[g]).GetHashCode());
}
return hash;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((UInt64)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((ulong)(object)this[g]).GetHashCode());
}
return hash;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((Int64)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((long)(object)this[g]).GetHashCode());
}
return hash;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((Single)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((float)(object)this[g]).GetHashCode());
}
return hash;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((Double)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((double)(object)this[g]).GetHashCode());
}
return hash;
}
@@ -1392,7 +1427,7 @@ namespace System.Numerics
}
else
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
hash = HashHelpers.Combine(hash, this.register.byte_0.GetHashCode());
hash = HashHelpers.Combine(hash, this.register.byte_1.GetHashCode());
@@ -1412,7 +1447,7 @@ namespace System.Numerics
hash = HashHelpers.Combine(hash, this.register.byte_15.GetHashCode());
return hash;
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
hash = HashHelpers.Combine(hash, this.register.sbyte_0.GetHashCode());
hash = HashHelpers.Combine(hash, this.register.sbyte_1.GetHashCode());
@@ -1432,7 +1467,7 @@ namespace System.Numerics
hash = HashHelpers.Combine(hash, this.register.sbyte_15.GetHashCode());
return hash;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
hash = HashHelpers.Combine(hash, this.register.uint16_0.GetHashCode());
hash = HashHelpers.Combine(hash, this.register.uint16_1.GetHashCode());
@@ -1444,7 +1479,7 @@ namespace System.Numerics
hash = HashHelpers.Combine(hash, this.register.uint16_7.GetHashCode());
return hash;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
hash = HashHelpers.Combine(hash, this.register.int16_0.GetHashCode());
hash = HashHelpers.Combine(hash, this.register.int16_1.GetHashCode());
@@ -1456,7 +1491,7 @@ namespace System.Numerics
hash = HashHelpers.Combine(hash, this.register.int16_7.GetHashCode());
return hash;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
hash = HashHelpers.Combine(hash, this.register.uint32_0.GetHashCode());
hash = HashHelpers.Combine(hash, this.register.uint32_1.GetHashCode());
@@ -1464,7 +1499,7 @@ namespace System.Numerics
hash = HashHelpers.Combine(hash, this.register.uint32_3.GetHashCode());
return hash;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
hash = HashHelpers.Combine(hash, this.register.int32_0.GetHashCode());
hash = HashHelpers.Combine(hash, this.register.int32_1.GetHashCode());
@@ -1472,19 +1507,19 @@ namespace System.Numerics
hash = HashHelpers.Combine(hash, this.register.int32_3.GetHashCode());
return hash;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
hash = HashHelpers.Combine(hash, this.register.uint64_0.GetHashCode());
hash = HashHelpers.Combine(hash, this.register.uint64_1.GetHashCode());
return hash;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
hash = HashHelpers.Combine(hash, this.register.int64_0.GetHashCode());
hash = HashHelpers.Combine(hash, this.register.int64_1.GetHashCode());
return hash;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
hash = HashHelpers.Combine(hash, this.register.single_0.GetHashCode());
hash = HashHelpers.Combine(hash, this.register.single_1.GetHashCode());
@@ -1492,7 +1527,7 @@ namespace System.Numerics
hash = HashHelpers.Combine(hash, this.register.single_3.GetHashCode());
return hash;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
hash = HashHelpers.Combine(hash, this.register.double_0.GetHashCode());
hash = HashHelpers.Combine(hash, this.register.double_1.GetHashCode());
@@ -1562,93 +1597,93 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* dataPtr = stackalloc Byte[Count];
+ byte* dataPtr = stackalloc byte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Byte)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (byte)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (SByte)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (sbyte)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* dataPtr = stackalloc UInt16[Count];
+ ushort* dataPtr = stackalloc ushort[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt16)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (ushort)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int16)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (short)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* dataPtr = stackalloc UInt32[Count];
+ uint* dataPtr = stackalloc uint[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt32)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (uint)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int32)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (int)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* dataPtr = stackalloc UInt64[Count];
+ ulong* dataPtr = stackalloc ulong[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt64)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (ulong)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int64)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (long)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Single)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (float)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Double)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (double)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
@@ -1660,101 +1695,101 @@ namespace System.Numerics
else
{
Vector<T> sum = new Vector<T>();
- if (typeof(T) == typeof(Byte))
- {
- sum.register.byte_0 = (Byte)(left.register.byte_0 + right.register.byte_0);
- sum.register.byte_1 = (Byte)(left.register.byte_1 + right.register.byte_1);
- sum.register.byte_2 = (Byte)(left.register.byte_2 + right.register.byte_2);
- sum.register.byte_3 = (Byte)(left.register.byte_3 + right.register.byte_3);
- sum.register.byte_4 = (Byte)(left.register.byte_4 + right.register.byte_4);
- sum.register.byte_5 = (Byte)(left.register.byte_5 + right.register.byte_5);
- sum.register.byte_6 = (Byte)(left.register.byte_6 + right.register.byte_6);
- sum.register.byte_7 = (Byte)(left.register.byte_7 + right.register.byte_7);
- sum.register.byte_8 = (Byte)(left.register.byte_8 + right.register.byte_8);
- sum.register.byte_9 = (Byte)(left.register.byte_9 + right.register.byte_9);
- sum.register.byte_10 = (Byte)(left.register.byte_10 + right.register.byte_10);
- sum.register.byte_11 = (Byte)(left.register.byte_11 + right.register.byte_11);
- sum.register.byte_12 = (Byte)(left.register.byte_12 + right.register.byte_12);
- sum.register.byte_13 = (Byte)(left.register.byte_13 + right.register.byte_13);
- sum.register.byte_14 = (Byte)(left.register.byte_14 + right.register.byte_14);
- sum.register.byte_15 = (Byte)(left.register.byte_15 + right.register.byte_15);
- }
- else if (typeof(T) == typeof(SByte))
- {
- sum.register.sbyte_0 = (SByte)(left.register.sbyte_0 + right.register.sbyte_0);
- sum.register.sbyte_1 = (SByte)(left.register.sbyte_1 + right.register.sbyte_1);
- sum.register.sbyte_2 = (SByte)(left.register.sbyte_2 + right.register.sbyte_2);
- sum.register.sbyte_3 = (SByte)(left.register.sbyte_3 + right.register.sbyte_3);
- sum.register.sbyte_4 = (SByte)(left.register.sbyte_4 + right.register.sbyte_4);
- sum.register.sbyte_5 = (SByte)(left.register.sbyte_5 + right.register.sbyte_5);
- sum.register.sbyte_6 = (SByte)(left.register.sbyte_6 + right.register.sbyte_6);
- sum.register.sbyte_7 = (SByte)(left.register.sbyte_7 + right.register.sbyte_7);
- sum.register.sbyte_8 = (SByte)(left.register.sbyte_8 + right.register.sbyte_8);
- sum.register.sbyte_9 = (SByte)(left.register.sbyte_9 + right.register.sbyte_9);
- sum.register.sbyte_10 = (SByte)(left.register.sbyte_10 + right.register.sbyte_10);
- sum.register.sbyte_11 = (SByte)(left.register.sbyte_11 + right.register.sbyte_11);
- sum.register.sbyte_12 = (SByte)(left.register.sbyte_12 + right.register.sbyte_12);
- sum.register.sbyte_13 = (SByte)(left.register.sbyte_13 + right.register.sbyte_13);
- sum.register.sbyte_14 = (SByte)(left.register.sbyte_14 + right.register.sbyte_14);
- sum.register.sbyte_15 = (SByte)(left.register.sbyte_15 + right.register.sbyte_15);
- }
- else if (typeof(T) == typeof(UInt16))
- {
- sum.register.uint16_0 = (UInt16)(left.register.uint16_0 + right.register.uint16_0);
- sum.register.uint16_1 = (UInt16)(left.register.uint16_1 + right.register.uint16_1);
- sum.register.uint16_2 = (UInt16)(left.register.uint16_2 + right.register.uint16_2);
- sum.register.uint16_3 = (UInt16)(left.register.uint16_3 + right.register.uint16_3);
- sum.register.uint16_4 = (UInt16)(left.register.uint16_4 + right.register.uint16_4);
- sum.register.uint16_5 = (UInt16)(left.register.uint16_5 + right.register.uint16_5);
- sum.register.uint16_6 = (UInt16)(left.register.uint16_6 + right.register.uint16_6);
- sum.register.uint16_7 = (UInt16)(left.register.uint16_7 + right.register.uint16_7);
- }
- else if (typeof(T) == typeof(Int16))
- {
- sum.register.int16_0 = (Int16)(left.register.int16_0 + right.register.int16_0);
- sum.register.int16_1 = (Int16)(left.register.int16_1 + right.register.int16_1);
- sum.register.int16_2 = (Int16)(left.register.int16_2 + right.register.int16_2);
- sum.register.int16_3 = (Int16)(left.register.int16_3 + right.register.int16_3);
- sum.register.int16_4 = (Int16)(left.register.int16_4 + right.register.int16_4);
- sum.register.int16_5 = (Int16)(left.register.int16_5 + right.register.int16_5);
- sum.register.int16_6 = (Int16)(left.register.int16_6 + right.register.int16_6);
- sum.register.int16_7 = (Int16)(left.register.int16_7 + right.register.int16_7);
- }
- else if (typeof(T) == typeof(UInt32))
- {
- sum.register.uint32_0 = (UInt32)(left.register.uint32_0 + right.register.uint32_0);
- sum.register.uint32_1 = (UInt32)(left.register.uint32_1 + right.register.uint32_1);
- sum.register.uint32_2 = (UInt32)(left.register.uint32_2 + right.register.uint32_2);
- sum.register.uint32_3 = (UInt32)(left.register.uint32_3 + right.register.uint32_3);
- }
- else if (typeof(T) == typeof(Int32))
- {
- sum.register.int32_0 = (Int32)(left.register.int32_0 + right.register.int32_0);
- sum.register.int32_1 = (Int32)(left.register.int32_1 + right.register.int32_1);
- sum.register.int32_2 = (Int32)(left.register.int32_2 + right.register.int32_2);
- sum.register.int32_3 = (Int32)(left.register.int32_3 + right.register.int32_3);
- }
- else if (typeof(T) == typeof(UInt64))
- {
- sum.register.uint64_0 = (UInt64)(left.register.uint64_0 + right.register.uint64_0);
- sum.register.uint64_1 = (UInt64)(left.register.uint64_1 + right.register.uint64_1);
- }
- else if (typeof(T) == typeof(Int64))
- {
- sum.register.int64_0 = (Int64)(left.register.int64_0 + right.register.int64_0);
- sum.register.int64_1 = (Int64)(left.register.int64_1 + right.register.int64_1);
- }
- else if (typeof(T) == typeof(Single))
- {
- sum.register.single_0 = (Single)(left.register.single_0 + right.register.single_0);
- sum.register.single_1 = (Single)(left.register.single_1 + right.register.single_1);
- sum.register.single_2 = (Single)(left.register.single_2 + right.register.single_2);
- sum.register.single_3 = (Single)(left.register.single_3 + right.register.single_3);
- }
- else if (typeof(T) == typeof(Double))
- {
- sum.register.double_0 = (Double)(left.register.double_0 + right.register.double_0);
- sum.register.double_1 = (Double)(left.register.double_1 + right.register.double_1);
+ if (typeof(T) == typeof(byte))
+ {
+ sum.register.byte_0 = (byte)(left.register.byte_0 + right.register.byte_0);
+ sum.register.byte_1 = (byte)(left.register.byte_1 + right.register.byte_1);
+ sum.register.byte_2 = (byte)(left.register.byte_2 + right.register.byte_2);
+ sum.register.byte_3 = (byte)(left.register.byte_3 + right.register.byte_3);
+ sum.register.byte_4 = (byte)(left.register.byte_4 + right.register.byte_4);
+ sum.register.byte_5 = (byte)(left.register.byte_5 + right.register.byte_5);
+ sum.register.byte_6 = (byte)(left.register.byte_6 + right.register.byte_6);
+ sum.register.byte_7 = (byte)(left.register.byte_7 + right.register.byte_7);
+ sum.register.byte_8 = (byte)(left.register.byte_8 + right.register.byte_8);
+ sum.register.byte_9 = (byte)(left.register.byte_9 + right.register.byte_9);
+ sum.register.byte_10 = (byte)(left.register.byte_10 + right.register.byte_10);
+ sum.register.byte_11 = (byte)(left.register.byte_11 + right.register.byte_11);
+ sum.register.byte_12 = (byte)(left.register.byte_12 + right.register.byte_12);
+ sum.register.byte_13 = (byte)(left.register.byte_13 + right.register.byte_13);
+ sum.register.byte_14 = (byte)(left.register.byte_14 + right.register.byte_14);
+ sum.register.byte_15 = (byte)(left.register.byte_15 + right.register.byte_15);
+ }
+ else if (typeof(T) == typeof(sbyte))
+ {
+ sum.register.sbyte_0 = (sbyte)(left.register.sbyte_0 + right.register.sbyte_0);
+ sum.register.sbyte_1 = (sbyte)(left.register.sbyte_1 + right.register.sbyte_1);
+ sum.register.sbyte_2 = (sbyte)(left.register.sbyte_2 + right.register.sbyte_2);
+ sum.register.sbyte_3 = (sbyte)(left.register.sbyte_3 + right.register.sbyte_3);
+ sum.register.sbyte_4 = (sbyte)(left.register.sbyte_4 + right.register.sbyte_4);
+ sum.register.sbyte_5 = (sbyte)(left.register.sbyte_5 + right.register.sbyte_5);
+ sum.register.sbyte_6 = (sbyte)(left.register.sbyte_6 + right.register.sbyte_6);
+ sum.register.sbyte_7 = (sbyte)(left.register.sbyte_7 + right.register.sbyte_7);
+ sum.register.sbyte_8 = (sbyte)(left.register.sbyte_8 + right.register.sbyte_8);
+ sum.register.sbyte_9 = (sbyte)(left.register.sbyte_9 + right.register.sbyte_9);
+ sum.register.sbyte_10 = (sbyte)(left.register.sbyte_10 + right.register.sbyte_10);
+ sum.register.sbyte_11 = (sbyte)(left.register.sbyte_11 + right.register.sbyte_11);
+ sum.register.sbyte_12 = (sbyte)(left.register.sbyte_12 + right.register.sbyte_12);
+ sum.register.sbyte_13 = (sbyte)(left.register.sbyte_13 + right.register.sbyte_13);
+ sum.register.sbyte_14 = (sbyte)(left.register.sbyte_14 + right.register.sbyte_14);
+ sum.register.sbyte_15 = (sbyte)(left.register.sbyte_15 + right.register.sbyte_15);
+ }
+ else if (typeof(T) == typeof(ushort))
+ {
+ sum.register.uint16_0 = (ushort)(left.register.uint16_0 + right.register.uint16_0);
+ sum.register.uint16_1 = (ushort)(left.register.uint16_1 + right.register.uint16_1);
+ sum.register.uint16_2 = (ushort)(left.register.uint16_2 + right.register.uint16_2);
+ sum.register.uint16_3 = (ushort)(left.register.uint16_3 + right.register.uint16_3);
+ sum.register.uint16_4 = (ushort)(left.register.uint16_4 + right.register.uint16_4);
+ sum.register.uint16_5 = (ushort)(left.register.uint16_5 + right.register.uint16_5);
+ sum.register.uint16_6 = (ushort)(left.register.uint16_6 + right.register.uint16_6);
+ sum.register.uint16_7 = (ushort)(left.register.uint16_7 + right.register.uint16_7);
+ }
+ else if (typeof(T) == typeof(short))
+ {
+ sum.register.int16_0 = (short)(left.register.int16_0 + right.register.int16_0);
+ sum.register.int16_1 = (short)(left.register.int16_1 + right.register.int16_1);
+ sum.register.int16_2 = (short)(left.register.int16_2 + right.register.int16_2);
+ sum.register.int16_3 = (short)(left.register.int16_3 + right.register.int16_3);
+ sum.register.int16_4 = (short)(left.register.int16_4 + right.register.int16_4);
+ sum.register.int16_5 = (short)(left.register.int16_5 + right.register.int16_5);
+ sum.register.int16_6 = (short)(left.register.int16_6 + right.register.int16_6);
+ sum.register.int16_7 = (short)(left.register.int16_7 + right.register.int16_7);
+ }
+ else if (typeof(T) == typeof(uint))
+ {
+ sum.register.uint32_0 = (uint)(left.register.uint32_0 + right.register.uint32_0);
+ sum.register.uint32_1 = (uint)(left.register.uint32_1 + right.register.uint32_1);
+ sum.register.uint32_2 = (uint)(left.register.uint32_2 + right.register.uint32_2);
+ sum.register.uint32_3 = (uint)(left.register.uint32_3 + right.register.uint32_3);
+ }
+ else if (typeof(T) == typeof(int))
+ {
+ sum.register.int32_0 = (int)(left.register.int32_0 + right.register.int32_0);
+ sum.register.int32_1 = (int)(left.register.int32_1 + right.register.int32_1);
+ sum.register.int32_2 = (int)(left.register.int32_2 + right.register.int32_2);
+ sum.register.int32_3 = (int)(left.register.int32_3 + right.register.int32_3);
+ }
+ else if (typeof(T) == typeof(ulong))
+ {
+ sum.register.uint64_0 = (ulong)(left.register.uint64_0 + right.register.uint64_0);
+ sum.register.uint64_1 = (ulong)(left.register.uint64_1 + right.register.uint64_1);
+ }
+ else if (typeof(T) == typeof(long))
+ {
+ sum.register.int64_0 = (long)(left.register.int64_0 + right.register.int64_0);
+ sum.register.int64_1 = (long)(left.register.int64_1 + right.register.int64_1);
+ }
+ else if (typeof(T) == typeof(float))
+ {
+ sum.register.single_0 = (float)(left.register.single_0 + right.register.single_0);
+ sum.register.single_1 = (float)(left.register.single_1 + right.register.single_1);
+ sum.register.single_2 = (float)(left.register.single_2 + right.register.single_2);
+ sum.register.single_3 = (float)(left.register.single_3 + right.register.single_3);
+ }
+ else if (typeof(T) == typeof(double))
+ {
+ sum.register.double_0 = (double)(left.register.double_0 + right.register.double_0);
+ sum.register.double_1 = (double)(left.register.double_1 + right.register.double_1);
}
return sum;
}
@@ -1773,93 +1808,93 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* dataPtr = stackalloc Byte[Count];
+ byte* dataPtr = stackalloc byte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Byte)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (byte)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (SByte)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (sbyte)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* dataPtr = stackalloc UInt16[Count];
+ ushort* dataPtr = stackalloc ushort[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt16)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (ushort)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int16)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (short)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* dataPtr = stackalloc UInt32[Count];
+ uint* dataPtr = stackalloc uint[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt32)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (uint)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int32)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (int)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* dataPtr = stackalloc UInt64[Count];
+ ulong* dataPtr = stackalloc ulong[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt64)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (ulong)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int64)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (long)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Single)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (float)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Double)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (double)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
@@ -1871,101 +1906,101 @@ namespace System.Numerics
else
{
Vector<T> difference = new Vector<T>();
- if (typeof(T) == typeof(Byte))
- {
- difference.register.byte_0 = (Byte)(left.register.byte_0 - right.register.byte_0);
- difference.register.byte_1 = (Byte)(left.register.byte_1 - right.register.byte_1);
- difference.register.byte_2 = (Byte)(left.register.byte_2 - right.register.byte_2);
- difference.register.byte_3 = (Byte)(left.register.byte_3 - right.register.byte_3);
- difference.register.byte_4 = (Byte)(left.register.byte_4 - right.register.byte_4);
- difference.register.byte_5 = (Byte)(left.register.byte_5 - right.register.byte_5);
- difference.register.byte_6 = (Byte)(left.register.byte_6 - right.register.byte_6);
- difference.register.byte_7 = (Byte)(left.register.byte_7 - right.register.byte_7);
- difference.register.byte_8 = (Byte)(left.register.byte_8 - right.register.byte_8);
- difference.register.byte_9 = (Byte)(left.register.byte_9 - right.register.byte_9);
- difference.register.byte_10 = (Byte)(left.register.byte_10 - right.register.byte_10);
- difference.register.byte_11 = (Byte)(left.register.byte_11 - right.register.byte_11);
- difference.register.byte_12 = (Byte)(left.register.byte_12 - right.register.byte_12);
- difference.register.byte_13 = (Byte)(left.register.byte_13 - right.register.byte_13);
- difference.register.byte_14 = (Byte)(left.register.byte_14 - right.register.byte_14);
- difference.register.byte_15 = (Byte)(left.register.byte_15 - right.register.byte_15);
- }
- else if (typeof(T) == typeof(SByte))
- {
- difference.register.sbyte_0 = (SByte)(left.register.sbyte_0 - right.register.sbyte_0);
- difference.register.sbyte_1 = (SByte)(left.register.sbyte_1 - right.register.sbyte_1);
- difference.register.sbyte_2 = (SByte)(left.register.sbyte_2 - right.register.sbyte_2);
- difference.register.sbyte_3 = (SByte)(left.register.sbyte_3 - right.register.sbyte_3);
- difference.register.sbyte_4 = (SByte)(left.register.sbyte_4 - right.register.sbyte_4);
- difference.register.sbyte_5 = (SByte)(left.register.sbyte_5 - right.register.sbyte_5);
- difference.register.sbyte_6 = (SByte)(left.register.sbyte_6 - right.register.sbyte_6);
- difference.register.sbyte_7 = (SByte)(left.register.sbyte_7 - right.register.sbyte_7);
- difference.register.sbyte_8 = (SByte)(left.register.sbyte_8 - right.register.sbyte_8);
- difference.register.sbyte_9 = (SByte)(left.register.sbyte_9 - right.register.sbyte_9);
- difference.register.sbyte_10 = (SByte)(left.register.sbyte_10 - right.register.sbyte_10);
- difference.register.sbyte_11 = (SByte)(left.register.sbyte_11 - right.register.sbyte_11);
- difference.register.sbyte_12 = (SByte)(left.register.sbyte_12 - right.register.sbyte_12);
- difference.register.sbyte_13 = (SByte)(left.register.sbyte_13 - right.register.sbyte_13);
- difference.register.sbyte_14 = (SByte)(left.register.sbyte_14 - right.register.sbyte_14);
- difference.register.sbyte_15 = (SByte)(left.register.sbyte_15 - right.register.sbyte_15);
- }
- else if (typeof(T) == typeof(UInt16))
- {
- difference.register.uint16_0 = (UInt16)(left.register.uint16_0 - right.register.uint16_0);
- difference.register.uint16_1 = (UInt16)(left.register.uint16_1 - right.register.uint16_1);
- difference.register.uint16_2 = (UInt16)(left.register.uint16_2 - right.register.uint16_2);
- difference.register.uint16_3 = (UInt16)(left.register.uint16_3 - right.register.uint16_3);
- difference.register.uint16_4 = (UInt16)(left.register.uint16_4 - right.register.uint16_4);
- difference.register.uint16_5 = (UInt16)(left.register.uint16_5 - right.register.uint16_5);
- difference.register.uint16_6 = (UInt16)(left.register.uint16_6 - right.register.uint16_6);
- difference.register.uint16_7 = (UInt16)(left.register.uint16_7 - right.register.uint16_7);
- }
- else if (typeof(T) == typeof(Int16))
- {
- difference.register.int16_0 = (Int16)(left.register.int16_0 - right.register.int16_0);
- difference.register.int16_1 = (Int16)(left.register.int16_1 - right.register.int16_1);
- difference.register.int16_2 = (Int16)(left.register.int16_2 - right.register.int16_2);
- difference.register.int16_3 = (Int16)(left.register.int16_3 - right.register.int16_3);
- difference.register.int16_4 = (Int16)(left.register.int16_4 - right.register.int16_4);
- difference.register.int16_5 = (Int16)(left.register.int16_5 - right.register.int16_5);
- difference.register.int16_6 = (Int16)(left.register.int16_6 - right.register.int16_6);
- difference.register.int16_7 = (Int16)(left.register.int16_7 - right.register.int16_7);
- }
- else if (typeof(T) == typeof(UInt32))
- {
- difference.register.uint32_0 = (UInt32)(left.register.uint32_0 - right.register.uint32_0);
- difference.register.uint32_1 = (UInt32)(left.register.uint32_1 - right.register.uint32_1);
- difference.register.uint32_2 = (UInt32)(left.register.uint32_2 - right.register.uint32_2);
- difference.register.uint32_3 = (UInt32)(left.register.uint32_3 - right.register.uint32_3);
- }
- else if (typeof(T) == typeof(Int32))
- {
- difference.register.int32_0 = (Int32)(left.register.int32_0 - right.register.int32_0);
- difference.register.int32_1 = (Int32)(left.register.int32_1 - right.register.int32_1);
- difference.register.int32_2 = (Int32)(left.register.int32_2 - right.register.int32_2);
- difference.register.int32_3 = (Int32)(left.register.int32_3 - right.register.int32_3);
- }
- else if (typeof(T) == typeof(UInt64))
- {
- difference.register.uint64_0 = (UInt64)(left.register.uint64_0 - right.register.uint64_0);
- difference.register.uint64_1 = (UInt64)(left.register.uint64_1 - right.register.uint64_1);
- }
- else if (typeof(T) == typeof(Int64))
- {
- difference.register.int64_0 = (Int64)(left.register.int64_0 - right.register.int64_0);
- difference.register.int64_1 = (Int64)(left.register.int64_1 - right.register.int64_1);
- }
- else if (typeof(T) == typeof(Single))
- {
- difference.register.single_0 = (Single)(left.register.single_0 - right.register.single_0);
- difference.register.single_1 = (Single)(left.register.single_1 - right.register.single_1);
- difference.register.single_2 = (Single)(left.register.single_2 - right.register.single_2);
- difference.register.single_3 = (Single)(left.register.single_3 - right.register.single_3);
- }
- else if (typeof(T) == typeof(Double))
- {
- difference.register.double_0 = (Double)(left.register.double_0 - right.register.double_0);
- difference.register.double_1 = (Double)(left.register.double_1 - right.register.double_1);
+ if (typeof(T) == typeof(byte))
+ {
+ difference.register.byte_0 = (byte)(left.register.byte_0 - right.register.byte_0);
+ difference.register.byte_1 = (byte)(left.register.byte_1 - right.register.byte_1);
+ difference.register.byte_2 = (byte)(left.register.byte_2 - right.register.byte_2);
+ difference.register.byte_3 = (byte)(left.register.byte_3 - right.register.byte_3);
+ difference.register.byte_4 = (byte)(left.register.byte_4 - right.register.byte_4);
+ difference.register.byte_5 = (byte)(left.register.byte_5 - right.register.byte_5);
+ difference.register.byte_6 = (byte)(left.register.byte_6 - right.register.byte_6);
+ difference.register.byte_7 = (byte)(left.register.byte_7 - right.register.byte_7);
+ difference.register.byte_8 = (byte)(left.register.byte_8 - right.register.byte_8);
+ difference.register.byte_9 = (byte)(left.register.byte_9 - right.register.byte_9);
+ difference.register.byte_10 = (byte)(left.register.byte_10 - right.register.byte_10);
+ difference.register.byte_11 = (byte)(left.register.byte_11 - right.register.byte_11);
+ difference.register.byte_12 = (byte)(left.register.byte_12 - right.register.byte_12);
+ difference.register.byte_13 = (byte)(left.register.byte_13 - right.register.byte_13);
+ difference.register.byte_14 = (byte)(left.register.byte_14 - right.register.byte_14);
+ difference.register.byte_15 = (byte)(left.register.byte_15 - right.register.byte_15);
+ }
+ else if (typeof(T) == typeof(sbyte))
+ {
+ difference.register.sbyte_0 = (sbyte)(left.register.sbyte_0 - right.register.sbyte_0);
+ difference.register.sbyte_1 = (sbyte)(left.register.sbyte_1 - right.register.sbyte_1);
+ difference.register.sbyte_2 = (sbyte)(left.register.sbyte_2 - right.register.sbyte_2);
+ difference.register.sbyte_3 = (sbyte)(left.register.sbyte_3 - right.register.sbyte_3);
+ difference.register.sbyte_4 = (sbyte)(left.register.sbyte_4 - right.register.sbyte_4);
+ difference.register.sbyte_5 = (sbyte)(left.register.sbyte_5 - right.register.sbyte_5);
+ difference.register.sbyte_6 = (sbyte)(left.register.sbyte_6 - right.register.sbyte_6);
+ difference.register.sbyte_7 = (sbyte)(left.register.sbyte_7 - right.register.sbyte_7);
+ difference.register.sbyte_8 = (sbyte)(left.register.sbyte_8 - right.register.sbyte_8);
+ difference.register.sbyte_9 = (sbyte)(left.register.sbyte_9 - right.register.sbyte_9);
+ difference.register.sbyte_10 = (sbyte)(left.register.sbyte_10 - right.register.sbyte_10);
+ difference.register.sbyte_11 = (sbyte)(left.register.sbyte_11 - right.register.sbyte_11);
+ difference.register.sbyte_12 = (sbyte)(left.register.sbyte_12 - right.register.sbyte_12);
+ difference.register.sbyte_13 = (sbyte)(left.register.sbyte_13 - right.register.sbyte_13);
+ difference.register.sbyte_14 = (sbyte)(left.register.sbyte_14 - right.register.sbyte_14);
+ difference.register.sbyte_15 = (sbyte)(left.register.sbyte_15 - right.register.sbyte_15);
+ }
+ else if (typeof(T) == typeof(ushort))
+ {
+ difference.register.uint16_0 = (ushort)(left.register.uint16_0 - right.register.uint16_0);
+ difference.register.uint16_1 = (ushort)(left.register.uint16_1 - right.register.uint16_1);
+ difference.register.uint16_2 = (ushort)(left.register.uint16_2 - right.register.uint16_2);
+ difference.register.uint16_3 = (ushort)(left.register.uint16_3 - right.register.uint16_3);
+ difference.register.uint16_4 = (ushort)(left.register.uint16_4 - right.register.uint16_4);
+ difference.register.uint16_5 = (ushort)(left.register.uint16_5 - right.register.uint16_5);
+ difference.register.uint16_6 = (ushort)(left.register.uint16_6 - right.register.uint16_6);
+ difference.register.uint16_7 = (ushort)(left.register.uint16_7 - right.register.uint16_7);
+ }
+ else if (typeof(T) == typeof(short))
+ {
+ difference.register.int16_0 = (short)(left.register.int16_0 - right.register.int16_0);
+ difference.register.int16_1 = (short)(left.register.int16_1 - right.register.int16_1);
+ difference.register.int16_2 = (short)(left.register.int16_2 - right.register.int16_2);
+ difference.register.int16_3 = (short)(left.register.int16_3 - right.register.int16_3);
+ difference.register.int16_4 = (short)(left.register.int16_4 - right.register.int16_4);
+ difference.register.int16_5 = (short)(left.register.int16_5 - right.register.int16_5);
+ difference.register.int16_6 = (short)(left.register.int16_6 - right.register.int16_6);
+ difference.register.int16_7 = (short)(left.register.int16_7 - right.register.int16_7);
+ }
+ else if (typeof(T) == typeof(uint))
+ {
+ difference.register.uint32_0 = (uint)(left.register.uint32_0 - right.register.uint32_0);
+ difference.register.uint32_1 = (uint)(left.register.uint32_1 - right.register.uint32_1);
+ difference.register.uint32_2 = (uint)(left.register.uint32_2 - right.register.uint32_2);
+ difference.register.uint32_3 = (uint)(left.register.uint32_3 - right.register.uint32_3);
+ }
+ else if (typeof(T) == typeof(int))
+ {
+ difference.register.int32_0 = (int)(left.register.int32_0 - right.register.int32_0);
+ difference.register.int32_1 = (int)(left.register.int32_1 - right.register.int32_1);
+ difference.register.int32_2 = (int)(left.register.int32_2 - right.register.int32_2);
+ difference.register.int32_3 = (int)(left.register.int32_3 - right.register.int32_3);
+ }
+ else if (typeof(T) == typeof(ulong))
+ {
+ difference.register.uint64_0 = (ulong)(left.register.uint64_0 - right.register.uint64_0);
+ difference.register.uint64_1 = (ulong)(left.register.uint64_1 - right.register.uint64_1);
+ }
+ else if (typeof(T) == typeof(long))
+ {
+ difference.register.int64_0 = (long)(left.register.int64_0 - right.register.int64_0);
+ difference.register.int64_1 = (long)(left.register.int64_1 - right.register.int64_1);
+ }
+ else if (typeof(T) == typeof(float))
+ {
+ difference.register.single_0 = (float)(left.register.single_0 - right.register.single_0);
+ difference.register.single_1 = (float)(left.register.single_1 - right.register.single_1);
+ difference.register.single_2 = (float)(left.register.single_2 - right.register.single_2);
+ difference.register.single_3 = (float)(left.register.single_3 - right.register.single_3);
+ }
+ else if (typeof(T) == typeof(double))
+ {
+ difference.register.double_0 = (double)(left.register.double_0 - right.register.double_0);
+ difference.register.double_1 = (double)(left.register.double_1 - right.register.double_1);
}
return difference;
}
@@ -1985,93 +2020,93 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* dataPtr = stackalloc Byte[Count];
+ byte* dataPtr = stackalloc byte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Byte)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (byte)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (SByte)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (sbyte)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* dataPtr = stackalloc UInt16[Count];
+ ushort* dataPtr = stackalloc ushort[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt16)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (ushort)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int16)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (short)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* dataPtr = stackalloc UInt32[Count];
+ uint* dataPtr = stackalloc uint[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt32)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (uint)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int32)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (int)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* dataPtr = stackalloc UInt64[Count];
+ ulong* dataPtr = stackalloc ulong[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt64)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (ulong)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int64)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (long)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Single)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (float)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Double)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (double)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
@@ -2083,101 +2118,101 @@ namespace System.Numerics
else
{
Vector<T> product = new Vector<T>();
- if (typeof(T) == typeof(Byte))
- {
- product.register.byte_0 = (Byte)(left.register.byte_0 * right.register.byte_0);
- product.register.byte_1 = (Byte)(left.register.byte_1 * right.register.byte_1);
- product.register.byte_2 = (Byte)(left.register.byte_2 * right.register.byte_2);
- product.register.byte_3 = (Byte)(left.register.byte_3 * right.register.byte_3);
- product.register.byte_4 = (Byte)(left.register.byte_4 * right.register.byte_4);
- product.register.byte_5 = (Byte)(left.register.byte_5 * right.register.byte_5);
- product.register.byte_6 = (Byte)(left.register.byte_6 * right.register.byte_6);
- product.register.byte_7 = (Byte)(left.register.byte_7 * right.register.byte_7);
- product.register.byte_8 = (Byte)(left.register.byte_8 * right.register.byte_8);
- product.register.byte_9 = (Byte)(left.register.byte_9 * right.register.byte_9);
- product.register.byte_10 = (Byte)(left.register.byte_10 * right.register.byte_10);
- product.register.byte_11 = (Byte)(left.register.byte_11 * right.register.byte_11);
- product.register.byte_12 = (Byte)(left.register.byte_12 * right.register.byte_12);
- product.register.byte_13 = (Byte)(left.register.byte_13 * right.register.byte_13);
- product.register.byte_14 = (Byte)(left.register.byte_14 * right.register.byte_14);
- product.register.byte_15 = (Byte)(left.register.byte_15 * right.register.byte_15);
- }
- else if (typeof(T) == typeof(SByte))
- {
- product.register.sbyte_0 = (SByte)(left.register.sbyte_0 * right.register.sbyte_0);
- product.register.sbyte_1 = (SByte)(left.register.sbyte_1 * right.register.sbyte_1);
- product.register.sbyte_2 = (SByte)(left.register.sbyte_2 * right.register.sbyte_2);
- product.register.sbyte_3 = (SByte)(left.register.sbyte_3 * right.register.sbyte_3);
- product.register.sbyte_4 = (SByte)(left.register.sbyte_4 * right.register.sbyte_4);
- product.register.sbyte_5 = (SByte)(left.register.sbyte_5 * right.register.sbyte_5);
- product.register.sbyte_6 = (SByte)(left.register.sbyte_6 * right.register.sbyte_6);
- product.register.sbyte_7 = (SByte)(left.register.sbyte_7 * right.register.sbyte_7);
- product.register.sbyte_8 = (SByte)(left.register.sbyte_8 * right.register.sbyte_8);
- product.register.sbyte_9 = (SByte)(left.register.sbyte_9 * right.register.sbyte_9);
- product.register.sbyte_10 = (SByte)(left.register.sbyte_10 * right.register.sbyte_10);
- product.register.sbyte_11 = (SByte)(left.register.sbyte_11 * right.register.sbyte_11);
- product.register.sbyte_12 = (SByte)(left.register.sbyte_12 * right.register.sbyte_12);
- product.register.sbyte_13 = (SByte)(left.register.sbyte_13 * right.register.sbyte_13);
- product.register.sbyte_14 = (SByte)(left.register.sbyte_14 * right.register.sbyte_14);
- product.register.sbyte_15 = (SByte)(left.register.sbyte_15 * right.register.sbyte_15);
- }
- else if (typeof(T) == typeof(UInt16))
- {
- product.register.uint16_0 = (UInt16)(left.register.uint16_0 * right.register.uint16_0);
- product.register.uint16_1 = (UInt16)(left.register.uint16_1 * right.register.uint16_1);
- product.register.uint16_2 = (UInt16)(left.register.uint16_2 * right.register.uint16_2);
- product.register.uint16_3 = (UInt16)(left.register.uint16_3 * right.register.uint16_3);
- product.register.uint16_4 = (UInt16)(left.register.uint16_4 * right.register.uint16_4);
- product.register.uint16_5 = (UInt16)(left.register.uint16_5 * right.register.uint16_5);
- product.register.uint16_6 = (UInt16)(left.register.uint16_6 * right.register.uint16_6);
- product.register.uint16_7 = (UInt16)(left.register.uint16_7 * right.register.uint16_7);
- }
- else if (typeof(T) == typeof(Int16))
- {
- product.register.int16_0 = (Int16)(left.register.int16_0 * right.register.int16_0);
- product.register.int16_1 = (Int16)(left.register.int16_1 * right.register.int16_1);
- product.register.int16_2 = (Int16)(left.register.int16_2 * right.register.int16_2);
- product.register.int16_3 = (Int16)(left.register.int16_3 * right.register.int16_3);
- product.register.int16_4 = (Int16)(left.register.int16_4 * right.register.int16_4);
- product.register.int16_5 = (Int16)(left.register.int16_5 * right.register.int16_5);
- product.register.int16_6 = (Int16)(left.register.int16_6 * right.register.int16_6);
- product.register.int16_7 = (Int16)(left.register.int16_7 * right.register.int16_7);
- }
- else if (typeof(T) == typeof(UInt32))
- {
- product.register.uint32_0 = (UInt32)(left.register.uint32_0 * right.register.uint32_0);
- product.register.uint32_1 = (UInt32)(left.register.uint32_1 * right.register.uint32_1);
- product.register.uint32_2 = (UInt32)(left.register.uint32_2 * right.register.uint32_2);
- product.register.uint32_3 = (UInt32)(left.register.uint32_3 * right.register.uint32_3);
- }
- else if (typeof(T) == typeof(Int32))
- {
- product.register.int32_0 = (Int32)(left.register.int32_0 * right.register.int32_0);
- product.register.int32_1 = (Int32)(left.register.int32_1 * right.register.int32_1);
- product.register.int32_2 = (Int32)(left.register.int32_2 * right.register.int32_2);
- product.register.int32_3 = (Int32)(left.register.int32_3 * right.register.int32_3);
- }
- else if (typeof(T) == typeof(UInt64))
- {
- product.register.uint64_0 = (UInt64)(left.register.uint64_0 * right.register.uint64_0);
- product.register.uint64_1 = (UInt64)(left.register.uint64_1 * right.register.uint64_1);
- }
- else if (typeof(T) == typeof(Int64))
- {
- product.register.int64_0 = (Int64)(left.register.int64_0 * right.register.int64_0);
- product.register.int64_1 = (Int64)(left.register.int64_1 * right.register.int64_1);
- }
- else if (typeof(T) == typeof(Single))
- {
- product.register.single_0 = (Single)(left.register.single_0 * right.register.single_0);
- product.register.single_1 = (Single)(left.register.single_1 * right.register.single_1);
- product.register.single_2 = (Single)(left.register.single_2 * right.register.single_2);
- product.register.single_3 = (Single)(left.register.single_3 * right.register.single_3);
- }
- else if (typeof(T) == typeof(Double))
- {
- product.register.double_0 = (Double)(left.register.double_0 * right.register.double_0);
- product.register.double_1 = (Double)(left.register.double_1 * right.register.double_1);
+ if (typeof(T) == typeof(byte))
+ {
+ product.register.byte_0 = (byte)(left.register.byte_0 * right.register.byte_0);
+ product.register.byte_1 = (byte)(left.register.byte_1 * right.register.byte_1);
+ product.register.byte_2 = (byte)(left.register.byte_2 * right.register.byte_2);
+ product.register.byte_3 = (byte)(left.register.byte_3 * right.register.byte_3);
+ product.register.byte_4 = (byte)(left.register.byte_4 * right.register.byte_4);
+ product.register.byte_5 = (byte)(left.register.byte_5 * right.register.byte_5);
+ product.register.byte_6 = (byte)(left.register.byte_6 * right.register.byte_6);
+ product.register.byte_7 = (byte)(left.register.byte_7 * right.register.byte_7);
+ product.register.byte_8 = (byte)(left.register.byte_8 * right.register.byte_8);
+ product.register.byte_9 = (byte)(left.register.byte_9 * right.register.byte_9);
+ product.register.byte_10 = (byte)(left.register.byte_10 * right.register.byte_10);
+ product.register.byte_11 = (byte)(left.register.byte_11 * right.register.byte_11);
+ product.register.byte_12 = (byte)(left.register.byte_12 * right.register.byte_12);
+ product.register.byte_13 = (byte)(left.register.byte_13 * right.register.byte_13);
+ product.register.byte_14 = (byte)(left.register.byte_14 * right.register.byte_14);
+ product.register.byte_15 = (byte)(left.register.byte_15 * right.register.byte_15);
+ }
+ else if (typeof(T) == typeof(sbyte))
+ {
+ product.register.sbyte_0 = (sbyte)(left.register.sbyte_0 * right.register.sbyte_0);
+ product.register.sbyte_1 = (sbyte)(left.register.sbyte_1 * right.register.sbyte_1);
+ product.register.sbyte_2 = (sbyte)(left.register.sbyte_2 * right.register.sbyte_2);
+ product.register.sbyte_3 = (sbyte)(left.register.sbyte_3 * right.register.sbyte_3);
+ product.register.sbyte_4 = (sbyte)(left.register.sbyte_4 * right.register.sbyte_4);
+ product.register.sbyte_5 = (sbyte)(left.register.sbyte_5 * right.register.sbyte_5);
+ product.register.sbyte_6 = (sbyte)(left.register.sbyte_6 * right.register.sbyte_6);
+ product.register.sbyte_7 = (sbyte)(left.register.sbyte_7 * right.register.sbyte_7);
+ product.register.sbyte_8 = (sbyte)(left.register.sbyte_8 * right.register.sbyte_8);
+ product.register.sbyte_9 = (sbyte)(left.register.sbyte_9 * right.register.sbyte_9);
+ product.register.sbyte_10 = (sbyte)(left.register.sbyte_10 * right.register.sbyte_10);
+ product.register.sbyte_11 = (sbyte)(left.register.sbyte_11 * right.register.sbyte_11);
+ product.register.sbyte_12 = (sbyte)(left.register.sbyte_12 * right.register.sbyte_12);
+ product.register.sbyte_13 = (sbyte)(left.register.sbyte_13 * right.register.sbyte_13);
+ product.register.sbyte_14 = (sbyte)(left.register.sbyte_14 * right.register.sbyte_14);
+ product.register.sbyte_15 = (sbyte)(left.register.sbyte_15 * right.register.sbyte_15);
+ }
+ else if (typeof(T) == typeof(ushort))
+ {
+ product.register.uint16_0 = (ushort)(left.register.uint16_0 * right.register.uint16_0);
+ product.register.uint16_1 = (ushort)(left.register.uint16_1 * right.register.uint16_1);
+ product.register.uint16_2 = (ushort)(left.register.uint16_2 * right.register.uint16_2);
+ product.register.uint16_3 = (ushort)(left.register.uint16_3 * right.register.uint16_3);
+ product.register.uint16_4 = (ushort)(left.register.uint16_4 * right.register.uint16_4);
+ product.register.uint16_5 = (ushort)(left.register.uint16_5 * right.register.uint16_5);
+ product.register.uint16_6 = (ushort)(left.register.uint16_6 * right.register.uint16_6);
+ product.register.uint16_7 = (ushort)(left.register.uint16_7 * right.register.uint16_7);
+ }
+ else if (typeof(T) == typeof(short))
+ {
+ product.register.int16_0 = (short)(left.register.int16_0 * right.register.int16_0);
+ product.register.int16_1 = (short)(left.register.int16_1 * right.register.int16_1);
+ product.register.int16_2 = (short)(left.register.int16_2 * right.register.int16_2);
+ product.register.int16_3 = (short)(left.register.int16_3 * right.register.int16_3);
+ product.register.int16_4 = (short)(left.register.int16_4 * right.register.int16_4);
+ product.register.int16_5 = (short)(left.register.int16_5 * right.register.int16_5);
+ product.register.int16_6 = (short)(left.register.int16_6 * right.register.int16_6);
+ product.register.int16_7 = (short)(left.register.int16_7 * right.register.int16_7);
+ }
+ else if (typeof(T) == typeof(uint))
+ {
+ product.register.uint32_0 = (uint)(left.register.uint32_0 * right.register.uint32_0);
+ product.register.uint32_1 = (uint)(left.register.uint32_1 * right.register.uint32_1);
+ product.register.uint32_2 = (uint)(left.register.uint32_2 * right.register.uint32_2);
+ product.register.uint32_3 = (uint)(left.register.uint32_3 * right.register.uint32_3);
+ }
+ else if (typeof(T) == typeof(int))
+ {
+ product.register.int32_0 = (int)(left.register.int32_0 * right.register.int32_0);
+ product.register.int32_1 = (int)(left.register.int32_1 * right.register.int32_1);
+ product.register.int32_2 = (int)(left.register.int32_2 * right.register.int32_2);
+ product.register.int32_3 = (int)(left.register.int32_3 * right.register.int32_3);
+ }
+ else if (typeof(T) == typeof(ulong))
+ {
+ product.register.uint64_0 = (ulong)(left.register.uint64_0 * right.register.uint64_0);
+ product.register.uint64_1 = (ulong)(left.register.uint64_1 * right.register.uint64_1);
+ }
+ else if (typeof(T) == typeof(long))
+ {
+ product.register.int64_0 = (long)(left.register.int64_0 * right.register.int64_0);
+ product.register.int64_1 = (long)(left.register.int64_1 * right.register.int64_1);
+ }
+ else if (typeof(T) == typeof(float))
+ {
+ product.register.single_0 = (float)(left.register.single_0 * right.register.single_0);
+ product.register.single_1 = (float)(left.register.single_1 * right.register.single_1);
+ product.register.single_2 = (float)(left.register.single_2 * right.register.single_2);
+ product.register.single_3 = (float)(left.register.single_3 * right.register.single_3);
+ }
+ else if (typeof(T) == typeof(double))
+ {
+ product.register.double_0 = (double)(left.register.double_0 * right.register.double_0);
+ product.register.double_1 = (double)(left.register.double_1 * right.register.double_1);
}
return product;
}
@@ -2202,101 +2237,101 @@ namespace System.Numerics
else
{
Vector<T> product = new Vector<T>();
- if (typeof(T) == typeof(Byte))
- {
- product.register.byte_0 = (Byte)(value.register.byte_0 * (Byte)(object)factor);
- product.register.byte_1 = (Byte)(value.register.byte_1 * (Byte)(object)factor);
- product.register.byte_2 = (Byte)(value.register.byte_2 * (Byte)(object)factor);
- product.register.byte_3 = (Byte)(value.register.byte_3 * (Byte)(object)factor);
- product.register.byte_4 = (Byte)(value.register.byte_4 * (Byte)(object)factor);
- product.register.byte_5 = (Byte)(value.register.byte_5 * (Byte)(object)factor);
- product.register.byte_6 = (Byte)(value.register.byte_6 * (Byte)(object)factor);
- product.register.byte_7 = (Byte)(value.register.byte_7 * (Byte)(object)factor);
- product.register.byte_8 = (Byte)(value.register.byte_8 * (Byte)(object)factor);
- product.register.byte_9 = (Byte)(value.register.byte_9 * (Byte)(object)factor);
- product.register.byte_10 = (Byte)(value.register.byte_10 * (Byte)(object)factor);
- product.register.byte_11 = (Byte)(value.register.byte_11 * (Byte)(object)factor);
- product.register.byte_12 = (Byte)(value.register.byte_12 * (Byte)(object)factor);
- product.register.byte_13 = (Byte)(value.register.byte_13 * (Byte)(object)factor);
- product.register.byte_14 = (Byte)(value.register.byte_14 * (Byte)(object)factor);
- product.register.byte_15 = (Byte)(value.register.byte_15 * (Byte)(object)factor);
- }
- else if (typeof(T) == typeof(SByte))
- {
- product.register.sbyte_0 = (SByte)(value.register.sbyte_0 * (SByte)(object)factor);
- product.register.sbyte_1 = (SByte)(value.register.sbyte_1 * (SByte)(object)factor);
- product.register.sbyte_2 = (SByte)(value.register.sbyte_2 * (SByte)(object)factor);
- product.register.sbyte_3 = (SByte)(value.register.sbyte_3 * (SByte)(object)factor);
- product.register.sbyte_4 = (SByte)(value.register.sbyte_4 * (SByte)(object)factor);
- product.register.sbyte_5 = (SByte)(value.register.sbyte_5 * (SByte)(object)factor);
- product.register.sbyte_6 = (SByte)(value.register.sbyte_6 * (SByte)(object)factor);
- product.register.sbyte_7 = (SByte)(value.register.sbyte_7 * (SByte)(object)factor);
- product.register.sbyte_8 = (SByte)(value.register.sbyte_8 * (SByte)(object)factor);
- product.register.sbyte_9 = (SByte)(value.register.sbyte_9 * (SByte)(object)factor);
- product.register.sbyte_10 = (SByte)(value.register.sbyte_10 * (SByte)(object)factor);
- product.register.sbyte_11 = (SByte)(value.register.sbyte_11 * (SByte)(object)factor);
- product.register.sbyte_12 = (SByte)(value.register.sbyte_12 * (SByte)(object)factor);
- product.register.sbyte_13 = (SByte)(value.register.sbyte_13 * (SByte)(object)factor);
- product.register.sbyte_14 = (SByte)(value.register.sbyte_14 * (SByte)(object)factor);
- product.register.sbyte_15 = (SByte)(value.register.sbyte_15 * (SByte)(object)factor);
- }
- else if (typeof(T) == typeof(UInt16))
- {
- product.register.uint16_0 = (UInt16)(value.register.uint16_0 * (UInt16)(object)factor);
- product.register.uint16_1 = (UInt16)(value.register.uint16_1 * (UInt16)(object)factor);
- product.register.uint16_2 = (UInt16)(value.register.uint16_2 * (UInt16)(object)factor);
- product.register.uint16_3 = (UInt16)(value.register.uint16_3 * (UInt16)(object)factor);
- product.register.uint16_4 = (UInt16)(value.register.uint16_4 * (UInt16)(object)factor);
- product.register.uint16_5 = (UInt16)(value.register.uint16_5 * (UInt16)(object)factor);
- product.register.uint16_6 = (UInt16)(value.register.uint16_6 * (UInt16)(object)factor);
- product.register.uint16_7 = (UInt16)(value.register.uint16_7 * (UInt16)(object)factor);
- }
- else if (typeof(T) == typeof(Int16))
- {
- product.register.int16_0 = (Int16)(value.register.int16_0 * (Int16)(object)factor);
- product.register.int16_1 = (Int16)(value.register.int16_1 * (Int16)(object)factor);
- product.register.int16_2 = (Int16)(value.register.int16_2 * (Int16)(object)factor);
- product.register.int16_3 = (Int16)(value.register.int16_3 * (Int16)(object)factor);
- product.register.int16_4 = (Int16)(value.register.int16_4 * (Int16)(object)factor);
- product.register.int16_5 = (Int16)(value.register.int16_5 * (Int16)(object)factor);
- product.register.int16_6 = (Int16)(value.register.int16_6 * (Int16)(object)factor);
- product.register.int16_7 = (Int16)(value.register.int16_7 * (Int16)(object)factor);
- }
- else if (typeof(T) == typeof(UInt32))
- {
- product.register.uint32_0 = (UInt32)(value.register.uint32_0 * (UInt32)(object)factor);
- product.register.uint32_1 = (UInt32)(value.register.uint32_1 * (UInt32)(object)factor);
- product.register.uint32_2 = (UInt32)(value.register.uint32_2 * (UInt32)(object)factor);
- product.register.uint32_3 = (UInt32)(value.register.uint32_3 * (UInt32)(object)factor);
- }
- else if (typeof(T) == typeof(Int32))
- {
- product.register.int32_0 = (Int32)(value.register.int32_0 * (Int32)(object)factor);
- product.register.int32_1 = (Int32)(value.register.int32_1 * (Int32)(object)factor);
- product.register.int32_2 = (Int32)(value.register.int32_2 * (Int32)(object)factor);
- product.register.int32_3 = (Int32)(value.register.int32_3 * (Int32)(object)factor);
- }
- else if (typeof(T) == typeof(UInt64))
- {
- product.register.uint64_0 = (UInt64)(value.register.uint64_0 * (UInt64)(object)factor);
- product.register.uint64_1 = (UInt64)(value.register.uint64_1 * (UInt64)(object)factor);
- }
- else if (typeof(T) == typeof(Int64))
- {
- product.register.int64_0 = (Int64)(value.register.int64_0 * (Int64)(object)factor);
- product.register.int64_1 = (Int64)(value.register.int64_1 * (Int64)(object)factor);
- }
- else if (typeof(T) == typeof(Single))
- {
- product.register.single_0 = (Single)(value.register.single_0 * (Single)(object)factor);
- product.register.single_1 = (Single)(value.register.single_1 * (Single)(object)factor);
- product.register.single_2 = (Single)(value.register.single_2 * (Single)(object)factor);
- product.register.single_3 = (Single)(value.register.single_3 * (Single)(object)factor);
- }
- else if (typeof(T) == typeof(Double))
- {
- product.register.double_0 = (Double)(value.register.double_0 * (Double)(object)factor);
- product.register.double_1 = (Double)(value.register.double_1 * (Double)(object)factor);
+ if (typeof(T) == typeof(byte))
+ {
+ product.register.byte_0 = (byte)(value.register.byte_0 * (byte)(object)factor);
+ product.register.byte_1 = (byte)(value.register.byte_1 * (byte)(object)factor);
+ product.register.byte_2 = (byte)(value.register.byte_2 * (byte)(object)factor);
+ product.register.byte_3 = (byte)(value.register.byte_3 * (byte)(object)factor);
+ product.register.byte_4 = (byte)(value.register.byte_4 * (byte)(object)factor);
+ product.register.byte_5 = (byte)(value.register.byte_5 * (byte)(object)factor);
+ product.register.byte_6 = (byte)(value.register.byte_6 * (byte)(object)factor);
+ product.register.byte_7 = (byte)(value.register.byte_7 * (byte)(object)factor);
+ product.register.byte_8 = (byte)(value.register.byte_8 * (byte)(object)factor);
+ product.register.byte_9 = (byte)(value.register.byte_9 * (byte)(object)factor);
+ product.register.byte_10 = (byte)(value.register.byte_10 * (byte)(object)factor);
+ product.register.byte_11 = (byte)(value.register.byte_11 * (byte)(object)factor);
+ product.register.byte_12 = (byte)(value.register.byte_12 * (byte)(object)factor);
+ product.register.byte_13 = (byte)(value.register.byte_13 * (byte)(object)factor);
+ product.register.byte_14 = (byte)(value.register.byte_14 * (byte)(object)factor);
+ product.register.byte_15 = (byte)(value.register.byte_15 * (byte)(object)factor);
+ }
+ else if (typeof(T) == typeof(sbyte))
+ {
+ product.register.sbyte_0 = (sbyte)(value.register.sbyte_0 * (sbyte)(object)factor);
+ product.register.sbyte_1 = (sbyte)(value.register.sbyte_1 * (sbyte)(object)factor);
+ product.register.sbyte_2 = (sbyte)(value.register.sbyte_2 * (sbyte)(object)factor);
+ product.register.sbyte_3 = (sbyte)(value.register.sbyte_3 * (sbyte)(object)factor);
+ product.register.sbyte_4 = (sbyte)(value.register.sbyte_4 * (sbyte)(object)factor);
+ product.register.sbyte_5 = (sbyte)(value.register.sbyte_5 * (sbyte)(object)factor);
+ product.register.sbyte_6 = (sbyte)(value.register.sbyte_6 * (sbyte)(object)factor);
+ product.register.sbyte_7 = (sbyte)(value.register.sbyte_7 * (sbyte)(object)factor);
+ product.register.sbyte_8 = (sbyte)(value.register.sbyte_8 * (sbyte)(object)factor);
+ product.register.sbyte_9 = (sbyte)(value.register.sbyte_9 * (sbyte)(object)factor);
+ product.register.sbyte_10 = (sbyte)(value.register.sbyte_10 * (sbyte)(object)factor);
+ product.register.sbyte_11 = (sbyte)(value.register.sbyte_11 * (sbyte)(object)factor);
+ product.register.sbyte_12 = (sbyte)(value.register.sbyte_12 * (sbyte)(object)factor);
+ product.register.sbyte_13 = (sbyte)(value.register.sbyte_13 * (sbyte)(object)factor);
+ product.register.sbyte_14 = (sbyte)(value.register.sbyte_14 * (sbyte)(object)factor);
+ product.register.sbyte_15 = (sbyte)(value.register.sbyte_15 * (sbyte)(object)factor);
+ }
+ else if (typeof(T) == typeof(ushort))
+ {
+ product.register.uint16_0 = (ushort)(value.register.uint16_0 * (ushort)(object)factor);
+ product.register.uint16_1 = (ushort)(value.register.uint16_1 * (ushort)(object)factor);
+ product.register.uint16_2 = (ushort)(value.register.uint16_2 * (ushort)(object)factor);
+ product.register.uint16_3 = (ushort)(value.register.uint16_3 * (ushort)(object)factor);
+ product.register.uint16_4 = (ushort)(value.register.uint16_4 * (ushort)(object)factor);
+ product.register.uint16_5 = (ushort)(value.register.uint16_5 * (ushort)(object)factor);
+ product.register.uint16_6 = (ushort)(value.register.uint16_6 * (ushort)(object)factor);
+ product.register.uint16_7 = (ushort)(value.register.uint16_7 * (ushort)(object)factor);
+ }
+ else if (typeof(T) == typeof(short))
+ {
+ product.register.int16_0 = (short)(value.register.int16_0 * (short)(object)factor);
+ product.register.int16_1 = (short)(value.register.int16_1 * (short)(object)factor);
+ product.register.int16_2 = (short)(value.register.int16_2 * (short)(object)factor);
+ product.register.int16_3 = (short)(value.register.int16_3 * (short)(object)factor);
+ product.register.int16_4 = (short)(value.register.int16_4 * (short)(object)factor);
+ product.register.int16_5 = (short)(value.register.int16_5 * (short)(object)factor);
+ product.register.int16_6 = (short)(value.register.int16_6 * (short)(object)factor);
+ product.register.int16_7 = (short)(value.register.int16_7 * (short)(object)factor);
+ }
+ else if (typeof(T) == typeof(uint))
+ {
+ product.register.uint32_0 = (uint)(value.register.uint32_0 * (uint)(object)factor);
+ product.register.uint32_1 = (uint)(value.register.uint32_1 * (uint)(object)factor);
+ product.register.uint32_2 = (uint)(value.register.uint32_2 * (uint)(object)factor);
+ product.register.uint32_3 = (uint)(value.register.uint32_3 * (uint)(object)factor);
+ }
+ else if (typeof(T) == typeof(int))
+ {
+ product.register.int32_0 = (int)(value.register.int32_0 * (int)(object)factor);
+ product.register.int32_1 = (int)(value.register.int32_1 * (int)(object)factor);
+ product.register.int32_2 = (int)(value.register.int32_2 * (int)(object)factor);
+ product.register.int32_3 = (int)(value.register.int32_3 * (int)(object)factor);
+ }
+ else if (typeof(T) == typeof(ulong))
+ {
+ product.register.uint64_0 = (ulong)(value.register.uint64_0 * (ulong)(object)factor);
+ product.register.uint64_1 = (ulong)(value.register.uint64_1 * (ulong)(object)factor);
+ }
+ else if (typeof(T) == typeof(long))
+ {
+ product.register.int64_0 = (long)(value.register.int64_0 * (long)(object)factor);
+ product.register.int64_1 = (long)(value.register.int64_1 * (long)(object)factor);
+ }
+ else if (typeof(T) == typeof(float))
+ {
+ product.register.single_0 = (float)(value.register.single_0 * (float)(object)factor);
+ product.register.single_1 = (float)(value.register.single_1 * (float)(object)factor);
+ product.register.single_2 = (float)(value.register.single_2 * (float)(object)factor);
+ product.register.single_3 = (float)(value.register.single_3 * (float)(object)factor);
+ }
+ else if (typeof(T) == typeof(double))
+ {
+ product.register.double_0 = (double)(value.register.double_0 * (double)(object)factor);
+ product.register.double_1 = (double)(value.register.double_1 * (double)(object)factor);
}
return product;
}
@@ -2321,101 +2356,101 @@ namespace System.Numerics
else
{
Vector<T> product = new Vector<T>();
- if (typeof(T) == typeof(Byte))
- {
- product.register.byte_0 = (Byte)(value.register.byte_0 * (Byte)(object)factor);
- product.register.byte_1 = (Byte)(value.register.byte_1 * (Byte)(object)factor);
- product.register.byte_2 = (Byte)(value.register.byte_2 * (Byte)(object)factor);
- product.register.byte_3 = (Byte)(value.register.byte_3 * (Byte)(object)factor);
- product.register.byte_4 = (Byte)(value.register.byte_4 * (Byte)(object)factor);
- product.register.byte_5 = (Byte)(value.register.byte_5 * (Byte)(object)factor);
- product.register.byte_6 = (Byte)(value.register.byte_6 * (Byte)(object)factor);
- product.register.byte_7 = (Byte)(value.register.byte_7 * (Byte)(object)factor);
- product.register.byte_8 = (Byte)(value.register.byte_8 * (Byte)(object)factor);
- product.register.byte_9 = (Byte)(value.register.byte_9 * (Byte)(object)factor);
- product.register.byte_10 = (Byte)(value.register.byte_10 * (Byte)(object)factor);
- product.register.byte_11 = (Byte)(value.register.byte_11 * (Byte)(object)factor);
- product.register.byte_12 = (Byte)(value.register.byte_12 * (Byte)(object)factor);
- product.register.byte_13 = (Byte)(value.register.byte_13 * (Byte)(object)factor);
- product.register.byte_14 = (Byte)(value.register.byte_14 * (Byte)(object)factor);
- product.register.byte_15 = (Byte)(value.register.byte_15 * (Byte)(object)factor);
- }
- else if (typeof(T) == typeof(SByte))
- {
- product.register.sbyte_0 = (SByte)(value.register.sbyte_0 * (SByte)(object)factor);
- product.register.sbyte_1 = (SByte)(value.register.sbyte_1 * (SByte)(object)factor);
- product.register.sbyte_2 = (SByte)(value.register.sbyte_2 * (SByte)(object)factor);
- product.register.sbyte_3 = (SByte)(value.register.sbyte_3 * (SByte)(object)factor);
- product.register.sbyte_4 = (SByte)(value.register.sbyte_4 * (SByte)(object)factor);
- product.register.sbyte_5 = (SByte)(value.register.sbyte_5 * (SByte)(object)factor);
- product.register.sbyte_6 = (SByte)(value.register.sbyte_6 * (SByte)(object)factor);
- product.register.sbyte_7 = (SByte)(value.register.sbyte_7 * (SByte)(object)factor);
- product.register.sbyte_8 = (SByte)(value.register.sbyte_8 * (SByte)(object)factor);
- product.register.sbyte_9 = (SByte)(value.register.sbyte_9 * (SByte)(object)factor);
- product.register.sbyte_10 = (SByte)(value.register.sbyte_10 * (SByte)(object)factor);
- product.register.sbyte_11 = (SByte)(value.register.sbyte_11 * (SByte)(object)factor);
- product.register.sbyte_12 = (SByte)(value.register.sbyte_12 * (SByte)(object)factor);
- product.register.sbyte_13 = (SByte)(value.register.sbyte_13 * (SByte)(object)factor);
- product.register.sbyte_14 = (SByte)(value.register.sbyte_14 * (SByte)(object)factor);
- product.register.sbyte_15 = (SByte)(value.register.sbyte_15 * (SByte)(object)factor);
- }
- else if (typeof(T) == typeof(UInt16))
- {
- product.register.uint16_0 = (UInt16)(value.register.uint16_0 * (UInt16)(object)factor);
- product.register.uint16_1 = (UInt16)(value.register.uint16_1 * (UInt16)(object)factor);
- product.register.uint16_2 = (UInt16)(value.register.uint16_2 * (UInt16)(object)factor);
- product.register.uint16_3 = (UInt16)(value.register.uint16_3 * (UInt16)(object)factor);
- product.register.uint16_4 = (UInt16)(value.register.uint16_4 * (UInt16)(object)factor);
- product.register.uint16_5 = (UInt16)(value.register.uint16_5 * (UInt16)(object)factor);
- product.register.uint16_6 = (UInt16)(value.register.uint16_6 * (UInt16)(object)factor);
- product.register.uint16_7 = (UInt16)(value.register.uint16_7 * (UInt16)(object)factor);
- }
- else if (typeof(T) == typeof(Int16))
- {
- product.register.int16_0 = (Int16)(value.register.int16_0 * (Int16)(object)factor);
- product.register.int16_1 = (Int16)(value.register.int16_1 * (Int16)(object)factor);
- product.register.int16_2 = (Int16)(value.register.int16_2 * (Int16)(object)factor);
- product.register.int16_3 = (Int16)(value.register.int16_3 * (Int16)(object)factor);
- product.register.int16_4 = (Int16)(value.register.int16_4 * (Int16)(object)factor);
- product.register.int16_5 = (Int16)(value.register.int16_5 * (Int16)(object)factor);
- product.register.int16_6 = (Int16)(value.register.int16_6 * (Int16)(object)factor);
- product.register.int16_7 = (Int16)(value.register.int16_7 * (Int16)(object)factor);
- }
- else if (typeof(T) == typeof(UInt32))
- {
- product.register.uint32_0 = (UInt32)(value.register.uint32_0 * (UInt32)(object)factor);
- product.register.uint32_1 = (UInt32)(value.register.uint32_1 * (UInt32)(object)factor);
- product.register.uint32_2 = (UInt32)(value.register.uint32_2 * (UInt32)(object)factor);
- product.register.uint32_3 = (UInt32)(value.register.uint32_3 * (UInt32)(object)factor);
- }
- else if (typeof(T) == typeof(Int32))
- {
- product.register.int32_0 = (Int32)(value.register.int32_0 * (Int32)(object)factor);
- product.register.int32_1 = (Int32)(value.register.int32_1 * (Int32)(object)factor);
- product.register.int32_2 = (Int32)(value.register.int32_2 * (Int32)(object)factor);
- product.register.int32_3 = (Int32)(value.register.int32_3 * (Int32)(object)factor);
- }
- else if (typeof(T) == typeof(UInt64))
- {
- product.register.uint64_0 = (UInt64)(value.register.uint64_0 * (UInt64)(object)factor);
- product.register.uint64_1 = (UInt64)(value.register.uint64_1 * (UInt64)(object)factor);
- }
- else if (typeof(T) == typeof(Int64))
- {
- product.register.int64_0 = (Int64)(value.register.int64_0 * (Int64)(object)factor);
- product.register.int64_1 = (Int64)(value.register.int64_1 * (Int64)(object)factor);
- }
- else if (typeof(T) == typeof(Single))
- {
- product.register.single_0 = (Single)(value.register.single_0 * (Single)(object)factor);
- product.register.single_1 = (Single)(value.register.single_1 * (Single)(object)factor);
- product.register.single_2 = (Single)(value.register.single_2 * (Single)(object)factor);
- product.register.single_3 = (Single)(value.register.single_3 * (Single)(object)factor);
- }
- else if (typeof(T) == typeof(Double))
- {
- product.register.double_0 = (Double)(value.register.double_0 * (Double)(object)factor);
- product.register.double_1 = (Double)(value.register.double_1 * (Double)(object)factor);
+ if (typeof(T) == typeof(byte))
+ {
+ product.register.byte_0 = (byte)(value.register.byte_0 * (byte)(object)factor);
+ product.register.byte_1 = (byte)(value.register.byte_1 * (byte)(object)factor);
+ product.register.byte_2 = (byte)(value.register.byte_2 * (byte)(object)factor);
+ product.register.byte_3 = (byte)(value.register.byte_3 * (byte)(object)factor);
+ product.register.byte_4 = (byte)(value.register.byte_4 * (byte)(object)factor);
+ product.register.byte_5 = (byte)(value.register.byte_5 * (byte)(object)factor);
+ product.register.byte_6 = (byte)(value.register.byte_6 * (byte)(object)factor);
+ product.register.byte_7 = (byte)(value.register.byte_7 * (byte)(object)factor);
+ product.register.byte_8 = (byte)(value.register.byte_8 * (byte)(object)factor);
+ product.register.byte_9 = (byte)(value.register.byte_9 * (byte)(object)factor);
+ product.register.byte_10 = (byte)(value.register.byte_10 * (byte)(object)factor);
+ product.register.byte_11 = (byte)(value.register.byte_11 * (byte)(object)factor);
+ product.register.byte_12 = (byte)(value.register.byte_12 * (byte)(object)factor);
+ product.register.byte_13 = (byte)(value.register.byte_13 * (byte)(object)factor);
+ product.register.byte_14 = (byte)(value.register.byte_14 * (byte)(object)factor);
+ product.register.byte_15 = (byte)(value.register.byte_15 * (byte)(object)factor);
+ }
+ else if (typeof(T) == typeof(sbyte))
+ {
+ product.register.sbyte_0 = (sbyte)(value.register.sbyte_0 * (sbyte)(object)factor);
+ product.register.sbyte_1 = (sbyte)(value.register.sbyte_1 * (sbyte)(object)factor);
+ product.register.sbyte_2 = (sbyte)(value.register.sbyte_2 * (sbyte)(object)factor);
+ product.register.sbyte_3 = (sbyte)(value.register.sbyte_3 * (sbyte)(object)factor);
+ product.register.sbyte_4 = (sbyte)(value.register.sbyte_4 * (sbyte)(object)factor);
+ product.register.sbyte_5 = (sbyte)(value.register.sbyte_5 * (sbyte)(object)factor);
+ product.register.sbyte_6 = (sbyte)(value.register.sbyte_6 * (sbyte)(object)factor);
+ product.register.sbyte_7 = (sbyte)(value.register.sbyte_7 * (sbyte)(object)factor);
+ product.register.sbyte_8 = (sbyte)(value.register.sbyte_8 * (sbyte)(object)factor);
+ product.register.sbyte_9 = (sbyte)(value.register.sbyte_9 * (sbyte)(object)factor);
+ product.register.sbyte_10 = (sbyte)(value.register.sbyte_10 * (sbyte)(object)factor);
+ product.register.sbyte_11 = (sbyte)(value.register.sbyte_11 * (sbyte)(object)factor);
+ product.register.sbyte_12 = (sbyte)(value.register.sbyte_12 * (sbyte)(object)factor);
+ product.register.sbyte_13 = (sbyte)(value.register.sbyte_13 * (sbyte)(object)factor);
+ product.register.sbyte_14 = (sbyte)(value.register.sbyte_14 * (sbyte)(object)factor);
+ product.register.sbyte_15 = (sbyte)(value.register.sbyte_15 * (sbyte)(object)factor);
+ }
+ else if (typeof(T) == typeof(ushort))
+ {
+ product.register.uint16_0 = (ushort)(value.register.uint16_0 * (ushort)(object)factor);
+ product.register.uint16_1 = (ushort)(value.register.uint16_1 * (ushort)(object)factor);
+ product.register.uint16_2 = (ushort)(value.register.uint16_2 * (ushort)(object)factor);
+ product.register.uint16_3 = (ushort)(value.register.uint16_3 * (ushort)(object)factor);
+ product.register.uint16_4 = (ushort)(value.register.uint16_4 * (ushort)(object)factor);
+ product.register.uint16_5 = (ushort)(value.register.uint16_5 * (ushort)(object)factor);
+ product.register.uint16_6 = (ushort)(value.register.uint16_6 * (ushort)(object)factor);
+ product.register.uint16_7 = (ushort)(value.register.uint16_7 * (ushort)(object)factor);
+ }
+ else if (typeof(T) == typeof(short))
+ {
+ product.register.int16_0 = (short)(value.register.int16_0 * (short)(object)factor);
+ product.register.int16_1 = (short)(value.register.int16_1 * (short)(object)factor);
+ product.register.int16_2 = (short)(value.register.int16_2 * (short)(object)factor);
+ product.register.int16_3 = (short)(value.register.int16_3 * (short)(object)factor);
+ product.register.int16_4 = (short)(value.register.int16_4 * (short)(object)factor);
+ product.register.int16_5 = (short)(value.register.int16_5 * (short)(object)factor);
+ product.register.int16_6 = (short)(value.register.int16_6 * (short)(object)factor);
+ product.register.int16_7 = (short)(value.register.int16_7 * (short)(object)factor);
+ }
+ else if (typeof(T) == typeof(uint))
+ {
+ product.register.uint32_0 = (uint)(value.register.uint32_0 * (uint)(object)factor);
+ product.register.uint32_1 = (uint)(value.register.uint32_1 * (uint)(object)factor);
+ product.register.uint32_2 = (uint)(value.register.uint32_2 * (uint)(object)factor);
+ product.register.uint32_3 = (uint)(value.register.uint32_3 * (uint)(object)factor);
+ }
+ else if (typeof(T) == typeof(int))
+ {
+ product.register.int32_0 = (int)(value.register.int32_0 * (int)(object)factor);
+ product.register.int32_1 = (int)(value.register.int32_1 * (int)(object)factor);
+ product.register.int32_2 = (int)(value.register.int32_2 * (int)(object)factor);
+ product.register.int32_3 = (int)(value.register.int32_3 * (int)(object)factor);
+ }
+ else if (typeof(T) == typeof(ulong))
+ {
+ product.register.uint64_0 = (ulong)(value.register.uint64_0 * (ulong)(object)factor);
+ product.register.uint64_1 = (ulong)(value.register.uint64_1 * (ulong)(object)factor);
+ }
+ else if (typeof(T) == typeof(long))
+ {
+ product.register.int64_0 = (long)(value.register.int64_0 * (long)(object)factor);
+ product.register.int64_1 = (long)(value.register.int64_1 * (long)(object)factor);
+ }
+ else if (typeof(T) == typeof(float))
+ {
+ product.register.single_0 = (float)(value.register.single_0 * (float)(object)factor);
+ product.register.single_1 = (float)(value.register.single_1 * (float)(object)factor);
+ product.register.single_2 = (float)(value.register.single_2 * (float)(object)factor);
+ product.register.single_3 = (float)(value.register.single_3 * (float)(object)factor);
+ }
+ else if (typeof(T) == typeof(double))
+ {
+ product.register.double_0 = (double)(value.register.double_0 * (double)(object)factor);
+ product.register.double_1 = (double)(value.register.double_1 * (double)(object)factor);
}
return product;
}
@@ -2435,93 +2470,93 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* dataPtr = stackalloc Byte[Count];
+ byte* dataPtr = stackalloc byte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Byte)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (byte)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (SByte)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (sbyte)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* dataPtr = stackalloc UInt16[Count];
+ ushort* dataPtr = stackalloc ushort[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt16)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (ushort)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int16)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (short)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* dataPtr = stackalloc UInt32[Count];
+ uint* dataPtr = stackalloc uint[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt32)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (uint)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int32)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (int)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* dataPtr = stackalloc UInt64[Count];
+ ulong* dataPtr = stackalloc ulong[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (UInt64)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (ulong)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int64)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (long)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Single)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (float)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Double)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (double)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
@@ -2533,101 +2568,101 @@ namespace System.Numerics
else
{
Vector<T> quotient = new Vector<T>();
- if (typeof(T) == typeof(Byte))
- {
- quotient.register.byte_0 = (Byte)(left.register.byte_0 / right.register.byte_0);
- quotient.register.byte_1 = (Byte)(left.register.byte_1 / right.register.byte_1);
- quotient.register.byte_2 = (Byte)(left.register.byte_2 / right.register.byte_2);
- quotient.register.byte_3 = (Byte)(left.register.byte_3 / right.register.byte_3);
- quotient.register.byte_4 = (Byte)(left.register.byte_4 / right.register.byte_4);
- quotient.register.byte_5 = (Byte)(left.register.byte_5 / right.register.byte_5);
- quotient.register.byte_6 = (Byte)(left.register.byte_6 / right.register.byte_6);
- quotient.register.byte_7 = (Byte)(left.register.byte_7 / right.register.byte_7);
- quotient.register.byte_8 = (Byte)(left.register.byte_8 / right.register.byte_8);
- quotient.register.byte_9 = (Byte)(left.register.byte_9 / right.register.byte_9);
- quotient.register.byte_10 = (Byte)(left.register.byte_10 / right.register.byte_10);
- quotient.register.byte_11 = (Byte)(left.register.byte_11 / right.register.byte_11);
- quotient.register.byte_12 = (Byte)(left.register.byte_12 / right.register.byte_12);
- quotient.register.byte_13 = (Byte)(left.register.byte_13 / right.register.byte_13);
- quotient.register.byte_14 = (Byte)(left.register.byte_14 / right.register.byte_14);
- quotient.register.byte_15 = (Byte)(left.register.byte_15 / right.register.byte_15);
- }
- else if (typeof(T) == typeof(SByte))
- {
- quotient.register.sbyte_0 = (SByte)(left.register.sbyte_0 / right.register.sbyte_0);
- quotient.register.sbyte_1 = (SByte)(left.register.sbyte_1 / right.register.sbyte_1);
- quotient.register.sbyte_2 = (SByte)(left.register.sbyte_2 / right.register.sbyte_2);
- quotient.register.sbyte_3 = (SByte)(left.register.sbyte_3 / right.register.sbyte_3);
- quotient.register.sbyte_4 = (SByte)(left.register.sbyte_4 / right.register.sbyte_4);
- quotient.register.sbyte_5 = (SByte)(left.register.sbyte_5 / right.register.sbyte_5);
- quotient.register.sbyte_6 = (SByte)(left.register.sbyte_6 / right.register.sbyte_6);
- quotient.register.sbyte_7 = (SByte)(left.register.sbyte_7 / right.register.sbyte_7);
- quotient.register.sbyte_8 = (SByte)(left.register.sbyte_8 / right.register.sbyte_8);
- quotient.register.sbyte_9 = (SByte)(left.register.sbyte_9 / right.register.sbyte_9);
- quotient.register.sbyte_10 = (SByte)(left.register.sbyte_10 / right.register.sbyte_10);
- quotient.register.sbyte_11 = (SByte)(left.register.sbyte_11 / right.register.sbyte_11);
- quotient.register.sbyte_12 = (SByte)(left.register.sbyte_12 / right.register.sbyte_12);
- quotient.register.sbyte_13 = (SByte)(left.register.sbyte_13 / right.register.sbyte_13);
- quotient.register.sbyte_14 = (SByte)(left.register.sbyte_14 / right.register.sbyte_14);
- quotient.register.sbyte_15 = (SByte)(left.register.sbyte_15 / right.register.sbyte_15);
- }
- else if (typeof(T) == typeof(UInt16))
- {
- quotient.register.uint16_0 = (UInt16)(left.register.uint16_0 / right.register.uint16_0);
- quotient.register.uint16_1 = (UInt16)(left.register.uint16_1 / right.register.uint16_1);
- quotient.register.uint16_2 = (UInt16)(left.register.uint16_2 / right.register.uint16_2);
- quotient.register.uint16_3 = (UInt16)(left.register.uint16_3 / right.register.uint16_3);
- quotient.register.uint16_4 = (UInt16)(left.register.uint16_4 / right.register.uint16_4);
- quotient.register.uint16_5 = (UInt16)(left.register.uint16_5 / right.register.uint16_5);
- quotient.register.uint16_6 = (UInt16)(left.register.uint16_6 / right.register.uint16_6);
- quotient.register.uint16_7 = (UInt16)(left.register.uint16_7 / right.register.uint16_7);
- }
- else if (typeof(T) == typeof(Int16))
- {
- quotient.register.int16_0 = (Int16)(left.register.int16_0 / right.register.int16_0);
- quotient.register.int16_1 = (Int16)(left.register.int16_1 / right.register.int16_1);
- quotient.register.int16_2 = (Int16)(left.register.int16_2 / right.register.int16_2);
- quotient.register.int16_3 = (Int16)(left.register.int16_3 / right.register.int16_3);
- quotient.register.int16_4 = (Int16)(left.register.int16_4 / right.register.int16_4);
- quotient.register.int16_5 = (Int16)(left.register.int16_5 / right.register.int16_5);
- quotient.register.int16_6 = (Int16)(left.register.int16_6 / right.register.int16_6);
- quotient.register.int16_7 = (Int16)(left.register.int16_7 / right.register.int16_7);
- }
- else if (typeof(T) == typeof(UInt32))
- {
- quotient.register.uint32_0 = (UInt32)(left.register.uint32_0 / right.register.uint32_0);
- quotient.register.uint32_1 = (UInt32)(left.register.uint32_1 / right.register.uint32_1);
- quotient.register.uint32_2 = (UInt32)(left.register.uint32_2 / right.register.uint32_2);
- quotient.register.uint32_3 = (UInt32)(left.register.uint32_3 / right.register.uint32_3);
- }
- else if (typeof(T) == typeof(Int32))
- {
- quotient.register.int32_0 = (Int32)(left.register.int32_0 / right.register.int32_0);
- quotient.register.int32_1 = (Int32)(left.register.int32_1 / right.register.int32_1);
- quotient.register.int32_2 = (Int32)(left.register.int32_2 / right.register.int32_2);
- quotient.register.int32_3 = (Int32)(left.register.int32_3 / right.register.int32_3);
- }
- else if (typeof(T) == typeof(UInt64))
- {
- quotient.register.uint64_0 = (UInt64)(left.register.uint64_0 / right.register.uint64_0);
- quotient.register.uint64_1 = (UInt64)(left.register.uint64_1 / right.register.uint64_1);
- }
- else if (typeof(T) == typeof(Int64))
- {
- quotient.register.int64_0 = (Int64)(left.register.int64_0 / right.register.int64_0);
- quotient.register.int64_1 = (Int64)(left.register.int64_1 / right.register.int64_1);
- }
- else if (typeof(T) == typeof(Single))
- {
- quotient.register.single_0 = (Single)(left.register.single_0 / right.register.single_0);
- quotient.register.single_1 = (Single)(left.register.single_1 / right.register.single_1);
- quotient.register.single_2 = (Single)(left.register.single_2 / right.register.single_2);
- quotient.register.single_3 = (Single)(left.register.single_3 / right.register.single_3);
- }
- else if (typeof(T) == typeof(Double))
- {
- quotient.register.double_0 = (Double)(left.register.double_0 / right.register.double_0);
- quotient.register.double_1 = (Double)(left.register.double_1 / right.register.double_1);
+ if (typeof(T) == typeof(byte))
+ {
+ quotient.register.byte_0 = (byte)(left.register.byte_0 / right.register.byte_0);
+ quotient.register.byte_1 = (byte)(left.register.byte_1 / right.register.byte_1);
+ quotient.register.byte_2 = (byte)(left.register.byte_2 / right.register.byte_2);
+ quotient.register.byte_3 = (byte)(left.register.byte_3 / right.register.byte_3);
+ quotient.register.byte_4 = (byte)(left.register.byte_4 / right.register.byte_4);
+ quotient.register.byte_5 = (byte)(left.register.byte_5 / right.register.byte_5);
+ quotient.register.byte_6 = (byte)(left.register.byte_6 / right.register.byte_6);
+ quotient.register.byte_7 = (byte)(left.register.byte_7 / right.register.byte_7);
+ quotient.register.byte_8 = (byte)(left.register.byte_8 / right.register.byte_8);
+ quotient.register.byte_9 = (byte)(left.register.byte_9 / right.register.byte_9);
+ quotient.register.byte_10 = (byte)(left.register.byte_10 / right.register.byte_10);
+ quotient.register.byte_11 = (byte)(left.register.byte_11 / right.register.byte_11);
+ quotient.register.byte_12 = (byte)(left.register.byte_12 / right.register.byte_12);
+ quotient.register.byte_13 = (byte)(left.register.byte_13 / right.register.byte_13);
+ quotient.register.byte_14 = (byte)(left.register.byte_14 / right.register.byte_14);
+ quotient.register.byte_15 = (byte)(left.register.byte_15 / right.register.byte_15);
+ }
+ else if (typeof(T) == typeof(sbyte))
+ {
+ quotient.register.sbyte_0 = (sbyte)(left.register.sbyte_0 / right.register.sbyte_0);
+ quotient.register.sbyte_1 = (sbyte)(left.register.sbyte_1 / right.register.sbyte_1);
+ quotient.register.sbyte_2 = (sbyte)(left.register.sbyte_2 / right.register.sbyte_2);
+ quotient.register.sbyte_3 = (sbyte)(left.register.sbyte_3 / right.register.sbyte_3);
+ quotient.register.sbyte_4 = (sbyte)(left.register.sbyte_4 / right.register.sbyte_4);
+ quotient.register.sbyte_5 = (sbyte)(left.register.sbyte_5 / right.register.sbyte_5);
+ quotient.register.sbyte_6 = (sbyte)(left.register.sbyte_6 / right.register.sbyte_6);
+ quotient.register.sbyte_7 = (sbyte)(left.register.sbyte_7 / right.register.sbyte_7);
+ quotient.register.sbyte_8 = (sbyte)(left.register.sbyte_8 / right.register.sbyte_8);
+ quotient.register.sbyte_9 = (sbyte)(left.register.sbyte_9 / right.register.sbyte_9);
+ quotient.register.sbyte_10 = (sbyte)(left.register.sbyte_10 / right.register.sbyte_10);
+ quotient.register.sbyte_11 = (sbyte)(left.register.sbyte_11 / right.register.sbyte_11);
+ quotient.register.sbyte_12 = (sbyte)(left.register.sbyte_12 / right.register.sbyte_12);
+ quotient.register.sbyte_13 = (sbyte)(left.register.sbyte_13 / right.register.sbyte_13);
+ quotient.register.sbyte_14 = (sbyte)(left.register.sbyte_14 / right.register.sbyte_14);
+ quotient.register.sbyte_15 = (sbyte)(left.register.sbyte_15 / right.register.sbyte_15);
+ }
+ else if (typeof(T) == typeof(ushort))
+ {
+ quotient.register.uint16_0 = (ushort)(left.register.uint16_0 / right.register.uint16_0);
+ quotient.register.uint16_1 = (ushort)(left.register.uint16_1 / right.register.uint16_1);
+ quotient.register.uint16_2 = (ushort)(left.register.uint16_2 / right.register.uint16_2);
+ quotient.register.uint16_3 = (ushort)(left.register.uint16_3 / right.register.uint16_3);
+ quotient.register.uint16_4 = (ushort)(left.register.uint16_4 / right.register.uint16_4);
+ quotient.register.uint16_5 = (ushort)(left.register.uint16_5 / right.register.uint16_5);
+ quotient.register.uint16_6 = (ushort)(left.register.uint16_6 / right.register.uint16_6);
+ quotient.register.uint16_7 = (ushort)(left.register.uint16_7 / right.register.uint16_7);
+ }
+ else if (typeof(T) == typeof(short))
+ {
+ quotient.register.int16_0 = (short)(left.register.int16_0 / right.register.int16_0);
+ quotient.register.int16_1 = (short)(left.register.int16_1 / right.register.int16_1);
+ quotient.register.int16_2 = (short)(left.register.int16_2 / right.register.int16_2);
+ quotient.register.int16_3 = (short)(left.register.int16_3 / right.register.int16_3);
+ quotient.register.int16_4 = (short)(left.register.int16_4 / right.register.int16_4);
+ quotient.register.int16_5 = (short)(left.register.int16_5 / right.register.int16_5);
+ quotient.register.int16_6 = (short)(left.register.int16_6 / right.register.int16_6);
+ quotient.register.int16_7 = (short)(left.register.int16_7 / right.register.int16_7);
+ }
+ else if (typeof(T) == typeof(uint))
+ {
+ quotient.register.uint32_0 = (uint)(left.register.uint32_0 / right.register.uint32_0);
+ quotient.register.uint32_1 = (uint)(left.register.uint32_1 / right.register.uint32_1);
+ quotient.register.uint32_2 = (uint)(left.register.uint32_2 / right.register.uint32_2);
+ quotient.register.uint32_3 = (uint)(left.register.uint32_3 / right.register.uint32_3);
+ }
+ else if (typeof(T) == typeof(int))
+ {
+ quotient.register.int32_0 = (int)(left.register.int32_0 / right.register.int32_0);
+ quotient.register.int32_1 = (int)(left.register.int32_1 / right.register.int32_1);
+ quotient.register.int32_2 = (int)(left.register.int32_2 / right.register.int32_2);
+ quotient.register.int32_3 = (int)(left.register.int32_3 / right.register.int32_3);
+ }
+ else if (typeof(T) == typeof(ulong))
+ {
+ quotient.register.uint64_0 = (ulong)(left.register.uint64_0 / right.register.uint64_0);
+ quotient.register.uint64_1 = (ulong)(left.register.uint64_1 / right.register.uint64_1);
+ }
+ else if (typeof(T) == typeof(long))
+ {
+ quotient.register.int64_0 = (long)(left.register.int64_0 / right.register.int64_0);
+ quotient.register.int64_1 = (long)(left.register.int64_1 / right.register.int64_1);
+ }
+ else if (typeof(T) == typeof(float))
+ {
+ quotient.register.single_0 = (float)(left.register.single_0 / right.register.single_0);
+ quotient.register.single_1 = (float)(left.register.single_1 / right.register.single_1);
+ quotient.register.single_2 = (float)(left.register.single_2 / right.register.single_2);
+ quotient.register.single_3 = (float)(left.register.single_3 / right.register.single_3);
+ }
+ else if (typeof(T) == typeof(double))
+ {
+ quotient.register.double_0 = (double)(left.register.double_0 / right.register.double_0);
+ quotient.register.double_1 = (double)(left.register.double_1 / right.register.double_1);
}
return quotient;
}
@@ -2660,10 +2695,10 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- Int64* resultBase = &result.register.int64_0;
- Int64* leftBase = &left.register.int64_0;
- Int64* rightBase = &right.register.int64_0;
- for (int g = 0; g < Vector<Int64>.Count; g++)
+ long* resultBase = &result.register.int64_0;
+ long* leftBase = &left.register.int64_0;
+ long* rightBase = &right.register.int64_0;
+ for (int g = 0; g < Vector<long>.Count; g++)
{
resultBase[g] = leftBase[g] & rightBase[g];
}
@@ -2691,10 +2726,10 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- Int64* resultBase = &result.register.int64_0;
- Int64* leftBase = &left.register.int64_0;
- Int64* rightBase = &right.register.int64_0;
- for (int g = 0; g < Vector<Int64>.Count; g++)
+ long* resultBase = &result.register.int64_0;
+ long* leftBase = &left.register.int64_0;
+ long* rightBase = &right.register.int64_0;
+ for (int g = 0; g < Vector<long>.Count; g++)
{
resultBase[g] = leftBase[g] | rightBase[g];
}
@@ -2722,10 +2757,10 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- Int64* resultBase = &result.register.int64_0;
- Int64* leftBase = &left.register.int64_0;
- Int64* rightBase = &right.register.int64_0;
- for (int g = 0; g < Vector<Int64>.Count; g++)
+ long* resultBase = &result.register.int64_0;
+ long* leftBase = &left.register.int64_0;
+ long* rightBase = &right.register.int64_0;
+ for (int g = 0; g < Vector<long>.Count; g++)
{
resultBase[g] = leftBase[g] ^ rightBase[g];
}
@@ -2784,9 +2819,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[Intrinsic]
- public static explicit operator Vector<Byte>(Vector<T> value)
+ public static explicit operator Vector<byte>(Vector<T> value)
{
- return new Vector<Byte>(ref value.register);
+ return new Vector<byte>(ref value.register);
}
/// <summary>
@@ -2796,9 +2831,9 @@ namespace System.Numerics
/// <returns>The reinterpreted vector.</returns>
[CLSCompliant(false)]
[Intrinsic]
- public static explicit operator Vector<SByte>(Vector<T> value)
+ public static explicit operator Vector<sbyte>(Vector<T> value)
{
- return new Vector<SByte>(ref value.register);
+ return new Vector<sbyte>(ref value.register);
}
/// <summary>
@@ -2808,9 +2843,9 @@ namespace System.Numerics
/// <returns>The reinterpreted vector.</returns>
[CLSCompliant(false)]
[Intrinsic]
- public static explicit operator Vector<UInt16>(Vector<T> value)
+ public static explicit operator Vector<ushort>(Vector<T> value)
{
- return new Vector<UInt16>(ref value.register);
+ return new Vector<ushort>(ref value.register);
}
/// <summary>
@@ -2819,9 +2854,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[Intrinsic]
- public static explicit operator Vector<Int16>(Vector<T> value)
+ public static explicit operator Vector<short>(Vector<T> value)
{
- return new Vector<Int16>(ref value.register);
+ return new Vector<short>(ref value.register);
}
/// <summary>
@@ -2831,9 +2866,9 @@ namespace System.Numerics
/// <returns>The reinterpreted vector.</returns>
[CLSCompliant(false)]
[Intrinsic]
- public static explicit operator Vector<UInt32>(Vector<T> value)
+ public static explicit operator Vector<uint>(Vector<T> value)
{
- return new Vector<UInt32>(ref value.register);
+ return new Vector<uint>(ref value.register);
}
/// <summary>
@@ -2842,9 +2877,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[Intrinsic]
- public static explicit operator Vector<Int32>(Vector<T> value)
+ public static explicit operator Vector<int>(Vector<T> value)
{
- return new Vector<Int32>(ref value.register);
+ return new Vector<int>(ref value.register);
}
/// <summary>
@@ -2854,9 +2889,9 @@ namespace System.Numerics
/// <returns>The reinterpreted vector.</returns>
[CLSCompliant(false)]
[Intrinsic]
- public static explicit operator Vector<UInt64>(Vector<T> value)
+ public static explicit operator Vector<ulong>(Vector<T> value)
{
- return new Vector<UInt64>(ref value.register);
+ return new Vector<ulong>(ref value.register);
}
/// <summary>
@@ -2865,9 +2900,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[Intrinsic]
- public static explicit operator Vector<Int64>(Vector<T> value)
+ public static explicit operator Vector<long>(Vector<T> value)
{
- return new Vector<Int64>(ref value.register);
+ return new Vector<long>(ref value.register);
}
/// <summary>
@@ -2876,9 +2911,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[Intrinsic]
- public static explicit operator Vector<Single>(Vector<T> value)
+ public static explicit operator Vector<float>(Vector<T> value)
{
- return new Vector<Single>(ref value.register);
+ return new Vector<float>(ref value.register);
}
/// <summary>
@@ -2887,9 +2922,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[Intrinsic]
- public static explicit operator Vector<Double>(Vector<T> value)
+ public static explicit operator Vector<double>(Vector<T> value)
{
- return new Vector<Double>(ref value.register);
+ return new Vector<double>(ref value.register);
}
#endregion Conversions
@@ -2901,93 +2936,93 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* dataPtr = stackalloc Byte[Count];
+ byte* dataPtr = stackalloc byte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* dataPtr = stackalloc UInt16[Count];
+ ushort* dataPtr = stackalloc ushort[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* dataPtr = stackalloc UInt32[Count];
+ uint* dataPtr = stackalloc uint[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* dataPtr = stackalloc UInt64[Count];
+ ulong* dataPtr = stackalloc ulong[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetUInt64WithAllBitsSet() : (UInt64)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetUInt64WithAllBitsSet() : (ulong)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetInt64WithAllBitsSet() : (Int64)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetInt64WithAllBitsSet() : (long)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetDoubleWithAllBitsSet() : (Double)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.GetDoubleWithAllBitsSet() : (double)0;
}
return new Vector<T>(dataPtr);
}
@@ -2999,110 +3034,110 @@ namespace System.Numerics
else
{
Register register = new Register();
- if (typeof(T) == typeof(Byte))
- {
- register.byte_0 = left.register.byte_0 == right.register.byte_0 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_1 = left.register.byte_1 == right.register.byte_1 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_2 = left.register.byte_2 == right.register.byte_2 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_3 = left.register.byte_3 == right.register.byte_3 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_4 = left.register.byte_4 == right.register.byte_4 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_5 = left.register.byte_5 == right.register.byte_5 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_6 = left.register.byte_6 == right.register.byte_6 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_7 = left.register.byte_7 == right.register.byte_7 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_8 = left.register.byte_8 == right.register.byte_8 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_9 = left.register.byte_9 == right.register.byte_9 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_10 = left.register.byte_10 == right.register.byte_10 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_11 = left.register.byte_11 == right.register.byte_11 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_12 = left.register.byte_12 == right.register.byte_12 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_13 = left.register.byte_13 == right.register.byte_13 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_14 = left.register.byte_14 == right.register.byte_14 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_15 = left.register.byte_15 == right.register.byte_15 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
+ if (typeof(T) == typeof(byte))
+ {
+ register.byte_0 = left.register.byte_0 == right.register.byte_0 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_1 = left.register.byte_1 == right.register.byte_1 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_2 = left.register.byte_2 == right.register.byte_2 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_3 = left.register.byte_3 == right.register.byte_3 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_4 = left.register.byte_4 == right.register.byte_4 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_5 = left.register.byte_5 == right.register.byte_5 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_6 = left.register.byte_6 == right.register.byte_6 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_7 = left.register.byte_7 == right.register.byte_7 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_8 = left.register.byte_8 == right.register.byte_8 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_9 = left.register.byte_9 == right.register.byte_9 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_10 = left.register.byte_10 == right.register.byte_10 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_11 = left.register.byte_11 == right.register.byte_11 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_12 = left.register.byte_12 == right.register.byte_12 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_13 = left.register.byte_13 == right.register.byte_13 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_14 = left.register.byte_14 == right.register.byte_14 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_15 = left.register.byte_15 == right.register.byte_15 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(SByte))
- {
- register.sbyte_0 = left.register.sbyte_0 == right.register.sbyte_0 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_1 = left.register.sbyte_1 == right.register.sbyte_1 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_2 = left.register.sbyte_2 == right.register.sbyte_2 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_3 = left.register.sbyte_3 == right.register.sbyte_3 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_4 = left.register.sbyte_4 == right.register.sbyte_4 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_5 = left.register.sbyte_5 == right.register.sbyte_5 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_6 = left.register.sbyte_6 == right.register.sbyte_6 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_7 = left.register.sbyte_7 == right.register.sbyte_7 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_8 = left.register.sbyte_8 == right.register.sbyte_8 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_9 = left.register.sbyte_9 == right.register.sbyte_9 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_10 = left.register.sbyte_10 == right.register.sbyte_10 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_11 = left.register.sbyte_11 == right.register.sbyte_11 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_12 = left.register.sbyte_12 == right.register.sbyte_12 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_13 = left.register.sbyte_13 == right.register.sbyte_13 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_14 = left.register.sbyte_14 == right.register.sbyte_14 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_15 = left.register.sbyte_15 == right.register.sbyte_15 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
+ else if (typeof(T) == typeof(sbyte))
+ {
+ register.sbyte_0 = left.register.sbyte_0 == right.register.sbyte_0 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_1 = left.register.sbyte_1 == right.register.sbyte_1 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_2 = left.register.sbyte_2 == right.register.sbyte_2 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_3 = left.register.sbyte_3 == right.register.sbyte_3 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_4 = left.register.sbyte_4 == right.register.sbyte_4 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_5 = left.register.sbyte_5 == right.register.sbyte_5 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_6 = left.register.sbyte_6 == right.register.sbyte_6 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_7 = left.register.sbyte_7 == right.register.sbyte_7 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_8 = left.register.sbyte_8 == right.register.sbyte_8 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_9 = left.register.sbyte_9 == right.register.sbyte_9 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_10 = left.register.sbyte_10 == right.register.sbyte_10 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_11 = left.register.sbyte_11 == right.register.sbyte_11 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_12 = left.register.sbyte_12 == right.register.sbyte_12 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_13 = left.register.sbyte_13 == right.register.sbyte_13 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_14 = left.register.sbyte_14 == right.register.sbyte_14 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_15 = left.register.sbyte_15 == right.register.sbyte_15 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- register.uint16_0 = left.register.uint16_0 == right.register.uint16_0 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_1 = left.register.uint16_1 == right.register.uint16_1 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_2 = left.register.uint16_2 == right.register.uint16_2 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_3 = left.register.uint16_3 == right.register.uint16_3 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_4 = left.register.uint16_4 == right.register.uint16_4 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_5 = left.register.uint16_5 == right.register.uint16_5 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_6 = left.register.uint16_6 == right.register.uint16_6 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_7 = left.register.uint16_7 == right.register.uint16_7 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
+ register.uint16_0 = left.register.uint16_0 == right.register.uint16_0 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_1 = left.register.uint16_1 == right.register.uint16_1 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_2 = left.register.uint16_2 == right.register.uint16_2 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_3 = left.register.uint16_3 == right.register.uint16_3 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_4 = left.register.uint16_4 == right.register.uint16_4 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_5 = left.register.uint16_5 == right.register.uint16_5 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_6 = left.register.uint16_6 == right.register.uint16_6 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_7 = left.register.uint16_7 == right.register.uint16_7 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- register.int16_0 = left.register.int16_0 == right.register.int16_0 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_1 = left.register.int16_1 == right.register.int16_1 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_2 = left.register.int16_2 == right.register.int16_2 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_3 = left.register.int16_3 == right.register.int16_3 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_4 = left.register.int16_4 == right.register.int16_4 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_5 = left.register.int16_5 == right.register.int16_5 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_6 = left.register.int16_6 == right.register.int16_6 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_7 = left.register.int16_7 == right.register.int16_7 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
+ register.int16_0 = left.register.int16_0 == right.register.int16_0 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_1 = left.register.int16_1 == right.register.int16_1 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_2 = left.register.int16_2 == right.register.int16_2 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_3 = left.register.int16_3 == right.register.int16_3 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_4 = left.register.int16_4 == right.register.int16_4 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_5 = left.register.int16_5 == right.register.int16_5 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_6 = left.register.int16_6 == right.register.int16_6 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_7 = left.register.int16_7 == right.register.int16_7 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- register.uint32_0 = left.register.uint32_0 == right.register.uint32_0 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
- register.uint32_1 = left.register.uint32_1 == right.register.uint32_1 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
- register.uint32_2 = left.register.uint32_2 == right.register.uint32_2 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
- register.uint32_3 = left.register.uint32_3 == right.register.uint32_3 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
+ register.uint32_0 = left.register.uint32_0 == right.register.uint32_0 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
+ register.uint32_1 = left.register.uint32_1 == right.register.uint32_1 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
+ register.uint32_2 = left.register.uint32_2 == right.register.uint32_2 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
+ register.uint32_3 = left.register.uint32_3 == right.register.uint32_3 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- register.int32_0 = left.register.int32_0 == right.register.int32_0 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
- register.int32_1 = left.register.int32_1 == right.register.int32_1 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
- register.int32_2 = left.register.int32_2 == right.register.int32_2 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
- register.int32_3 = left.register.int32_3 == right.register.int32_3 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
+ register.int32_0 = left.register.int32_0 == right.register.int32_0 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
+ register.int32_1 = left.register.int32_1 == right.register.int32_1 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
+ register.int32_2 = left.register.int32_2 == right.register.int32_2 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
+ register.int32_3 = left.register.int32_3 == right.register.int32_3 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- register.uint64_0 = left.register.uint64_0 == right.register.uint64_0 ? ConstantHelper.GetUInt64WithAllBitsSet() : (UInt64)0;
- register.uint64_1 = left.register.uint64_1 == right.register.uint64_1 ? ConstantHelper.GetUInt64WithAllBitsSet() : (UInt64)0;
+ register.uint64_0 = left.register.uint64_0 == right.register.uint64_0 ? ConstantHelper.GetUInt64WithAllBitsSet() : (ulong)0;
+ register.uint64_1 = left.register.uint64_1 == right.register.uint64_1 ? ConstantHelper.GetUInt64WithAllBitsSet() : (ulong)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- register.int64_0 = left.register.int64_0 == right.register.int64_0 ? ConstantHelper.GetInt64WithAllBitsSet() : (Int64)0;
- register.int64_1 = left.register.int64_1 == right.register.int64_1 ? ConstantHelper.GetInt64WithAllBitsSet() : (Int64)0;
+ register.int64_0 = left.register.int64_0 == right.register.int64_0 ? ConstantHelper.GetInt64WithAllBitsSet() : (long)0;
+ register.int64_1 = left.register.int64_1 == right.register.int64_1 ? ConstantHelper.GetInt64WithAllBitsSet() : (long)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- register.single_0 = left.register.single_0 == right.register.single_0 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
- register.single_1 = left.register.single_1 == right.register.single_1 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
- register.single_2 = left.register.single_2 == right.register.single_2 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
- register.single_3 = left.register.single_3 == right.register.single_3 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
+ register.single_0 = left.register.single_0 == right.register.single_0 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
+ register.single_1 = left.register.single_1 == right.register.single_1 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
+ register.single_2 = left.register.single_2 == right.register.single_2 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
+ register.single_3 = left.register.single_3 == right.register.single_3 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- register.double_0 = left.register.double_0 == right.register.double_0 ? ConstantHelper.GetDoubleWithAllBitsSet() : (Double)0;
- register.double_1 = left.register.double_1 == right.register.double_1 ? ConstantHelper.GetDoubleWithAllBitsSet() : (Double)0;
+ register.double_0 = left.register.double_0 == right.register.double_0 ? ConstantHelper.GetDoubleWithAllBitsSet() : (double)0;
+ register.double_1 = left.register.double_1 == right.register.double_1 ? ConstantHelper.GetDoubleWithAllBitsSet() : (double)0;
return new Vector<T>(ref register);
}
else
@@ -3118,93 +3153,93 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* dataPtr = stackalloc Byte[Count];
+ byte* dataPtr = stackalloc byte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* dataPtr = stackalloc UInt16[Count];
+ ushort* dataPtr = stackalloc ushort[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* dataPtr = stackalloc UInt32[Count];
+ uint* dataPtr = stackalloc uint[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* dataPtr = stackalloc UInt64[Count];
+ ulong* dataPtr = stackalloc ulong[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetUInt64WithAllBitsSet() : (UInt64)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetUInt64WithAllBitsSet() : (ulong)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetInt64WithAllBitsSet() : (Int64)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetInt64WithAllBitsSet() : (long)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetDoubleWithAllBitsSet() : (Double)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.GetDoubleWithAllBitsSet() : (double)0;
}
return new Vector<T>(dataPtr);
}
@@ -3216,110 +3251,110 @@ namespace System.Numerics
else
{
Register register = new Register();
- if (typeof(T) == typeof(Byte))
- {
- register.byte_0 = left.register.byte_0 < right.register.byte_0 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_1 = left.register.byte_1 < right.register.byte_1 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_2 = left.register.byte_2 < right.register.byte_2 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_3 = left.register.byte_3 < right.register.byte_3 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_4 = left.register.byte_4 < right.register.byte_4 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_5 = left.register.byte_5 < right.register.byte_5 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_6 = left.register.byte_6 < right.register.byte_6 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_7 = left.register.byte_7 < right.register.byte_7 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_8 = left.register.byte_8 < right.register.byte_8 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_9 = left.register.byte_9 < right.register.byte_9 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_10 = left.register.byte_10 < right.register.byte_10 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_11 = left.register.byte_11 < right.register.byte_11 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_12 = left.register.byte_12 < right.register.byte_12 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_13 = left.register.byte_13 < right.register.byte_13 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_14 = left.register.byte_14 < right.register.byte_14 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_15 = left.register.byte_15 < right.register.byte_15 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
+ if (typeof(T) == typeof(byte))
+ {
+ register.byte_0 = left.register.byte_0 < right.register.byte_0 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_1 = left.register.byte_1 < right.register.byte_1 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_2 = left.register.byte_2 < right.register.byte_2 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_3 = left.register.byte_3 < right.register.byte_3 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_4 = left.register.byte_4 < right.register.byte_4 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_5 = left.register.byte_5 < right.register.byte_5 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_6 = left.register.byte_6 < right.register.byte_6 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_7 = left.register.byte_7 < right.register.byte_7 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_8 = left.register.byte_8 < right.register.byte_8 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_9 = left.register.byte_9 < right.register.byte_9 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_10 = left.register.byte_10 < right.register.byte_10 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_11 = left.register.byte_11 < right.register.byte_11 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_12 = left.register.byte_12 < right.register.byte_12 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_13 = left.register.byte_13 < right.register.byte_13 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_14 = left.register.byte_14 < right.register.byte_14 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_15 = left.register.byte_15 < right.register.byte_15 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(SByte))
- {
- register.sbyte_0 = left.register.sbyte_0 < right.register.sbyte_0 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_1 = left.register.sbyte_1 < right.register.sbyte_1 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_2 = left.register.sbyte_2 < right.register.sbyte_2 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_3 = left.register.sbyte_3 < right.register.sbyte_3 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_4 = left.register.sbyte_4 < right.register.sbyte_4 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_5 = left.register.sbyte_5 < right.register.sbyte_5 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_6 = left.register.sbyte_6 < right.register.sbyte_6 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_7 = left.register.sbyte_7 < right.register.sbyte_7 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_8 = left.register.sbyte_8 < right.register.sbyte_8 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_9 = left.register.sbyte_9 < right.register.sbyte_9 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_10 = left.register.sbyte_10 < right.register.sbyte_10 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_11 = left.register.sbyte_11 < right.register.sbyte_11 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_12 = left.register.sbyte_12 < right.register.sbyte_12 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_13 = left.register.sbyte_13 < right.register.sbyte_13 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_14 = left.register.sbyte_14 < right.register.sbyte_14 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_15 = left.register.sbyte_15 < right.register.sbyte_15 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
+ else if (typeof(T) == typeof(sbyte))
+ {
+ register.sbyte_0 = left.register.sbyte_0 < right.register.sbyte_0 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_1 = left.register.sbyte_1 < right.register.sbyte_1 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_2 = left.register.sbyte_2 < right.register.sbyte_2 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_3 = left.register.sbyte_3 < right.register.sbyte_3 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_4 = left.register.sbyte_4 < right.register.sbyte_4 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_5 = left.register.sbyte_5 < right.register.sbyte_5 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_6 = left.register.sbyte_6 < right.register.sbyte_6 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_7 = left.register.sbyte_7 < right.register.sbyte_7 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_8 = left.register.sbyte_8 < right.register.sbyte_8 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_9 = left.register.sbyte_9 < right.register.sbyte_9 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_10 = left.register.sbyte_10 < right.register.sbyte_10 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_11 = left.register.sbyte_11 < right.register.sbyte_11 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_12 = left.register.sbyte_12 < right.register.sbyte_12 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_13 = left.register.sbyte_13 < right.register.sbyte_13 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_14 = left.register.sbyte_14 < right.register.sbyte_14 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_15 = left.register.sbyte_15 < right.register.sbyte_15 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- register.uint16_0 = left.register.uint16_0 < right.register.uint16_0 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_1 = left.register.uint16_1 < right.register.uint16_1 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_2 = left.register.uint16_2 < right.register.uint16_2 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_3 = left.register.uint16_3 < right.register.uint16_3 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_4 = left.register.uint16_4 < right.register.uint16_4 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_5 = left.register.uint16_5 < right.register.uint16_5 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_6 = left.register.uint16_6 < right.register.uint16_6 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_7 = left.register.uint16_7 < right.register.uint16_7 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
+ register.uint16_0 = left.register.uint16_0 < right.register.uint16_0 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_1 = left.register.uint16_1 < right.register.uint16_1 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_2 = left.register.uint16_2 < right.register.uint16_2 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_3 = left.register.uint16_3 < right.register.uint16_3 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_4 = left.register.uint16_4 < right.register.uint16_4 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_5 = left.register.uint16_5 < right.register.uint16_5 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_6 = left.register.uint16_6 < right.register.uint16_6 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_7 = left.register.uint16_7 < right.register.uint16_7 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- register.int16_0 = left.register.int16_0 < right.register.int16_0 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_1 = left.register.int16_1 < right.register.int16_1 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_2 = left.register.int16_2 < right.register.int16_2 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_3 = left.register.int16_3 < right.register.int16_3 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_4 = left.register.int16_4 < right.register.int16_4 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_5 = left.register.int16_5 < right.register.int16_5 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_6 = left.register.int16_6 < right.register.int16_6 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_7 = left.register.int16_7 < right.register.int16_7 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
+ register.int16_0 = left.register.int16_0 < right.register.int16_0 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_1 = left.register.int16_1 < right.register.int16_1 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_2 = left.register.int16_2 < right.register.int16_2 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_3 = left.register.int16_3 < right.register.int16_3 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_4 = left.register.int16_4 < right.register.int16_4 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_5 = left.register.int16_5 < right.register.int16_5 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_6 = left.register.int16_6 < right.register.int16_6 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_7 = left.register.int16_7 < right.register.int16_7 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- register.uint32_0 = left.register.uint32_0 < right.register.uint32_0 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
- register.uint32_1 = left.register.uint32_1 < right.register.uint32_1 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
- register.uint32_2 = left.register.uint32_2 < right.register.uint32_2 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
- register.uint32_3 = left.register.uint32_3 < right.register.uint32_3 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
+ register.uint32_0 = left.register.uint32_0 < right.register.uint32_0 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
+ register.uint32_1 = left.register.uint32_1 < right.register.uint32_1 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
+ register.uint32_2 = left.register.uint32_2 < right.register.uint32_2 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
+ register.uint32_3 = left.register.uint32_3 < right.register.uint32_3 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- register.int32_0 = left.register.int32_0 < right.register.int32_0 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
- register.int32_1 = left.register.int32_1 < right.register.int32_1 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
- register.int32_2 = left.register.int32_2 < right.register.int32_2 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
- register.int32_3 = left.register.int32_3 < right.register.int32_3 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
+ register.int32_0 = left.register.int32_0 < right.register.int32_0 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
+ register.int32_1 = left.register.int32_1 < right.register.int32_1 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
+ register.int32_2 = left.register.int32_2 < right.register.int32_2 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
+ register.int32_3 = left.register.int32_3 < right.register.int32_3 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- register.uint64_0 = left.register.uint64_0 < right.register.uint64_0 ? ConstantHelper.GetUInt64WithAllBitsSet() : (UInt64)0;
- register.uint64_1 = left.register.uint64_1 < right.register.uint64_1 ? ConstantHelper.GetUInt64WithAllBitsSet() : (UInt64)0;
+ register.uint64_0 = left.register.uint64_0 < right.register.uint64_0 ? ConstantHelper.GetUInt64WithAllBitsSet() : (ulong)0;
+ register.uint64_1 = left.register.uint64_1 < right.register.uint64_1 ? ConstantHelper.GetUInt64WithAllBitsSet() : (ulong)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- register.int64_0 = left.register.int64_0 < right.register.int64_0 ? ConstantHelper.GetInt64WithAllBitsSet() : (Int64)0;
- register.int64_1 = left.register.int64_1 < right.register.int64_1 ? ConstantHelper.GetInt64WithAllBitsSet() : (Int64)0;
+ register.int64_0 = left.register.int64_0 < right.register.int64_0 ? ConstantHelper.GetInt64WithAllBitsSet() : (long)0;
+ register.int64_1 = left.register.int64_1 < right.register.int64_1 ? ConstantHelper.GetInt64WithAllBitsSet() : (long)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- register.single_0 = left.register.single_0 < right.register.single_0 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
- register.single_1 = left.register.single_1 < right.register.single_1 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
- register.single_2 = left.register.single_2 < right.register.single_2 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
- register.single_3 = left.register.single_3 < right.register.single_3 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
+ register.single_0 = left.register.single_0 < right.register.single_0 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
+ register.single_1 = left.register.single_1 < right.register.single_1 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
+ register.single_2 = left.register.single_2 < right.register.single_2 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
+ register.single_3 = left.register.single_3 < right.register.single_3 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- register.double_0 = left.register.double_0 < right.register.double_0 ? ConstantHelper.GetDoubleWithAllBitsSet() : (Double)0;
- register.double_1 = left.register.double_1 < right.register.double_1 ? ConstantHelper.GetDoubleWithAllBitsSet() : (Double)0;
+ register.double_0 = left.register.double_0 < right.register.double_0 ? ConstantHelper.GetDoubleWithAllBitsSet() : (double)0;
+ register.double_1 = left.register.double_1 < right.register.double_1 ? ConstantHelper.GetDoubleWithAllBitsSet() : (double)0;
return new Vector<T>(ref register);
}
else
@@ -3335,93 +3370,93 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* dataPtr = stackalloc Byte[Count];
+ byte* dataPtr = stackalloc byte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* dataPtr = stackalloc UInt16[Count];
+ ushort* dataPtr = stackalloc ushort[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* dataPtr = stackalloc UInt32[Count];
+ uint* dataPtr = stackalloc uint[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* dataPtr = stackalloc UInt64[Count];
+ ulong* dataPtr = stackalloc ulong[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetUInt64WithAllBitsSet() : (UInt64)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetUInt64WithAllBitsSet() : (ulong)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetInt64WithAllBitsSet() : (Int64)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetInt64WithAllBitsSet() : (long)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetDoubleWithAllBitsSet() : (Double)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.GetDoubleWithAllBitsSet() : (double)0;
}
return new Vector<T>(dataPtr);
}
@@ -3433,110 +3468,110 @@ namespace System.Numerics
else
{
Register register = new Register();
- if (typeof(T) == typeof(Byte))
- {
- register.byte_0 = left.register.byte_0 > right.register.byte_0 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_1 = left.register.byte_1 > right.register.byte_1 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_2 = left.register.byte_2 > right.register.byte_2 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_3 = left.register.byte_3 > right.register.byte_3 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_4 = left.register.byte_4 > right.register.byte_4 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_5 = left.register.byte_5 > right.register.byte_5 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_6 = left.register.byte_6 > right.register.byte_6 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_7 = left.register.byte_7 > right.register.byte_7 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_8 = left.register.byte_8 > right.register.byte_8 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_9 = left.register.byte_9 > right.register.byte_9 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_10 = left.register.byte_10 > right.register.byte_10 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_11 = left.register.byte_11 > right.register.byte_11 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_12 = left.register.byte_12 > right.register.byte_12 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_13 = left.register.byte_13 > right.register.byte_13 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_14 = left.register.byte_14 > right.register.byte_14 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
- register.byte_15 = left.register.byte_15 > right.register.byte_15 ? ConstantHelper.GetByteWithAllBitsSet() : (Byte)0;
+ if (typeof(T) == typeof(byte))
+ {
+ register.byte_0 = left.register.byte_0 > right.register.byte_0 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_1 = left.register.byte_1 > right.register.byte_1 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_2 = left.register.byte_2 > right.register.byte_2 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_3 = left.register.byte_3 > right.register.byte_3 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_4 = left.register.byte_4 > right.register.byte_4 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_5 = left.register.byte_5 > right.register.byte_5 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_6 = left.register.byte_6 > right.register.byte_6 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_7 = left.register.byte_7 > right.register.byte_7 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_8 = left.register.byte_8 > right.register.byte_8 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_9 = left.register.byte_9 > right.register.byte_9 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_10 = left.register.byte_10 > right.register.byte_10 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_11 = left.register.byte_11 > right.register.byte_11 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_12 = left.register.byte_12 > right.register.byte_12 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_13 = left.register.byte_13 > right.register.byte_13 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_14 = left.register.byte_14 > right.register.byte_14 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
+ register.byte_15 = left.register.byte_15 > right.register.byte_15 ? ConstantHelper.GetByteWithAllBitsSet() : (byte)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(SByte))
- {
- register.sbyte_0 = left.register.sbyte_0 > right.register.sbyte_0 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_1 = left.register.sbyte_1 > right.register.sbyte_1 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_2 = left.register.sbyte_2 > right.register.sbyte_2 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_3 = left.register.sbyte_3 > right.register.sbyte_3 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_4 = left.register.sbyte_4 > right.register.sbyte_4 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_5 = left.register.sbyte_5 > right.register.sbyte_5 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_6 = left.register.sbyte_6 > right.register.sbyte_6 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_7 = left.register.sbyte_7 > right.register.sbyte_7 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_8 = left.register.sbyte_8 > right.register.sbyte_8 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_9 = left.register.sbyte_9 > right.register.sbyte_9 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_10 = left.register.sbyte_10 > right.register.sbyte_10 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_11 = left.register.sbyte_11 > right.register.sbyte_11 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_12 = left.register.sbyte_12 > right.register.sbyte_12 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_13 = left.register.sbyte_13 > right.register.sbyte_13 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_14 = left.register.sbyte_14 > right.register.sbyte_14 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
- register.sbyte_15 = left.register.sbyte_15 > right.register.sbyte_15 ? ConstantHelper.GetSByteWithAllBitsSet() : (SByte)0;
+ else if (typeof(T) == typeof(sbyte))
+ {
+ register.sbyte_0 = left.register.sbyte_0 > right.register.sbyte_0 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_1 = left.register.sbyte_1 > right.register.sbyte_1 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_2 = left.register.sbyte_2 > right.register.sbyte_2 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_3 = left.register.sbyte_3 > right.register.sbyte_3 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_4 = left.register.sbyte_4 > right.register.sbyte_4 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_5 = left.register.sbyte_5 > right.register.sbyte_5 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_6 = left.register.sbyte_6 > right.register.sbyte_6 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_7 = left.register.sbyte_7 > right.register.sbyte_7 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_8 = left.register.sbyte_8 > right.register.sbyte_8 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_9 = left.register.sbyte_9 > right.register.sbyte_9 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_10 = left.register.sbyte_10 > right.register.sbyte_10 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_11 = left.register.sbyte_11 > right.register.sbyte_11 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_12 = left.register.sbyte_12 > right.register.sbyte_12 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_13 = left.register.sbyte_13 > right.register.sbyte_13 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_14 = left.register.sbyte_14 > right.register.sbyte_14 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
+ register.sbyte_15 = left.register.sbyte_15 > right.register.sbyte_15 ? ConstantHelper.GetSByteWithAllBitsSet() : (sbyte)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- register.uint16_0 = left.register.uint16_0 > right.register.uint16_0 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_1 = left.register.uint16_1 > right.register.uint16_1 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_2 = left.register.uint16_2 > right.register.uint16_2 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_3 = left.register.uint16_3 > right.register.uint16_3 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_4 = left.register.uint16_4 > right.register.uint16_4 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_5 = left.register.uint16_5 > right.register.uint16_5 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_6 = left.register.uint16_6 > right.register.uint16_6 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
- register.uint16_7 = left.register.uint16_7 > right.register.uint16_7 ? ConstantHelper.GetUInt16WithAllBitsSet() : (UInt16)0;
+ register.uint16_0 = left.register.uint16_0 > right.register.uint16_0 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_1 = left.register.uint16_1 > right.register.uint16_1 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_2 = left.register.uint16_2 > right.register.uint16_2 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_3 = left.register.uint16_3 > right.register.uint16_3 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_4 = left.register.uint16_4 > right.register.uint16_4 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_5 = left.register.uint16_5 > right.register.uint16_5 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_6 = left.register.uint16_6 > right.register.uint16_6 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
+ register.uint16_7 = left.register.uint16_7 > right.register.uint16_7 ? ConstantHelper.GetUInt16WithAllBitsSet() : (ushort)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- register.int16_0 = left.register.int16_0 > right.register.int16_0 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_1 = left.register.int16_1 > right.register.int16_1 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_2 = left.register.int16_2 > right.register.int16_2 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_3 = left.register.int16_3 > right.register.int16_3 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_4 = left.register.int16_4 > right.register.int16_4 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_5 = left.register.int16_5 > right.register.int16_5 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_6 = left.register.int16_6 > right.register.int16_6 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
- register.int16_7 = left.register.int16_7 > right.register.int16_7 ? ConstantHelper.GetInt16WithAllBitsSet() : (Int16)0;
+ register.int16_0 = left.register.int16_0 > right.register.int16_0 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_1 = left.register.int16_1 > right.register.int16_1 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_2 = left.register.int16_2 > right.register.int16_2 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_3 = left.register.int16_3 > right.register.int16_3 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_4 = left.register.int16_4 > right.register.int16_4 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_5 = left.register.int16_5 > right.register.int16_5 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_6 = left.register.int16_6 > right.register.int16_6 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
+ register.int16_7 = left.register.int16_7 > right.register.int16_7 ? ConstantHelper.GetInt16WithAllBitsSet() : (short)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- register.uint32_0 = left.register.uint32_0 > right.register.uint32_0 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
- register.uint32_1 = left.register.uint32_1 > right.register.uint32_1 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
- register.uint32_2 = left.register.uint32_2 > right.register.uint32_2 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
- register.uint32_3 = left.register.uint32_3 > right.register.uint32_3 ? ConstantHelper.GetUInt32WithAllBitsSet() : (UInt32)0;
+ register.uint32_0 = left.register.uint32_0 > right.register.uint32_0 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
+ register.uint32_1 = left.register.uint32_1 > right.register.uint32_1 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
+ register.uint32_2 = left.register.uint32_2 > right.register.uint32_2 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
+ register.uint32_3 = left.register.uint32_3 > right.register.uint32_3 ? ConstantHelper.GetUInt32WithAllBitsSet() : (uint)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- register.int32_0 = left.register.int32_0 > right.register.int32_0 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
- register.int32_1 = left.register.int32_1 > right.register.int32_1 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
- register.int32_2 = left.register.int32_2 > right.register.int32_2 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
- register.int32_3 = left.register.int32_3 > right.register.int32_3 ? ConstantHelper.GetInt32WithAllBitsSet() : (Int32)0;
+ register.int32_0 = left.register.int32_0 > right.register.int32_0 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
+ register.int32_1 = left.register.int32_1 > right.register.int32_1 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
+ register.int32_2 = left.register.int32_2 > right.register.int32_2 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
+ register.int32_3 = left.register.int32_3 > right.register.int32_3 ? ConstantHelper.GetInt32WithAllBitsSet() : (int)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- register.uint64_0 = left.register.uint64_0 > right.register.uint64_0 ? ConstantHelper.GetUInt64WithAllBitsSet() : (UInt64)0;
- register.uint64_1 = left.register.uint64_1 > right.register.uint64_1 ? ConstantHelper.GetUInt64WithAllBitsSet() : (UInt64)0;
+ register.uint64_0 = left.register.uint64_0 > right.register.uint64_0 ? ConstantHelper.GetUInt64WithAllBitsSet() : (ulong)0;
+ register.uint64_1 = left.register.uint64_1 > right.register.uint64_1 ? ConstantHelper.GetUInt64WithAllBitsSet() : (ulong)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- register.int64_0 = left.register.int64_0 > right.register.int64_0 ? ConstantHelper.GetInt64WithAllBitsSet() : (Int64)0;
- register.int64_1 = left.register.int64_1 > right.register.int64_1 ? ConstantHelper.GetInt64WithAllBitsSet() : (Int64)0;
+ register.int64_0 = left.register.int64_0 > right.register.int64_0 ? ConstantHelper.GetInt64WithAllBitsSet() : (long)0;
+ register.int64_1 = left.register.int64_1 > right.register.int64_1 ? ConstantHelper.GetInt64WithAllBitsSet() : (long)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- register.single_0 = left.register.single_0 > right.register.single_0 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
- register.single_1 = left.register.single_1 > right.register.single_1 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
- register.single_2 = left.register.single_2 > right.register.single_2 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
- register.single_3 = left.register.single_3 > right.register.single_3 ? ConstantHelper.GetSingleWithAllBitsSet() : (Single)0;
+ register.single_0 = left.register.single_0 > right.register.single_0 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
+ register.single_1 = left.register.single_1 > right.register.single_1 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
+ register.single_2 = left.register.single_2 > right.register.single_2 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
+ register.single_3 = left.register.single_3 > right.register.single_3 ? ConstantHelper.GetSingleWithAllBitsSet() : (float)0;
return new Vector<T>(ref register);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- register.double_0 = left.register.double_0 > right.register.double_0 ? ConstantHelper.GetDoubleWithAllBitsSet() : (Double)0;
- register.double_1 = left.register.double_1 > right.register.double_1 ? ConstantHelper.GetDoubleWithAllBitsSet() : (Double)0;
+ register.double_0 = left.register.double_0 > right.register.double_0 ? ConstantHelper.GetDoubleWithAllBitsSet() : (double)0;
+ register.double_1 = left.register.double_1 > right.register.double_1 ? ConstantHelper.GetDoubleWithAllBitsSet() : (double)0;
return new Vector<T>(ref register);
}
else
@@ -3569,75 +3604,75 @@ namespace System.Numerics
[Intrinsic]
internal static unsafe Vector<T> Abs(Vector<T> value)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
return value;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
return value;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
return value;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
return value;
}
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(SByte))
+ if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (SByte)(object)(Math.Abs((SByte)(object)value[g]));
+ dataPtr[g] = (sbyte)(object)(Math.Abs((sbyte)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int16)(object)(Math.Abs((Int16)(object)value[g]));
+ dataPtr[g] = (short)(object)(Math.Abs((short)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int32)(object)(Math.Abs((Int32)(object)value[g]));
+ dataPtr[g] = (int)(object)(Math.Abs((int)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Int64)(object)(Math.Abs((Int64)(object)value[g]));
+ dataPtr[g] = (long)(object)(Math.Abs((long)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Single)(object)(Math.Abs((Single)(object)value[g]));
+ dataPtr[g] = (float)(object)(Math.Abs((float)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (Double)(object)(Math.Abs((Double)(object)value[g]));
+ dataPtr[g] = (double)(object)(Math.Abs((double)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
@@ -3648,64 +3683,64 @@ namespace System.Numerics
}
else
{
- if (typeof(T) == typeof(SByte))
- {
- value.register.sbyte_0 = (SByte)(Math.Abs(value.register.sbyte_0));
- value.register.sbyte_1 = (SByte)(Math.Abs(value.register.sbyte_1));
- value.register.sbyte_2 = (SByte)(Math.Abs(value.register.sbyte_2));
- value.register.sbyte_3 = (SByte)(Math.Abs(value.register.sbyte_3));
- value.register.sbyte_4 = (SByte)(Math.Abs(value.register.sbyte_4));
- value.register.sbyte_5 = (SByte)(Math.Abs(value.register.sbyte_5));
- value.register.sbyte_6 = (SByte)(Math.Abs(value.register.sbyte_6));
- value.register.sbyte_7 = (SByte)(Math.Abs(value.register.sbyte_7));
- value.register.sbyte_8 = (SByte)(Math.Abs(value.register.sbyte_8));
- value.register.sbyte_9 = (SByte)(Math.Abs(value.register.sbyte_9));
- value.register.sbyte_10 = (SByte)(Math.Abs(value.register.sbyte_10));
- value.register.sbyte_11 = (SByte)(Math.Abs(value.register.sbyte_11));
- value.register.sbyte_12 = (SByte)(Math.Abs(value.register.sbyte_12));
- value.register.sbyte_13 = (SByte)(Math.Abs(value.register.sbyte_13));
- value.register.sbyte_14 = (SByte)(Math.Abs(value.register.sbyte_14));
- value.register.sbyte_15 = (SByte)(Math.Abs(value.register.sbyte_15));
+ if (typeof(T) == typeof(sbyte))
+ {
+ value.register.sbyte_0 = (sbyte)(Math.Abs(value.register.sbyte_0));
+ value.register.sbyte_1 = (sbyte)(Math.Abs(value.register.sbyte_1));
+ value.register.sbyte_2 = (sbyte)(Math.Abs(value.register.sbyte_2));
+ value.register.sbyte_3 = (sbyte)(Math.Abs(value.register.sbyte_3));
+ value.register.sbyte_4 = (sbyte)(Math.Abs(value.register.sbyte_4));
+ value.register.sbyte_5 = (sbyte)(Math.Abs(value.register.sbyte_5));
+ value.register.sbyte_6 = (sbyte)(Math.Abs(value.register.sbyte_6));
+ value.register.sbyte_7 = (sbyte)(Math.Abs(value.register.sbyte_7));
+ value.register.sbyte_8 = (sbyte)(Math.Abs(value.register.sbyte_8));
+ value.register.sbyte_9 = (sbyte)(Math.Abs(value.register.sbyte_9));
+ value.register.sbyte_10 = (sbyte)(Math.Abs(value.register.sbyte_10));
+ value.register.sbyte_11 = (sbyte)(Math.Abs(value.register.sbyte_11));
+ value.register.sbyte_12 = (sbyte)(Math.Abs(value.register.sbyte_12));
+ value.register.sbyte_13 = (sbyte)(Math.Abs(value.register.sbyte_13));
+ value.register.sbyte_14 = (sbyte)(Math.Abs(value.register.sbyte_14));
+ value.register.sbyte_15 = (sbyte)(Math.Abs(value.register.sbyte_15));
return value;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- value.register.int16_0 = (Int16)(Math.Abs(value.register.int16_0));
- value.register.int16_1 = (Int16)(Math.Abs(value.register.int16_1));
- value.register.int16_2 = (Int16)(Math.Abs(value.register.int16_2));
- value.register.int16_3 = (Int16)(Math.Abs(value.register.int16_3));
- value.register.int16_4 = (Int16)(Math.Abs(value.register.int16_4));
- value.register.int16_5 = (Int16)(Math.Abs(value.register.int16_5));
- value.register.int16_6 = (Int16)(Math.Abs(value.register.int16_6));
- value.register.int16_7 = (Int16)(Math.Abs(value.register.int16_7));
+ value.register.int16_0 = (short)(Math.Abs(value.register.int16_0));
+ value.register.int16_1 = (short)(Math.Abs(value.register.int16_1));
+ value.register.int16_2 = (short)(Math.Abs(value.register.int16_2));
+ value.register.int16_3 = (short)(Math.Abs(value.register.int16_3));
+ value.register.int16_4 = (short)(Math.Abs(value.register.int16_4));
+ value.register.int16_5 = (short)(Math.Abs(value.register.int16_5));
+ value.register.int16_6 = (short)(Math.Abs(value.register.int16_6));
+ value.register.int16_7 = (short)(Math.Abs(value.register.int16_7));
return value;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- value.register.int32_0 = (Int32)(Math.Abs(value.register.int32_0));
- value.register.int32_1 = (Int32)(Math.Abs(value.register.int32_1));
- value.register.int32_2 = (Int32)(Math.Abs(value.register.int32_2));
- value.register.int32_3 = (Int32)(Math.Abs(value.register.int32_3));
+ value.register.int32_0 = (int)(Math.Abs(value.register.int32_0));
+ value.register.int32_1 = (int)(Math.Abs(value.register.int32_1));
+ value.register.int32_2 = (int)(Math.Abs(value.register.int32_2));
+ value.register.int32_3 = (int)(Math.Abs(value.register.int32_3));
return value;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- value.register.int64_0 = (Int64)(Math.Abs(value.register.int64_0));
- value.register.int64_1 = (Int64)(Math.Abs(value.register.int64_1));
+ value.register.int64_0 = (long)(Math.Abs(value.register.int64_0));
+ value.register.int64_1 = (long)(Math.Abs(value.register.int64_1));
return value;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- value.register.single_0 = (Single)(Math.Abs(value.register.single_0));
- value.register.single_1 = (Single)(Math.Abs(value.register.single_1));
- value.register.single_2 = (Single)(Math.Abs(value.register.single_2));
- value.register.single_3 = (Single)(Math.Abs(value.register.single_3));
+ value.register.single_0 = (float)(Math.Abs(value.register.single_0));
+ value.register.single_1 = (float)(Math.Abs(value.register.single_1));
+ value.register.single_2 = (float)(Math.Abs(value.register.single_2));
+ value.register.single_3 = (float)(Math.Abs(value.register.single_3));
return value;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- value.register.double_0 = (Double)(Math.Abs(value.register.double_0));
- value.register.double_1 = (Double)(Math.Abs(value.register.double_1));
+ value.register.double_0 = (double)(Math.Abs(value.register.double_0));
+ value.register.double_1 = (double)(Math.Abs(value.register.double_1));
return value;
}
else
@@ -3720,93 +3755,93 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* dataPtr = stackalloc Byte[Count];
+ byte* dataPtr = stackalloc byte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (Byte)(object)left[g] : (Byte)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (byte)(object)left[g] : (byte)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (SByte)(object)left[g] : (SByte)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (sbyte)(object)left[g] : (sbyte)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* dataPtr = stackalloc UInt16[Count];
+ ushort* dataPtr = stackalloc ushort[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (UInt16)(object)left[g] : (UInt16)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (ushort)(object)left[g] : (ushort)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (Int16)(object)left[g] : (Int16)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (short)(object)left[g] : (short)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* dataPtr = stackalloc UInt32[Count];
+ uint* dataPtr = stackalloc uint[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (UInt32)(object)left[g] : (UInt32)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (uint)(object)left[g] : (uint)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (Int32)(object)left[g] : (Int32)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (int)(object)left[g] : (int)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* dataPtr = stackalloc UInt64[Count];
+ ulong* dataPtr = stackalloc ulong[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (UInt64)(object)left[g] : (UInt64)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (ulong)(object)left[g] : (ulong)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (Int64)(object)left[g] : (Int64)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (long)(object)left[g] : (long)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (Single)(object)left[g] : (Single)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (float)(object)left[g] : (float)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (Double)(object)left[g] : (Double)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (double)(object)left[g] : (double)(object)right[g];
}
return new Vector<T>(dataPtr);
}
@@ -3818,7 +3853,7 @@ namespace System.Numerics
else
{
Vector<T> vec = new Vector<T>();
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
vec.register.byte_0 = left.register.byte_0 < right.register.byte_0 ? left.register.byte_0 : right.register.byte_0;
vec.register.byte_1 = left.register.byte_1 < right.register.byte_1 ? left.register.byte_1 : right.register.byte_1;
@@ -3838,7 +3873,7 @@ namespace System.Numerics
vec.register.byte_15 = left.register.byte_15 < right.register.byte_15 ? left.register.byte_15 : right.register.byte_15;
return vec;
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
vec.register.sbyte_0 = left.register.sbyte_0 < right.register.sbyte_0 ? left.register.sbyte_0 : right.register.sbyte_0;
vec.register.sbyte_1 = left.register.sbyte_1 < right.register.sbyte_1 ? left.register.sbyte_1 : right.register.sbyte_1;
@@ -3858,7 +3893,7 @@ namespace System.Numerics
vec.register.sbyte_15 = left.register.sbyte_15 < right.register.sbyte_15 ? left.register.sbyte_15 : right.register.sbyte_15;
return vec;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
vec.register.uint16_0 = left.register.uint16_0 < right.register.uint16_0 ? left.register.uint16_0 : right.register.uint16_0;
vec.register.uint16_1 = left.register.uint16_1 < right.register.uint16_1 ? left.register.uint16_1 : right.register.uint16_1;
@@ -3870,7 +3905,7 @@ namespace System.Numerics
vec.register.uint16_7 = left.register.uint16_7 < right.register.uint16_7 ? left.register.uint16_7 : right.register.uint16_7;
return vec;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
vec.register.int16_0 = left.register.int16_0 < right.register.int16_0 ? left.register.int16_0 : right.register.int16_0;
vec.register.int16_1 = left.register.int16_1 < right.register.int16_1 ? left.register.int16_1 : right.register.int16_1;
@@ -3882,7 +3917,7 @@ namespace System.Numerics
vec.register.int16_7 = left.register.int16_7 < right.register.int16_7 ? left.register.int16_7 : right.register.int16_7;
return vec;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
vec.register.uint32_0 = left.register.uint32_0 < right.register.uint32_0 ? left.register.uint32_0 : right.register.uint32_0;
vec.register.uint32_1 = left.register.uint32_1 < right.register.uint32_1 ? left.register.uint32_1 : right.register.uint32_1;
@@ -3890,7 +3925,7 @@ namespace System.Numerics
vec.register.uint32_3 = left.register.uint32_3 < right.register.uint32_3 ? left.register.uint32_3 : right.register.uint32_3;
return vec;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
vec.register.int32_0 = left.register.int32_0 < right.register.int32_0 ? left.register.int32_0 : right.register.int32_0;
vec.register.int32_1 = left.register.int32_1 < right.register.int32_1 ? left.register.int32_1 : right.register.int32_1;
@@ -3898,19 +3933,19 @@ namespace System.Numerics
vec.register.int32_3 = left.register.int32_3 < right.register.int32_3 ? left.register.int32_3 : right.register.int32_3;
return vec;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
vec.register.uint64_0 = left.register.uint64_0 < right.register.uint64_0 ? left.register.uint64_0 : right.register.uint64_0;
vec.register.uint64_1 = left.register.uint64_1 < right.register.uint64_1 ? left.register.uint64_1 : right.register.uint64_1;
return vec;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
vec.register.int64_0 = left.register.int64_0 < right.register.int64_0 ? left.register.int64_0 : right.register.int64_0;
vec.register.int64_1 = left.register.int64_1 < right.register.int64_1 ? left.register.int64_1 : right.register.int64_1;
return vec;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
vec.register.single_0 = left.register.single_0 < right.register.single_0 ? left.register.single_0 : right.register.single_0;
vec.register.single_1 = left.register.single_1 < right.register.single_1 ? left.register.single_1 : right.register.single_1;
@@ -3918,7 +3953,7 @@ namespace System.Numerics
vec.register.single_3 = left.register.single_3 < right.register.single_3 ? left.register.single_3 : right.register.single_3;
return vec;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
vec.register.double_0 = left.register.double_0 < right.register.double_0 ? left.register.double_0 : right.register.double_0;
vec.register.double_1 = left.register.double_1 < right.register.double_1 ? left.register.double_1 : right.register.double_1;
@@ -3936,93 +3971,93 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* dataPtr = stackalloc Byte[Count];
+ byte* dataPtr = stackalloc byte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (Byte)(object)left[g] : (Byte)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (byte)(object)left[g] : (byte)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (SByte)(object)left[g] : (SByte)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (sbyte)(object)left[g] : (sbyte)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* dataPtr = stackalloc UInt16[Count];
+ ushort* dataPtr = stackalloc ushort[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (UInt16)(object)left[g] : (UInt16)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (ushort)(object)left[g] : (ushort)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (Int16)(object)left[g] : (Int16)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (short)(object)left[g] : (short)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* dataPtr = stackalloc UInt32[Count];
+ uint* dataPtr = stackalloc uint[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (UInt32)(object)left[g] : (UInt32)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (uint)(object)left[g] : (uint)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (Int32)(object)left[g] : (Int32)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (int)(object)left[g] : (int)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* dataPtr = stackalloc UInt64[Count];
+ ulong* dataPtr = stackalloc ulong[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (UInt64)(object)left[g] : (UInt64)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (ulong)(object)left[g] : (ulong)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (Int64)(object)left[g] : (Int64)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (long)(object)left[g] : (long)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (Single)(object)left[g] : (Single)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (float)(object)left[g] : (float)(object)right[g];
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (Double)(object)left[g] : (Double)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (double)(object)left[g] : (double)(object)right[g];
}
return new Vector<T>(dataPtr);
}
@@ -4034,7 +4069,7 @@ namespace System.Numerics
else
{
Vector<T> vec = new Vector<T>();
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
vec.register.byte_0 = left.register.byte_0 > right.register.byte_0 ? left.register.byte_0 : right.register.byte_0;
vec.register.byte_1 = left.register.byte_1 > right.register.byte_1 ? left.register.byte_1 : right.register.byte_1;
@@ -4054,7 +4089,7 @@ namespace System.Numerics
vec.register.byte_15 = left.register.byte_15 > right.register.byte_15 ? left.register.byte_15 : right.register.byte_15;
return vec;
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
vec.register.sbyte_0 = left.register.sbyte_0 > right.register.sbyte_0 ? left.register.sbyte_0 : right.register.sbyte_0;
vec.register.sbyte_1 = left.register.sbyte_1 > right.register.sbyte_1 ? left.register.sbyte_1 : right.register.sbyte_1;
@@ -4074,7 +4109,7 @@ namespace System.Numerics
vec.register.sbyte_15 = left.register.sbyte_15 > right.register.sbyte_15 ? left.register.sbyte_15 : right.register.sbyte_15;
return vec;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
vec.register.uint16_0 = left.register.uint16_0 > right.register.uint16_0 ? left.register.uint16_0 : right.register.uint16_0;
vec.register.uint16_1 = left.register.uint16_1 > right.register.uint16_1 ? left.register.uint16_1 : right.register.uint16_1;
@@ -4086,7 +4121,7 @@ namespace System.Numerics
vec.register.uint16_7 = left.register.uint16_7 > right.register.uint16_7 ? left.register.uint16_7 : right.register.uint16_7;
return vec;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
vec.register.int16_0 = left.register.int16_0 > right.register.int16_0 ? left.register.int16_0 : right.register.int16_0;
vec.register.int16_1 = left.register.int16_1 > right.register.int16_1 ? left.register.int16_1 : right.register.int16_1;
@@ -4098,7 +4133,7 @@ namespace System.Numerics
vec.register.int16_7 = left.register.int16_7 > right.register.int16_7 ? left.register.int16_7 : right.register.int16_7;
return vec;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
vec.register.uint32_0 = left.register.uint32_0 > right.register.uint32_0 ? left.register.uint32_0 : right.register.uint32_0;
vec.register.uint32_1 = left.register.uint32_1 > right.register.uint32_1 ? left.register.uint32_1 : right.register.uint32_1;
@@ -4106,7 +4141,7 @@ namespace System.Numerics
vec.register.uint32_3 = left.register.uint32_3 > right.register.uint32_3 ? left.register.uint32_3 : right.register.uint32_3;
return vec;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
vec.register.int32_0 = left.register.int32_0 > right.register.int32_0 ? left.register.int32_0 : right.register.int32_0;
vec.register.int32_1 = left.register.int32_1 > right.register.int32_1 ? left.register.int32_1 : right.register.int32_1;
@@ -4114,19 +4149,19 @@ namespace System.Numerics
vec.register.int32_3 = left.register.int32_3 > right.register.int32_3 ? left.register.int32_3 : right.register.int32_3;
return vec;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
vec.register.uint64_0 = left.register.uint64_0 > right.register.uint64_0 ? left.register.uint64_0 : right.register.uint64_0;
vec.register.uint64_1 = left.register.uint64_1 > right.register.uint64_1 ? left.register.uint64_1 : right.register.uint64_1;
return vec;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
vec.register.int64_0 = left.register.int64_0 > right.register.int64_0 ? left.register.int64_0 : right.register.int64_0;
vec.register.int64_1 = left.register.int64_1 > right.register.int64_1 ? left.register.int64_1 : right.register.int64_1;
return vec;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
vec.register.single_0 = left.register.single_0 > right.register.single_0 ? left.register.single_0 : right.register.single_0;
vec.register.single_1 = left.register.single_1 > right.register.single_1 ? left.register.single_1 : right.register.single_1;
@@ -4134,7 +4169,7 @@ namespace System.Numerics
vec.register.single_3 = left.register.single_3 > right.register.single_3 ? left.register.single_3 : right.register.single_3;
return vec;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
vec.register.double_0 = left.register.double_0 > right.register.double_0 ? left.register.double_0 : right.register.double_0;
vec.register.double_1 = left.register.double_1 > right.register.double_1 ? left.register.double_1 : right.register.double_1;
@@ -4161,120 +4196,120 @@ namespace System.Numerics
}
else
{
- if (typeof(T) == typeof(Byte))
- {
- Byte product = 0;
- product += (Byte)(left.register.byte_0 * right.register.byte_0);
- product += (Byte)(left.register.byte_1 * right.register.byte_1);
- product += (Byte)(left.register.byte_2 * right.register.byte_2);
- product += (Byte)(left.register.byte_3 * right.register.byte_3);
- product += (Byte)(left.register.byte_4 * right.register.byte_4);
- product += (Byte)(left.register.byte_5 * right.register.byte_5);
- product += (Byte)(left.register.byte_6 * right.register.byte_6);
- product += (Byte)(left.register.byte_7 * right.register.byte_7);
- product += (Byte)(left.register.byte_8 * right.register.byte_8);
- product += (Byte)(left.register.byte_9 * right.register.byte_9);
- product += (Byte)(left.register.byte_10 * right.register.byte_10);
- product += (Byte)(left.register.byte_11 * right.register.byte_11);
- product += (Byte)(left.register.byte_12 * right.register.byte_12);
- product += (Byte)(left.register.byte_13 * right.register.byte_13);
- product += (Byte)(left.register.byte_14 * right.register.byte_14);
- product += (Byte)(left.register.byte_15 * right.register.byte_15);
+ if (typeof(T) == typeof(byte))
+ {
+ byte product = 0;
+ product += (byte)(left.register.byte_0 * right.register.byte_0);
+ product += (byte)(left.register.byte_1 * right.register.byte_1);
+ product += (byte)(left.register.byte_2 * right.register.byte_2);
+ product += (byte)(left.register.byte_3 * right.register.byte_3);
+ product += (byte)(left.register.byte_4 * right.register.byte_4);
+ product += (byte)(left.register.byte_5 * right.register.byte_5);
+ product += (byte)(left.register.byte_6 * right.register.byte_6);
+ product += (byte)(left.register.byte_7 * right.register.byte_7);
+ product += (byte)(left.register.byte_8 * right.register.byte_8);
+ product += (byte)(left.register.byte_9 * right.register.byte_9);
+ product += (byte)(left.register.byte_10 * right.register.byte_10);
+ product += (byte)(left.register.byte_11 * right.register.byte_11);
+ product += (byte)(left.register.byte_12 * right.register.byte_12);
+ product += (byte)(left.register.byte_13 * right.register.byte_13);
+ product += (byte)(left.register.byte_14 * right.register.byte_14);
+ product += (byte)(left.register.byte_15 * right.register.byte_15);
return (T)(object)product;
}
- else if (typeof(T) == typeof(SByte))
- {
- SByte product = 0;
- product += (SByte)(left.register.sbyte_0 * right.register.sbyte_0);
- product += (SByte)(left.register.sbyte_1 * right.register.sbyte_1);
- product += (SByte)(left.register.sbyte_2 * right.register.sbyte_2);
- product += (SByte)(left.register.sbyte_3 * right.register.sbyte_3);
- product += (SByte)(left.register.sbyte_4 * right.register.sbyte_4);
- product += (SByte)(left.register.sbyte_5 * right.register.sbyte_5);
- product += (SByte)(left.register.sbyte_6 * right.register.sbyte_6);
- product += (SByte)(left.register.sbyte_7 * right.register.sbyte_7);
- product += (SByte)(left.register.sbyte_8 * right.register.sbyte_8);
- product += (SByte)(left.register.sbyte_9 * right.register.sbyte_9);
- product += (SByte)(left.register.sbyte_10 * right.register.sbyte_10);
- product += (SByte)(left.register.sbyte_11 * right.register.sbyte_11);
- product += (SByte)(left.register.sbyte_12 * right.register.sbyte_12);
- product += (SByte)(left.register.sbyte_13 * right.register.sbyte_13);
- product += (SByte)(left.register.sbyte_14 * right.register.sbyte_14);
- product += (SByte)(left.register.sbyte_15 * right.register.sbyte_15);
+ else if (typeof(T) == typeof(sbyte))
+ {
+ sbyte product = 0;
+ product += (sbyte)(left.register.sbyte_0 * right.register.sbyte_0);
+ product += (sbyte)(left.register.sbyte_1 * right.register.sbyte_1);
+ product += (sbyte)(left.register.sbyte_2 * right.register.sbyte_2);
+ product += (sbyte)(left.register.sbyte_3 * right.register.sbyte_3);
+ product += (sbyte)(left.register.sbyte_4 * right.register.sbyte_4);
+ product += (sbyte)(left.register.sbyte_5 * right.register.sbyte_5);
+ product += (sbyte)(left.register.sbyte_6 * right.register.sbyte_6);
+ product += (sbyte)(left.register.sbyte_7 * right.register.sbyte_7);
+ product += (sbyte)(left.register.sbyte_8 * right.register.sbyte_8);
+ product += (sbyte)(left.register.sbyte_9 * right.register.sbyte_9);
+ product += (sbyte)(left.register.sbyte_10 * right.register.sbyte_10);
+ product += (sbyte)(left.register.sbyte_11 * right.register.sbyte_11);
+ product += (sbyte)(left.register.sbyte_12 * right.register.sbyte_12);
+ product += (sbyte)(left.register.sbyte_13 * right.register.sbyte_13);
+ product += (sbyte)(left.register.sbyte_14 * right.register.sbyte_14);
+ product += (sbyte)(left.register.sbyte_15 * right.register.sbyte_15);
return (T)(object)product;
}
- else if (typeof(T) == typeof(UInt16))
- {
- UInt16 product = 0;
- product += (UInt16)(left.register.uint16_0 * right.register.uint16_0);
- product += (UInt16)(left.register.uint16_1 * right.register.uint16_1);
- product += (UInt16)(left.register.uint16_2 * right.register.uint16_2);
- product += (UInt16)(left.register.uint16_3 * right.register.uint16_3);
- product += (UInt16)(left.register.uint16_4 * right.register.uint16_4);
- product += (UInt16)(left.register.uint16_5 * right.register.uint16_5);
- product += (UInt16)(left.register.uint16_6 * right.register.uint16_6);
- product += (UInt16)(left.register.uint16_7 * right.register.uint16_7);
+ else if (typeof(T) == typeof(ushort))
+ {
+ ushort product = 0;
+ product += (ushort)(left.register.uint16_0 * right.register.uint16_0);
+ product += (ushort)(left.register.uint16_1 * right.register.uint16_1);
+ product += (ushort)(left.register.uint16_2 * right.register.uint16_2);
+ product += (ushort)(left.register.uint16_3 * right.register.uint16_3);
+ product += (ushort)(left.register.uint16_4 * right.register.uint16_4);
+ product += (ushort)(left.register.uint16_5 * right.register.uint16_5);
+ product += (ushort)(left.register.uint16_6 * right.register.uint16_6);
+ product += (ushort)(left.register.uint16_7 * right.register.uint16_7);
return (T)(object)product;
}
- else if (typeof(T) == typeof(Int16))
- {
- Int16 product = 0;
- product += (Int16)(left.register.int16_0 * right.register.int16_0);
- product += (Int16)(left.register.int16_1 * right.register.int16_1);
- product += (Int16)(left.register.int16_2 * right.register.int16_2);
- product += (Int16)(left.register.int16_3 * right.register.int16_3);
- product += (Int16)(left.register.int16_4 * right.register.int16_4);
- product += (Int16)(left.register.int16_5 * right.register.int16_5);
- product += (Int16)(left.register.int16_6 * right.register.int16_6);
- product += (Int16)(left.register.int16_7 * right.register.int16_7);
+ else if (typeof(T) == typeof(short))
+ {
+ short product = 0;
+ product += (short)(left.register.int16_0 * right.register.int16_0);
+ product += (short)(left.register.int16_1 * right.register.int16_1);
+ product += (short)(left.register.int16_2 * right.register.int16_2);
+ product += (short)(left.register.int16_3 * right.register.int16_3);
+ product += (short)(left.register.int16_4 * right.register.int16_4);
+ product += (short)(left.register.int16_5 * right.register.int16_5);
+ product += (short)(left.register.int16_6 * right.register.int16_6);
+ product += (short)(left.register.int16_7 * right.register.int16_7);
return (T)(object)product;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32 product = 0;
- product += (UInt32)(left.register.uint32_0 * right.register.uint32_0);
- product += (UInt32)(left.register.uint32_1 * right.register.uint32_1);
- product += (UInt32)(left.register.uint32_2 * right.register.uint32_2);
- product += (UInt32)(left.register.uint32_3 * right.register.uint32_3);
+ uint product = 0;
+ product += (uint)(left.register.uint32_0 * right.register.uint32_0);
+ product += (uint)(left.register.uint32_1 * right.register.uint32_1);
+ product += (uint)(left.register.uint32_2 * right.register.uint32_2);
+ product += (uint)(left.register.uint32_3 * right.register.uint32_3);
return (T)(object)product;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32 product = 0;
- product += (Int32)(left.register.int32_0 * right.register.int32_0);
- product += (Int32)(left.register.int32_1 * right.register.int32_1);
- product += (Int32)(left.register.int32_2 * right.register.int32_2);
- product += (Int32)(left.register.int32_3 * right.register.int32_3);
+ int product = 0;
+ product += (int)(left.register.int32_0 * right.register.int32_0);
+ product += (int)(left.register.int32_1 * right.register.int32_1);
+ product += (int)(left.register.int32_2 * right.register.int32_2);
+ product += (int)(left.register.int32_3 * right.register.int32_3);
return (T)(object)product;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64 product = 0;
- product += (UInt64)(left.register.uint64_0 * right.register.uint64_0);
- product += (UInt64)(left.register.uint64_1 * right.register.uint64_1);
+ ulong product = 0;
+ product += (ulong)(left.register.uint64_0 * right.register.uint64_0);
+ product += (ulong)(left.register.uint64_1 * right.register.uint64_1);
return (T)(object)product;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64 product = 0;
- product += (Int64)(left.register.int64_0 * right.register.int64_0);
- product += (Int64)(left.register.int64_1 * right.register.int64_1);
+ long product = 0;
+ product += (long)(left.register.int64_0 * right.register.int64_0);
+ product += (long)(left.register.int64_1 * right.register.int64_1);
return (T)(object)product;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single product = 0;
- product += (Single)(left.register.single_0 * right.register.single_0);
- product += (Single)(left.register.single_1 * right.register.single_1);
- product += (Single)(left.register.single_2 * right.register.single_2);
- product += (Single)(left.register.single_3 * right.register.single_3);
+ float product = 0;
+ product += (float)(left.register.single_0 * right.register.single_0);
+ product += (float)(left.register.single_1 * right.register.single_1);
+ product += (float)(left.register.single_2 * right.register.single_2);
+ product += (float)(left.register.single_3 * right.register.single_3);
return (T)(object)product;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double product = 0;
- product += (Double)(left.register.double_0 * right.register.double_0);
- product += (Double)(left.register.double_1 * right.register.double_1);
+ double product = 0;
+ product += (double)(left.register.double_0 * right.register.double_0);
+ product += (double)(left.register.double_1 * right.register.double_1);
return (T)(object)product;
}
else
@@ -4289,93 +4324,93 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte* dataPtr = stackalloc Byte[Count];
+ byte* dataPtr = stackalloc byte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((Byte)Math.Sqrt((Byte)(object)value[g]));
+ dataPtr[g] = unchecked((byte)Math.Sqrt((byte)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte* dataPtr = stackalloc SByte[Count];
+ sbyte* dataPtr = stackalloc sbyte[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((SByte)Math.Sqrt((SByte)(object)value[g]));
+ dataPtr[g] = unchecked((sbyte)Math.Sqrt((sbyte)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16* dataPtr = stackalloc UInt16[Count];
+ ushort* dataPtr = stackalloc ushort[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((UInt16)Math.Sqrt((UInt16)(object)value[g]));
+ dataPtr[g] = unchecked((ushort)Math.Sqrt((ushort)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16* dataPtr = stackalloc Int16[Count];
+ short* dataPtr = stackalloc short[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((Int16)Math.Sqrt((Int16)(object)value[g]));
+ dataPtr[g] = unchecked((short)Math.Sqrt((short)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32* dataPtr = stackalloc UInt32[Count];
+ uint* dataPtr = stackalloc uint[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((UInt32)Math.Sqrt((UInt32)(object)value[g]));
+ dataPtr[g] = unchecked((uint)Math.Sqrt((uint)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32* dataPtr = stackalloc Int32[Count];
+ int* dataPtr = stackalloc int[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((Int32)Math.Sqrt((Int32)(object)value[g]));
+ dataPtr[g] = unchecked((int)Math.Sqrt((int)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64* dataPtr = stackalloc UInt64[Count];
+ ulong* dataPtr = stackalloc ulong[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((UInt64)Math.Sqrt((UInt64)(object)value[g]));
+ dataPtr[g] = unchecked((ulong)Math.Sqrt((ulong)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64* dataPtr = stackalloc Int64[Count];
+ long* dataPtr = stackalloc long[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((Int64)Math.Sqrt((Int64)(object)value[g]));
+ dataPtr[g] = unchecked((long)Math.Sqrt((long)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single* dataPtr = stackalloc Single[Count];
+ float* dataPtr = stackalloc float[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((Single)Math.Sqrt((Single)(object)value[g]));
+ dataPtr[g] = unchecked((float)Math.Sqrt((float)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double* dataPtr = stackalloc Double[Count];
+ double* dataPtr = stackalloc double[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((Double)Math.Sqrt((Double)(object)value[g]));
+ dataPtr[g] = unchecked((double)Math.Sqrt((double)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
@@ -4386,110 +4421,110 @@ namespace System.Numerics
}
else
{
- if (typeof(T) == typeof(Byte))
- {
- value.register.byte_0 = (Byte)Math.Sqrt(value.register.byte_0);
- value.register.byte_1 = (Byte)Math.Sqrt(value.register.byte_1);
- value.register.byte_2 = (Byte)Math.Sqrt(value.register.byte_2);
- value.register.byte_3 = (Byte)Math.Sqrt(value.register.byte_3);
- value.register.byte_4 = (Byte)Math.Sqrt(value.register.byte_4);
- value.register.byte_5 = (Byte)Math.Sqrt(value.register.byte_5);
- value.register.byte_6 = (Byte)Math.Sqrt(value.register.byte_6);
- value.register.byte_7 = (Byte)Math.Sqrt(value.register.byte_7);
- value.register.byte_8 = (Byte)Math.Sqrt(value.register.byte_8);
- value.register.byte_9 = (Byte)Math.Sqrt(value.register.byte_9);
- value.register.byte_10 = (Byte)Math.Sqrt(value.register.byte_10);
- value.register.byte_11 = (Byte)Math.Sqrt(value.register.byte_11);
- value.register.byte_12 = (Byte)Math.Sqrt(value.register.byte_12);
- value.register.byte_13 = (Byte)Math.Sqrt(value.register.byte_13);
- value.register.byte_14 = (Byte)Math.Sqrt(value.register.byte_14);
- value.register.byte_15 = (Byte)Math.Sqrt(value.register.byte_15);
+ if (typeof(T) == typeof(byte))
+ {
+ value.register.byte_0 = (byte)Math.Sqrt(value.register.byte_0);
+ value.register.byte_1 = (byte)Math.Sqrt(value.register.byte_1);
+ value.register.byte_2 = (byte)Math.Sqrt(value.register.byte_2);
+ value.register.byte_3 = (byte)Math.Sqrt(value.register.byte_3);
+ value.register.byte_4 = (byte)Math.Sqrt(value.register.byte_4);
+ value.register.byte_5 = (byte)Math.Sqrt(value.register.byte_5);
+ value.register.byte_6 = (byte)Math.Sqrt(value.register.byte_6);
+ value.register.byte_7 = (byte)Math.Sqrt(value.register.byte_7);
+ value.register.byte_8 = (byte)Math.Sqrt(value.register.byte_8);
+ value.register.byte_9 = (byte)Math.Sqrt(value.register.byte_9);
+ value.register.byte_10 = (byte)Math.Sqrt(value.register.byte_10);
+ value.register.byte_11 = (byte)Math.Sqrt(value.register.byte_11);
+ value.register.byte_12 = (byte)Math.Sqrt(value.register.byte_12);
+ value.register.byte_13 = (byte)Math.Sqrt(value.register.byte_13);
+ value.register.byte_14 = (byte)Math.Sqrt(value.register.byte_14);
+ value.register.byte_15 = (byte)Math.Sqrt(value.register.byte_15);
return value;
}
- else if (typeof(T) == typeof(SByte))
- {
- value.register.sbyte_0 = (SByte)Math.Sqrt(value.register.sbyte_0);
- value.register.sbyte_1 = (SByte)Math.Sqrt(value.register.sbyte_1);
- value.register.sbyte_2 = (SByte)Math.Sqrt(value.register.sbyte_2);
- value.register.sbyte_3 = (SByte)Math.Sqrt(value.register.sbyte_3);
- value.register.sbyte_4 = (SByte)Math.Sqrt(value.register.sbyte_4);
- value.register.sbyte_5 = (SByte)Math.Sqrt(value.register.sbyte_5);
- value.register.sbyte_6 = (SByte)Math.Sqrt(value.register.sbyte_6);
- value.register.sbyte_7 = (SByte)Math.Sqrt(value.register.sbyte_7);
- value.register.sbyte_8 = (SByte)Math.Sqrt(value.register.sbyte_8);
- value.register.sbyte_9 = (SByte)Math.Sqrt(value.register.sbyte_9);
- value.register.sbyte_10 = (SByte)Math.Sqrt(value.register.sbyte_10);
- value.register.sbyte_11 = (SByte)Math.Sqrt(value.register.sbyte_11);
- value.register.sbyte_12 = (SByte)Math.Sqrt(value.register.sbyte_12);
- value.register.sbyte_13 = (SByte)Math.Sqrt(value.register.sbyte_13);
- value.register.sbyte_14 = (SByte)Math.Sqrt(value.register.sbyte_14);
- value.register.sbyte_15 = (SByte)Math.Sqrt(value.register.sbyte_15);
+ else if (typeof(T) == typeof(sbyte))
+ {
+ value.register.sbyte_0 = (sbyte)Math.Sqrt(value.register.sbyte_0);
+ value.register.sbyte_1 = (sbyte)Math.Sqrt(value.register.sbyte_1);
+ value.register.sbyte_2 = (sbyte)Math.Sqrt(value.register.sbyte_2);
+ value.register.sbyte_3 = (sbyte)Math.Sqrt(value.register.sbyte_3);
+ value.register.sbyte_4 = (sbyte)Math.Sqrt(value.register.sbyte_4);
+ value.register.sbyte_5 = (sbyte)Math.Sqrt(value.register.sbyte_5);
+ value.register.sbyte_6 = (sbyte)Math.Sqrt(value.register.sbyte_6);
+ value.register.sbyte_7 = (sbyte)Math.Sqrt(value.register.sbyte_7);
+ value.register.sbyte_8 = (sbyte)Math.Sqrt(value.register.sbyte_8);
+ value.register.sbyte_9 = (sbyte)Math.Sqrt(value.register.sbyte_9);
+ value.register.sbyte_10 = (sbyte)Math.Sqrt(value.register.sbyte_10);
+ value.register.sbyte_11 = (sbyte)Math.Sqrt(value.register.sbyte_11);
+ value.register.sbyte_12 = (sbyte)Math.Sqrt(value.register.sbyte_12);
+ value.register.sbyte_13 = (sbyte)Math.Sqrt(value.register.sbyte_13);
+ value.register.sbyte_14 = (sbyte)Math.Sqrt(value.register.sbyte_14);
+ value.register.sbyte_15 = (sbyte)Math.Sqrt(value.register.sbyte_15);
return value;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- value.register.uint16_0 = (UInt16)Math.Sqrt(value.register.uint16_0);
- value.register.uint16_1 = (UInt16)Math.Sqrt(value.register.uint16_1);
- value.register.uint16_2 = (UInt16)Math.Sqrt(value.register.uint16_2);
- value.register.uint16_3 = (UInt16)Math.Sqrt(value.register.uint16_3);
- value.register.uint16_4 = (UInt16)Math.Sqrt(value.register.uint16_4);
- value.register.uint16_5 = (UInt16)Math.Sqrt(value.register.uint16_5);
- value.register.uint16_6 = (UInt16)Math.Sqrt(value.register.uint16_6);
- value.register.uint16_7 = (UInt16)Math.Sqrt(value.register.uint16_7);
+ value.register.uint16_0 = (ushort)Math.Sqrt(value.register.uint16_0);
+ value.register.uint16_1 = (ushort)Math.Sqrt(value.register.uint16_1);
+ value.register.uint16_2 = (ushort)Math.Sqrt(value.register.uint16_2);
+ value.register.uint16_3 = (ushort)Math.Sqrt(value.register.uint16_3);
+ value.register.uint16_4 = (ushort)Math.Sqrt(value.register.uint16_4);
+ value.register.uint16_5 = (ushort)Math.Sqrt(value.register.uint16_5);
+ value.register.uint16_6 = (ushort)Math.Sqrt(value.register.uint16_6);
+ value.register.uint16_7 = (ushort)Math.Sqrt(value.register.uint16_7);
return value;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- value.register.int16_0 = (Int16)Math.Sqrt(value.register.int16_0);
- value.register.int16_1 = (Int16)Math.Sqrt(value.register.int16_1);
- value.register.int16_2 = (Int16)Math.Sqrt(value.register.int16_2);
- value.register.int16_3 = (Int16)Math.Sqrt(value.register.int16_3);
- value.register.int16_4 = (Int16)Math.Sqrt(value.register.int16_4);
- value.register.int16_5 = (Int16)Math.Sqrt(value.register.int16_5);
- value.register.int16_6 = (Int16)Math.Sqrt(value.register.int16_6);
- value.register.int16_7 = (Int16)Math.Sqrt(value.register.int16_7);
+ value.register.int16_0 = (short)Math.Sqrt(value.register.int16_0);
+ value.register.int16_1 = (short)Math.Sqrt(value.register.int16_1);
+ value.register.int16_2 = (short)Math.Sqrt(value.register.int16_2);
+ value.register.int16_3 = (short)Math.Sqrt(value.register.int16_3);
+ value.register.int16_4 = (short)Math.Sqrt(value.register.int16_4);
+ value.register.int16_5 = (short)Math.Sqrt(value.register.int16_5);
+ value.register.int16_6 = (short)Math.Sqrt(value.register.int16_6);
+ value.register.int16_7 = (short)Math.Sqrt(value.register.int16_7);
return value;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- value.register.uint32_0 = (UInt32)Math.Sqrt(value.register.uint32_0);
- value.register.uint32_1 = (UInt32)Math.Sqrt(value.register.uint32_1);
- value.register.uint32_2 = (UInt32)Math.Sqrt(value.register.uint32_2);
- value.register.uint32_3 = (UInt32)Math.Sqrt(value.register.uint32_3);
+ value.register.uint32_0 = (uint)Math.Sqrt(value.register.uint32_0);
+ value.register.uint32_1 = (uint)Math.Sqrt(value.register.uint32_1);
+ value.register.uint32_2 = (uint)Math.Sqrt(value.register.uint32_2);
+ value.register.uint32_3 = (uint)Math.Sqrt(value.register.uint32_3);
return value;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- value.register.int32_0 = (Int32)Math.Sqrt(value.register.int32_0);
- value.register.int32_1 = (Int32)Math.Sqrt(value.register.int32_1);
- value.register.int32_2 = (Int32)Math.Sqrt(value.register.int32_2);
- value.register.int32_3 = (Int32)Math.Sqrt(value.register.int32_3);
+ value.register.int32_0 = (int)Math.Sqrt(value.register.int32_0);
+ value.register.int32_1 = (int)Math.Sqrt(value.register.int32_1);
+ value.register.int32_2 = (int)Math.Sqrt(value.register.int32_2);
+ value.register.int32_3 = (int)Math.Sqrt(value.register.int32_3);
return value;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- value.register.uint64_0 = (UInt64)Math.Sqrt(value.register.uint64_0);
- value.register.uint64_1 = (UInt64)Math.Sqrt(value.register.uint64_1);
+ value.register.uint64_0 = (ulong)Math.Sqrt(value.register.uint64_0);
+ value.register.uint64_1 = (ulong)Math.Sqrt(value.register.uint64_1);
return value;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- value.register.int64_0 = (Int64)Math.Sqrt(value.register.int64_0);
- value.register.int64_1 = (Int64)Math.Sqrt(value.register.int64_1);
+ value.register.int64_0 = (long)Math.Sqrt(value.register.int64_0);
+ value.register.int64_1 = (long)Math.Sqrt(value.register.int64_1);
return value;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- value.register.single_0 = (Single)Math.Sqrt(value.register.single_0);
- value.register.single_1 = (Single)Math.Sqrt(value.register.single_1);
- value.register.single_2 = (Single)Math.Sqrt(value.register.single_2);
- value.register.single_3 = (Single)Math.Sqrt(value.register.single_3);
+ value.register.single_0 = (float)Math.Sqrt(value.register.single_0);
+ value.register.single_1 = (float)Math.Sqrt(value.register.single_1);
+ value.register.single_2 = (float)Math.Sqrt(value.register.single_2);
+ value.register.single_3 = (float)Math.Sqrt(value.register.single_3);
return value;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- value.register.double_0 = (Double)Math.Sqrt(value.register.double_0);
- value.register.double_1 = (Double)Math.Sqrt(value.register.double_1);
+ value.register.double_0 = (double)Math.Sqrt(value.register.double_0);
+ value.register.double_1 = (double)Math.Sqrt(value.register.double_1);
return value;
}
else
@@ -4504,45 +4539,45 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static bool ScalarEquals(T left, T right)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- return (Byte)(object)left == (Byte)(object)right;
+ return (byte)(object)left == (byte)(object)right;
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- return (SByte)(object)left == (SByte)(object)right;
+ return (sbyte)(object)left == (sbyte)(object)right;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- return (UInt16)(object)left == (UInt16)(object)right;
+ return (ushort)(object)left == (ushort)(object)right;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- return (Int16)(object)left == (Int16)(object)right;
+ return (short)(object)left == (short)(object)right;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- return (UInt32)(object)left == (UInt32)(object)right;
+ return (uint)(object)left == (uint)(object)right;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- return (Int32)(object)left == (Int32)(object)right;
+ return (int)(object)left == (int)(object)right;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- return (UInt64)(object)left == (UInt64)(object)right;
+ return (ulong)(object)left == (ulong)(object)right;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- return (Int64)(object)left == (Int64)(object)right;
+ return (long)(object)left == (long)(object)right;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- return (Single)(object)left == (Single)(object)right;
+ return (float)(object)left == (float)(object)right;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- return (Double)(object)left == (Double)(object)right;
+ return (double)(object)left == (double)(object)right;
}
else
{
@@ -4553,45 +4588,45 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static bool ScalarLessThan(T left, T right)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- return (Byte)(object)left < (Byte)(object)right;
+ return (byte)(object)left < (byte)(object)right;
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- return (SByte)(object)left < (SByte)(object)right;
+ return (sbyte)(object)left < (sbyte)(object)right;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- return (UInt16)(object)left < (UInt16)(object)right;
+ return (ushort)(object)left < (ushort)(object)right;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- return (Int16)(object)left < (Int16)(object)right;
+ return (short)(object)left < (short)(object)right;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- return (UInt32)(object)left < (UInt32)(object)right;
+ return (uint)(object)left < (uint)(object)right;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- return (Int32)(object)left < (Int32)(object)right;
+ return (int)(object)left < (int)(object)right;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- return (UInt64)(object)left < (UInt64)(object)right;
+ return (ulong)(object)left < (ulong)(object)right;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- return (Int64)(object)left < (Int64)(object)right;
+ return (long)(object)left < (long)(object)right;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- return (Single)(object)left < (Single)(object)right;
+ return (float)(object)left < (float)(object)right;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- return (Double)(object)left < (Double)(object)right;
+ return (double)(object)left < (double)(object)right;
}
else
{
@@ -4602,45 +4637,45 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static bool ScalarGreaterThan(T left, T right)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- return (Byte)(object)left > (Byte)(object)right;
+ return (byte)(object)left > (byte)(object)right;
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- return (SByte)(object)left > (SByte)(object)right;
+ return (sbyte)(object)left > (sbyte)(object)right;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- return (UInt16)(object)left > (UInt16)(object)right;
+ return (ushort)(object)left > (ushort)(object)right;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- return (Int16)(object)left > (Int16)(object)right;
+ return (short)(object)left > (short)(object)right;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- return (UInt32)(object)left > (UInt32)(object)right;
+ return (uint)(object)left > (uint)(object)right;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- return (Int32)(object)left > (Int32)(object)right;
+ return (int)(object)left > (int)(object)right;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- return (UInt64)(object)left > (UInt64)(object)right;
+ return (ulong)(object)left > (ulong)(object)right;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- return (Int64)(object)left > (Int64)(object)right;
+ return (long)(object)left > (long)(object)right;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- return (Single)(object)left > (Single)(object)right;
+ return (float)(object)left > (float)(object)right;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- return (Double)(object)left > (Double)(object)right;
+ return (double)(object)left > (double)(object)right;
}
else
{
@@ -4651,45 +4686,45 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T ScalarAdd(T left, T right)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- return (T)(object)unchecked((Byte)((Byte)(object)left + (Byte)(object)right));
+ return (T)(object)unchecked((byte)((byte)(object)left + (byte)(object)right));
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- return (T)(object)unchecked((SByte)((SByte)(object)left + (SByte)(object)right));
+ return (T)(object)unchecked((sbyte)((sbyte)(object)left + (sbyte)(object)right));
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- return (T)(object)unchecked((UInt16)((UInt16)(object)left + (UInt16)(object)right));
+ return (T)(object)unchecked((ushort)((ushort)(object)left + (ushort)(object)right));
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- return (T)(object)unchecked((Int16)((Int16)(object)left + (Int16)(object)right));
+ return (T)(object)unchecked((short)((short)(object)left + (short)(object)right));
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- return (T)(object)unchecked((UInt32)((UInt32)(object)left + (UInt32)(object)right));
+ return (T)(object)unchecked((uint)((uint)(object)left + (uint)(object)right));
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- return (T)(object)unchecked((Int32)((Int32)(object)left + (Int32)(object)right));
+ return (T)(object)unchecked((int)((int)(object)left + (int)(object)right));
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- return (T)(object)unchecked((UInt64)((UInt64)(object)left + (UInt64)(object)right));
+ return (T)(object)unchecked((ulong)((ulong)(object)left + (ulong)(object)right));
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- return (T)(object)unchecked((Int64)((Int64)(object)left + (Int64)(object)right));
+ return (T)(object)unchecked((long)((long)(object)left + (long)(object)right));
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- return (T)(object)unchecked((Single)((Single)(object)left + (Single)(object)right));
+ return (T)(object)unchecked((float)((float)(object)left + (float)(object)right));
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- return (T)(object)unchecked((Double)((Double)(object)left + (Double)(object)right));
+ return (T)(object)unchecked((double)((double)(object)left + (double)(object)right));
}
else
{
@@ -4700,45 +4735,45 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T ScalarSubtract(T left, T right)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- return (T)(object)(Byte)((Byte)(object)left - (Byte)(object)right);
+ return (T)(object)(byte)((byte)(object)left - (byte)(object)right);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- return (T)(object)(SByte)((SByte)(object)left - (SByte)(object)right);
+ return (T)(object)(sbyte)((sbyte)(object)left - (sbyte)(object)right);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- return (T)(object)(UInt16)((UInt16)(object)left - (UInt16)(object)right);
+ return (T)(object)(ushort)((ushort)(object)left - (ushort)(object)right);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- return (T)(object)(Int16)((Int16)(object)left - (Int16)(object)right);
+ return (T)(object)(short)((short)(object)left - (short)(object)right);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- return (T)(object)(UInt32)((UInt32)(object)left - (UInt32)(object)right);
+ return (T)(object)(uint)((uint)(object)left - (uint)(object)right);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- return (T)(object)(Int32)((Int32)(object)left - (Int32)(object)right);
+ return (T)(object)(int)((int)(object)left - (int)(object)right);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- return (T)(object)(UInt64)((UInt64)(object)left - (UInt64)(object)right);
+ return (T)(object)(ulong)((ulong)(object)left - (ulong)(object)right);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- return (T)(object)(Int64)((Int64)(object)left - (Int64)(object)right);
+ return (T)(object)(long)((long)(object)left - (long)(object)right);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- return (T)(object)(Single)((Single)(object)left - (Single)(object)right);
+ return (T)(object)(float)((float)(object)left - (float)(object)right);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- return (T)(object)(Double)((Double)(object)left - (Double)(object)right);
+ return (T)(object)(double)((double)(object)left - (double)(object)right);
}
else
{
@@ -4749,45 +4784,45 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T ScalarMultiply(T left, T right)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- return (T)(object)unchecked((Byte)((Byte)(object)left * (Byte)(object)right));
+ return (T)(object)unchecked((byte)((byte)(object)left * (byte)(object)right));
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- return (T)(object)unchecked((SByte)((SByte)(object)left * (SByte)(object)right));
+ return (T)(object)unchecked((sbyte)((sbyte)(object)left * (sbyte)(object)right));
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- return (T)(object)unchecked((UInt16)((UInt16)(object)left * (UInt16)(object)right));
+ return (T)(object)unchecked((ushort)((ushort)(object)left * (ushort)(object)right));
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- return (T)(object)unchecked((Int16)((Int16)(object)left * (Int16)(object)right));
+ return (T)(object)unchecked((short)((short)(object)left * (short)(object)right));
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- return (T)(object)unchecked((UInt32)((UInt32)(object)left * (UInt32)(object)right));
+ return (T)(object)unchecked((uint)((uint)(object)left * (uint)(object)right));
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- return (T)(object)unchecked((Int32)((Int32)(object)left * (Int32)(object)right));
+ return (T)(object)unchecked((int)((int)(object)left * (int)(object)right));
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- return (T)(object)unchecked((UInt64)((UInt64)(object)left * (UInt64)(object)right));
+ return (T)(object)unchecked((ulong)((ulong)(object)left * (ulong)(object)right));
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- return (T)(object)unchecked((Int64)((Int64)(object)left * (Int64)(object)right));
+ return (T)(object)unchecked((long)((long)(object)left * (long)(object)right));
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- return (T)(object)unchecked((Single)((Single)(object)left * (Single)(object)right));
+ return (T)(object)unchecked((float)((float)(object)left * (float)(object)right));
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- return (T)(object)unchecked((Double)((Double)(object)left * (Double)(object)right));
+ return (T)(object)unchecked((double)((double)(object)left * (double)(object)right));
}
else
{
@@ -4798,45 +4833,45 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T ScalarDivide(T left, T right)
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- return (T)(object)(Byte)((Byte)(object)left / (Byte)(object)right);
+ return (T)(object)(byte)((byte)(object)left / (byte)(object)right);
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- return (T)(object)(SByte)((SByte)(object)left / (SByte)(object)right);
+ return (T)(object)(sbyte)((sbyte)(object)left / (sbyte)(object)right);
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- return (T)(object)(UInt16)((UInt16)(object)left / (UInt16)(object)right);
+ return (T)(object)(ushort)((ushort)(object)left / (ushort)(object)right);
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- return (T)(object)(Int16)((Int16)(object)left / (Int16)(object)right);
+ return (T)(object)(short)((short)(object)left / (short)(object)right);
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- return (T)(object)(UInt32)((UInt32)(object)left / (UInt32)(object)right);
+ return (T)(object)(uint)((uint)(object)left / (uint)(object)right);
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- return (T)(object)(Int32)((Int32)(object)left / (Int32)(object)right);
+ return (T)(object)(int)((int)(object)left / (int)(object)right);
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- return (T)(object)(UInt64)((UInt64)(object)left / (UInt64)(object)right);
+ return (T)(object)(ulong)((ulong)(object)left / (ulong)(object)right);
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- return (T)(object)(Int64)((Int64)(object)left / (Int64)(object)right);
+ return (T)(object)(long)((long)(object)left / (long)(object)right);
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- return (T)(object)(Single)((Single)(object)left / (Single)(object)right);
+ return (T)(object)(float)((float)(object)left / (float)(object)right);
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- return (T)(object)(Double)((Double)(object)left / (Double)(object)right);
+ return (T)(object)(double)((double)(object)left / (double)(object)right);
}
else
{
@@ -4847,54 +4882,54 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T GetOneValue()
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
- Byte value = 1;
+ byte value = 1;
return (T)(object)value;
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
- SByte value = 1;
+ sbyte value = 1;
return (T)(object)value;
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
- UInt16 value = 1;
+ ushort value = 1;
return (T)(object)value;
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
- Int16 value = 1;
+ short value = 1;
return (T)(object)value;
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
- UInt32 value = 1;
+ uint value = 1;
return (T)(object)value;
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
- Int32 value = 1;
+ int value = 1;
return (T)(object)value;
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
- UInt64 value = 1;
+ ulong value = 1;
return (T)(object)value;
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
- Int64 value = 1;
+ long value = 1;
return (T)(object)value;
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
- Single value = 1;
+ float value = 1;
return (T)(object)value;
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
- Double value = 1;
+ double value = 1;
return (T)(object)value;
}
else
@@ -4906,43 +4941,43 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T GetAllBitsSetValue()
{
- if (typeof(T) == typeof(Byte))
+ if (typeof(T) == typeof(byte))
{
return (T)(object)ConstantHelper.GetByteWithAllBitsSet();
}
- else if (typeof(T) == typeof(SByte))
+ else if (typeof(T) == typeof(sbyte))
{
return (T)(object)ConstantHelper.GetSByteWithAllBitsSet();
}
- else if (typeof(T) == typeof(UInt16))
+ else if (typeof(T) == typeof(ushort))
{
return (T)(object)ConstantHelper.GetUInt16WithAllBitsSet();
}
- else if (typeof(T) == typeof(Int16))
+ else if (typeof(T) == typeof(short))
{
return (T)(object)ConstantHelper.GetInt16WithAllBitsSet();
}
- else if (typeof(T) == typeof(UInt32))
+ else if (typeof(T) == typeof(uint))
{
return (T)(object)ConstantHelper.GetUInt32WithAllBitsSet();
}
- else if (typeof(T) == typeof(Int32))
+ else if (typeof(T) == typeof(int))
{
return (T)(object)ConstantHelper.GetInt32WithAllBitsSet();
}
- else if (typeof(T) == typeof(UInt64))
+ else if (typeof(T) == typeof(ulong))
{
return (T)(object)ConstantHelper.GetUInt64WithAllBitsSet();
}
- else if (typeof(T) == typeof(Int64))
+ else if (typeof(T) == typeof(long))
{
return (T)(object)ConstantHelper.GetInt64WithAllBitsSet();
}
- else if (typeof(T) == typeof(Single))
+ else if (typeof(T) == typeof(float))
{
return (T)(object)ConstantHelper.GetSingleWithAllBitsSet();
}
- else if (typeof(T) == typeof(Double))
+ else if (typeof(T) == typeof(double))
{
return (T)(object)ConstantHelper.GetDoubleWithAllBitsSet();
}
@@ -4966,22 +5001,22 @@ namespace System.Numerics
/// </summary>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe void Widen(Vector<Byte> source, out Vector<UInt16> low, out Vector<UInt16> high)
+ public static unsafe void Widen(Vector<byte> source, out Vector<ushort> low, out Vector<ushort> high)
{
- int elements = Vector<Byte>.Count;
- UInt16* lowPtr = stackalloc UInt16[elements / 2];
+ int elements = Vector<byte>.Count;
+ ushort* lowPtr = stackalloc ushort[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- lowPtr[i] = (UInt16)source[i];
+ lowPtr[i] = (ushort)source[i];
}
- UInt16* highPtr = stackalloc UInt16[elements / 2];
+ ushort* highPtr = stackalloc ushort[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- highPtr[i] = (UInt16)source[i + (elements / 2)];
+ highPtr[i] = (ushort)source[i + (elements / 2)];
}
- low = new Vector<UInt16>(lowPtr);
- high = new Vector<UInt16>(highPtr);
+ low = new Vector<ushort>(lowPtr);
+ high = new Vector<ushort>(highPtr);
}
/// <summary>
@@ -4992,22 +5027,22 @@ namespace System.Numerics
/// </summary>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe void Widen(Vector<UInt16> source, out Vector<UInt32> low, out Vector<UInt32> high)
+ public static unsafe void Widen(Vector<ushort> source, out Vector<uint> low, out Vector<uint> high)
{
- int elements = Vector<UInt16>.Count;
- UInt32* lowPtr = stackalloc UInt32[elements / 2];
+ int elements = Vector<ushort>.Count;
+ uint* lowPtr = stackalloc uint[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- lowPtr[i] = (UInt32)source[i];
+ lowPtr[i] = (uint)source[i];
}
- UInt32* highPtr = stackalloc UInt32[elements / 2];
+ uint* highPtr = stackalloc uint[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- highPtr[i] = (UInt32)source[i + (elements / 2)];
+ highPtr[i] = (uint)source[i + (elements / 2)];
}
- low = new Vector<UInt32>(lowPtr);
- high = new Vector<UInt32>(highPtr);
+ low = new Vector<uint>(lowPtr);
+ high = new Vector<uint>(highPtr);
}
/// <summary>
@@ -5018,22 +5053,22 @@ namespace System.Numerics
/// </summary>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe void Widen(Vector<UInt32> source, out Vector<UInt64> low, out Vector<UInt64> high)
+ public static unsafe void Widen(Vector<uint> source, out Vector<ulong> low, out Vector<ulong> high)
{
- int elements = Vector<UInt32>.Count;
- UInt64* lowPtr = stackalloc UInt64[elements / 2];
+ int elements = Vector<uint>.Count;
+ ulong* lowPtr = stackalloc ulong[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- lowPtr[i] = (UInt64)source[i];
+ lowPtr[i] = (ulong)source[i];
}
- UInt64* highPtr = stackalloc UInt64[elements / 2];
+ ulong* highPtr = stackalloc ulong[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- highPtr[i] = (UInt64)source[i + (elements / 2)];
+ highPtr[i] = (ulong)source[i + (elements / 2)];
}
- low = new Vector<UInt64>(lowPtr);
- high = new Vector<UInt64>(highPtr);
+ low = new Vector<ulong>(lowPtr);
+ high = new Vector<ulong>(highPtr);
}
/// <summary>
@@ -5044,22 +5079,22 @@ namespace System.Numerics
/// </summary>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe void Widen(Vector<SByte> source, out Vector<Int16> low, out Vector<Int16> high)
+ public static unsafe void Widen(Vector<sbyte> source, out Vector<short> low, out Vector<short> high)
{
- int elements = Vector<SByte>.Count;
- Int16* lowPtr = stackalloc Int16[elements / 2];
+ int elements = Vector<sbyte>.Count;
+ short* lowPtr = stackalloc short[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- lowPtr[i] = (Int16)source[i];
+ lowPtr[i] = (short)source[i];
}
- Int16* highPtr = stackalloc Int16[elements / 2];
+ short* highPtr = stackalloc short[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- highPtr[i] = (Int16)source[i + (elements / 2)];
+ highPtr[i] = (short)source[i + (elements / 2)];
}
- low = new Vector<Int16>(lowPtr);
- high = new Vector<Int16>(highPtr);
+ low = new Vector<short>(lowPtr);
+ high = new Vector<short>(highPtr);
}
/// <summary>
@@ -5069,22 +5104,22 @@ namespace System.Numerics
/// <param name="high">The second output vector, whose elements will contain the widened elements from higher indices in the source vector.</param>
/// </summary>
[Intrinsic]
- public static unsafe void Widen(Vector<Int16> source, out Vector<Int32> low, out Vector<Int32> high)
+ public static unsafe void Widen(Vector<short> source, out Vector<int> low, out Vector<int> high)
{
- int elements = Vector<Int16>.Count;
- Int32* lowPtr = stackalloc Int32[elements / 2];
+ int elements = Vector<short>.Count;
+ int* lowPtr = stackalloc int[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- lowPtr[i] = (Int32)source[i];
+ lowPtr[i] = (int)source[i];
}
- Int32* highPtr = stackalloc Int32[elements / 2];
+ int* highPtr = stackalloc int[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- highPtr[i] = (Int32)source[i + (elements / 2)];
+ highPtr[i] = (int)source[i + (elements / 2)];
}
- low = new Vector<Int32>(lowPtr);
- high = new Vector<Int32>(highPtr);
+ low = new Vector<int>(lowPtr);
+ high = new Vector<int>(highPtr);
}
/// <summary>
@@ -5094,22 +5129,22 @@ namespace System.Numerics
/// <param name="high">The second output vector, whose elements will contain the widened elements from higher indices in the source vector.</param>
/// </summary>
[Intrinsic]
- public static unsafe void Widen(Vector<Int32> source, out Vector<Int64> low, out Vector<Int64> high)
+ public static unsafe void Widen(Vector<int> source, out Vector<long> low, out Vector<long> high)
{
- int elements = Vector<Int32>.Count;
- Int64* lowPtr = stackalloc Int64[elements / 2];
+ int elements = Vector<int>.Count;
+ long* lowPtr = stackalloc long[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- lowPtr[i] = (Int64)source[i];
+ lowPtr[i] = (long)source[i];
}
- Int64* highPtr = stackalloc Int64[elements / 2];
+ long* highPtr = stackalloc long[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- highPtr[i] = (Int64)source[i + (elements / 2)];
+ highPtr[i] = (long)source[i + (elements / 2)];
}
- low = new Vector<Int64>(lowPtr);
- high = new Vector<Int64>(highPtr);
+ low = new Vector<long>(lowPtr);
+ high = new Vector<long>(highPtr);
}
/// <summary>
@@ -5119,22 +5154,22 @@ namespace System.Numerics
/// <param name="high">The second output vector, whose elements will contain the widened elements from higher indices in the source vector.</param>
/// </summary>
[Intrinsic]
- public static unsafe void Widen(Vector<Single> source, out Vector<Double> low, out Vector<Double> high)
+ public static unsafe void Widen(Vector<float> source, out Vector<double> low, out Vector<double> high)
{
- int elements = Vector<Single>.Count;
- Double* lowPtr = stackalloc Double[elements / 2];
+ int elements = Vector<float>.Count;
+ double* lowPtr = stackalloc double[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- lowPtr[i] = (Double)source[i];
+ lowPtr[i] = (double)source[i];
}
- Double* highPtr = stackalloc Double[elements / 2];
+ double* highPtr = stackalloc double[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- highPtr[i] = (Double)source[i + (elements / 2)];
+ highPtr[i] = (double)source[i + (elements / 2)];
}
- low = new Vector<Double>(lowPtr);
- high = new Vector<Double>(highPtr);
+ low = new Vector<double>(lowPtr);
+ high = new Vector<double>(highPtr);
}
/// <summary>
@@ -5145,23 +5180,23 @@ namespace System.Numerics
/// </summary>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe Vector<Byte> Narrow(Vector<UInt16> low, Vector<UInt16> high)
+ public static unsafe Vector<byte> Narrow(Vector<ushort> low, Vector<ushort> high)
{
- unchecked
- {
- int elements = Vector<Byte>.Count;
- Byte* retPtr = stackalloc Byte[elements];
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i] = (Byte)low[i];
- }
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i + (elements / 2)] = (Byte)high[i];
- }
+ unchecked
+ {
+ int elements = Vector<byte>.Count;
+ byte* retPtr = stackalloc byte[elements];
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i] = (byte)low[i];
+ }
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i + (elements / 2)] = (byte)high[i];
+ }
- return new Vector<Byte>(retPtr);
- }
+ return new Vector<byte>(retPtr);
+ }
}
/// <summary>
@@ -5172,23 +5207,23 @@ namespace System.Numerics
/// </summary>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe Vector<UInt16> Narrow(Vector<UInt32> low, Vector<UInt32> high)
+ public static unsafe Vector<ushort> Narrow(Vector<uint> low, Vector<uint> high)
{
- unchecked
- {
- int elements = Vector<UInt16>.Count;
- UInt16* retPtr = stackalloc UInt16[elements];
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i] = (UInt16)low[i];
- }
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i + (elements / 2)] = (UInt16)high[i];
- }
+ unchecked
+ {
+ int elements = Vector<ushort>.Count;
+ ushort* retPtr = stackalloc ushort[elements];
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i] = (ushort)low[i];
+ }
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i + (elements / 2)] = (ushort)high[i];
+ }
- return new Vector<UInt16>(retPtr);
- }
+ return new Vector<ushort>(retPtr);
+ }
}
/// <summary>
@@ -5199,23 +5234,23 @@ namespace System.Numerics
/// </summary>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe Vector<UInt32> Narrow(Vector<UInt64> low, Vector<UInt64> high)
+ public static unsafe Vector<uint> Narrow(Vector<ulong> low, Vector<ulong> high)
{
- unchecked
- {
- int elements = Vector<UInt32>.Count;
- UInt32* retPtr = stackalloc UInt32[elements];
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i] = (UInt32)low[i];
- }
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i + (elements / 2)] = (UInt32)high[i];
- }
+ unchecked
+ {
+ int elements = Vector<uint>.Count;
+ uint* retPtr = stackalloc uint[elements];
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i] = (uint)low[i];
+ }
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i + (elements / 2)] = (uint)high[i];
+ }
- return new Vector<UInt32>(retPtr);
- }
+ return new Vector<uint>(retPtr);
+ }
}
/// <summary>
@@ -5226,23 +5261,23 @@ namespace System.Numerics
/// </summary>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe Vector<SByte> Narrow(Vector<Int16> low, Vector<Int16> high)
+ public static unsafe Vector<sbyte> Narrow(Vector<short> low, Vector<short> high)
{
- unchecked
- {
- int elements = Vector<SByte>.Count;
- SByte* retPtr = stackalloc SByte[elements];
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i] = (SByte)low[i];
- }
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i + (elements / 2)] = (SByte)high[i];
- }
+ unchecked
+ {
+ int elements = Vector<sbyte>.Count;
+ sbyte* retPtr = stackalloc sbyte[elements];
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i] = (sbyte)low[i];
+ }
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i + (elements / 2)] = (sbyte)high[i];
+ }
- return new Vector<SByte>(retPtr);
- }
+ return new Vector<sbyte>(retPtr);
+ }
}
/// <summary>
@@ -5252,23 +5287,23 @@ namespace System.Numerics
/// <returns>A Vector{Int16} containing elements narrowed from the source vectors.</returns>
/// </summary>
[Intrinsic]
- public static unsafe Vector<Int16> Narrow(Vector<Int32> low, Vector<Int32> high)
+ public static unsafe Vector<short> Narrow(Vector<int> low, Vector<int> high)
{
- unchecked
- {
- int elements = Vector<Int16>.Count;
- Int16* retPtr = stackalloc Int16[elements];
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i] = (Int16)low[i];
- }
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i + (elements / 2)] = (Int16)high[i];
- }
+ unchecked
+ {
+ int elements = Vector<short>.Count;
+ short* retPtr = stackalloc short[elements];
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i] = (short)low[i];
+ }
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i + (elements / 2)] = (short)high[i];
+ }
- return new Vector<Int16>(retPtr);
- }
+ return new Vector<short>(retPtr);
+ }
}
/// <summary>
@@ -5278,23 +5313,23 @@ namespace System.Numerics
/// <returns>A Vector{Int32} containing elements narrowed from the source vectors.</returns>
/// </summary>
[Intrinsic]
- public static unsafe Vector<Int32> Narrow(Vector<Int64> low, Vector<Int64> high)
+ public static unsafe Vector<int> Narrow(Vector<long> low, Vector<long> high)
{
- unchecked
- {
- int elements = Vector<Int32>.Count;
- Int32* retPtr = stackalloc Int32[elements];
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i] = (Int32)low[i];
- }
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i + (elements / 2)] = (Int32)high[i];
- }
+ unchecked
+ {
+ int elements = Vector<int>.Count;
+ int* retPtr = stackalloc int[elements];
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i] = (int)low[i];
+ }
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i + (elements / 2)] = (int)high[i];
+ }
- return new Vector<Int32>(retPtr);
- }
+ return new Vector<int>(retPtr);
+ }
}
/// <summary>
@@ -5304,23 +5339,23 @@ namespace System.Numerics
/// <returns>A Vector{Single} containing elements narrowed from the source vectors.</returns>
/// </summary>
[Intrinsic]
- public static unsafe Vector<Single> Narrow(Vector<Double> low, Vector<Double> high)
+ public static unsafe Vector<float> Narrow(Vector<double> low, Vector<double> high)
{
- unchecked
- {
- int elements = Vector<Single>.Count;
- Single* retPtr = stackalloc Single[elements];
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i] = (Single)low[i];
- }
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i + (elements / 2)] = (Single)high[i];
- }
+ unchecked
+ {
+ int elements = Vector<float>.Count;
+ float* retPtr = stackalloc float[elements];
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i] = (float)low[i];
+ }
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i + (elements / 2)] = (float)high[i];
+ }
- return new Vector<Single>(retPtr);
- }
+ return new Vector<float>(retPtr);
+ }
}
#endregion Widen/Narrow
@@ -5332,19 +5367,19 @@ namespace System.Numerics
/// <param name="value">The source vector.</param>
/// <returns>The converted vector.</returns>
[Intrinsic]
- public static unsafe Vector<Single> ConvertToSingle(Vector<Int32> value)
+ public static unsafe Vector<float> ConvertToSingle(Vector<int> value)
{
- unchecked
- {
- int elements = Vector<Single>.Count;
- Single* retPtr = stackalloc Single[elements];
- for (int i = 0; i < elements; i++)
- {
- retPtr[i] = (Single)value[i];
- }
+ unchecked
+ {
+ int elements = Vector<float>.Count;
+ float* retPtr = stackalloc float[elements];
+ for (int i = 0; i < elements; i++)
+ {
+ retPtr[i] = (float)value[i];
+ }
- return new Vector<Single>(retPtr);
- }
+ return new Vector<float>(retPtr);
+ }
}
/// <summary>
@@ -5354,19 +5389,19 @@ namespace System.Numerics
/// <returns>The converted vector.</returns>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe Vector<Single> ConvertToSingle(Vector<UInt32> value)
+ public static unsafe Vector<float> ConvertToSingle(Vector<uint> value)
{
- unchecked
- {
- int elements = Vector<Single>.Count;
- Single* retPtr = stackalloc Single[elements];
- for (int i = 0; i < elements; i++)
- {
- retPtr[i] = (Single)value[i];
- }
+ unchecked
+ {
+ int elements = Vector<float>.Count;
+ float* retPtr = stackalloc float[elements];
+ for (int i = 0; i < elements; i++)
+ {
+ retPtr[i] = (float)value[i];
+ }
- return new Vector<Single>(retPtr);
- }
+ return new Vector<float>(retPtr);
+ }
}
/// <summary>
@@ -5375,19 +5410,19 @@ namespace System.Numerics
/// <param name="value">The source vector.</param>
/// <returns>The converted vector.</returns>
[Intrinsic]
- public static unsafe Vector<Double> ConvertToDouble(Vector<Int64> value)
+ public static unsafe Vector<double> ConvertToDouble(Vector<long> value)
{
- unchecked
- {
- int elements = Vector<Double>.Count;
- Double* retPtr = stackalloc Double[elements];
- for (int i = 0; i < elements; i++)
- {
- retPtr[i] = (Double)value[i];
- }
+ unchecked
+ {
+ int elements = Vector<double>.Count;
+ double* retPtr = stackalloc double[elements];
+ for (int i = 0; i < elements; i++)
+ {
+ retPtr[i] = (double)value[i];
+ }
- return new Vector<Double>(retPtr);
- }
+ return new Vector<double>(retPtr);
+ }
}
/// <summary>
@@ -5397,19 +5432,19 @@ namespace System.Numerics
/// <returns>The converted vector.</returns>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe Vector<Double> ConvertToDouble(Vector<UInt64> value)
+ public static unsafe Vector<double> ConvertToDouble(Vector<ulong> value)
{
- unchecked
- {
- int elements = Vector<Double>.Count;
- Double* retPtr = stackalloc Double[elements];
- for (int i = 0; i < elements; i++)
- {
- retPtr[i] = (Double)value[i];
- }
+ unchecked
+ {
+ int elements = Vector<double>.Count;
+ double* retPtr = stackalloc double[elements];
+ for (int i = 0; i < elements; i++)
+ {
+ retPtr[i] = (double)value[i];
+ }
- return new Vector<Double>(retPtr);
- }
+ return new Vector<double>(retPtr);
+ }
}
/// <summary>
@@ -5418,19 +5453,19 @@ namespace System.Numerics
/// <param name="value">The source vector.</param>
/// <returns>The converted vector.</returns>
[Intrinsic]
- public static unsafe Vector<Int32> ConvertToInt32(Vector<Single> value)
+ public static unsafe Vector<int> ConvertToInt32(Vector<float> value)
{
- unchecked
- {
- int elements = Vector<Int32>.Count;
- Int32* retPtr = stackalloc Int32[elements];
- for (int i = 0; i < elements; i++)
- {
- retPtr[i] = (Int32)value[i];
- }
+ unchecked
+ {
+ int elements = Vector<int>.Count;
+ int* retPtr = stackalloc int[elements];
+ for (int i = 0; i < elements; i++)
+ {
+ retPtr[i] = (int)value[i];
+ }
- return new Vector<Int32>(retPtr);
- }
+ return new Vector<int>(retPtr);
+ }
}
/// <summary>
@@ -5440,19 +5475,19 @@ namespace System.Numerics
/// <returns>The converted vector.</returns>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe Vector<UInt32> ConvertToUInt32(Vector<Single> value)
+ public static unsafe Vector<uint> ConvertToUInt32(Vector<float> value)
{
- unchecked
- {
- int elements = Vector<UInt32>.Count;
- UInt32* retPtr = stackalloc UInt32[elements];
- for (int i = 0; i < elements; i++)
- {
- retPtr[i] = (UInt32)value[i];
- }
+ unchecked
+ {
+ int elements = Vector<uint>.Count;
+ uint* retPtr = stackalloc uint[elements];
+ for (int i = 0; i < elements; i++)
+ {
+ retPtr[i] = (uint)value[i];
+ }
- return new Vector<UInt32>(retPtr);
- }
+ return new Vector<uint>(retPtr);
+ }
}
/// <summary>
@@ -5461,19 +5496,19 @@ namespace System.Numerics
/// <param name="value">The source vector.</param>
/// <returns>The converted vector.</returns>
[Intrinsic]
- public static unsafe Vector<Int64> ConvertToInt64(Vector<Double> value)
+ public static unsafe Vector<long> ConvertToInt64(Vector<double> value)
{
- unchecked
- {
- int elements = Vector<Int64>.Count;
- Int64* retPtr = stackalloc Int64[elements];
- for (int i = 0; i < elements; i++)
- {
- retPtr[i] = (Int64)value[i];
- }
+ unchecked
+ {
+ int elements = Vector<long>.Count;
+ long* retPtr = stackalloc long[elements];
+ for (int i = 0; i < elements; i++)
+ {
+ retPtr[i] = (long)value[i];
+ }
- return new Vector<Int64>(retPtr);
- }
+ return new Vector<long>(retPtr);
+ }
}
/// <summary>
@@ -5483,19 +5518,19 @@ namespace System.Numerics
/// <returns>The converted vector.</returns>
[CLSCompliant(false)]
[Intrinsic]
- public static unsafe Vector<UInt64> ConvertToUInt64(Vector<Double> value)
+ public static unsafe Vector<ulong> ConvertToUInt64(Vector<double> value)
{
- unchecked
- {
- int elements = Vector<UInt64>.Count;
- UInt64* retPtr = stackalloc UInt64[elements];
- for (int i = 0; i < elements; i++)
- {
- retPtr[i] = (UInt64)value[i];
- }
+ unchecked
+ {
+ int elements = Vector<ulong>.Count;
+ ulong* retPtr = stackalloc ulong[elements];
+ for (int i = 0; i < elements; i++)
+ {
+ retPtr[i] = (ulong)value[i];
+ }
- return new Vector<UInt64>(retPtr);
- }
+ return new Vector<ulong>(retPtr);
+ }
}
#endregion Same-Size Conversion
diff --git a/src/System.Private.CoreLib/shared/System/Numerics/Vector.tt b/src/System.Private.CoreLib/shared/System/Numerics/Vector.tt
index 275f47350..9eda34d04 100644
--- a/src/System.Private.CoreLib/shared/System/Numerics/Vector.tt
+++ b/src/System.Private.CoreLib/shared/System/Numerics/Vector.tt
@@ -7,9 +7,13 @@
<#@ import namespace="System.Runtime.InteropServices" #>
<#@ include file="GenerationConfig.ttinclude" #><# GenerateCopyrightHeader(); #>
+#if netcoreapp
+using Internal.Runtime.CompilerServices;
+#endif
using System.Globalization;
using System.Numerics.Hashing;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using System.Text;
namespace System.Numerics
@@ -17,8 +21,8 @@ namespace System.Numerics
/* Note: The following patterns are used throughout the code here and are described here
*
* PATTERN:
- * if (typeof(T) == typeof(Int32)) { ... }
- * else if (typeof(T) == typeof(Single)) { ... }
+ * if (typeof(T) == typeof(int)) { ... }
+ * else if (typeof(T) == typeof(float)) { ... }
* EXPLANATION:
* At runtime, each instantiation of Vector<T> will be type-specific, and each of these typeof blocks will be eliminated,
* as typeof(T) is a (JIT) compile-time constant for each instantiation. This design was chosen to eliminate any overhead from
@@ -101,7 +105,7 @@ namespace System.Numerics
internal byte _byte;
}
- // Calculates the size of this struct in bytes, by computing the offset of a field in a structure
+ // Calculates the size of this struct in bytes, by computing the offset of a field in a structure
private static unsafe int InitializeCount()
{
VectorSizeHelper vsh;
@@ -110,15 +114,16 @@ namespace System.Numerics
int vectorSizeInBytes = (int)(byteBase - vectorBase);
int typeSizeInBytes = -1;
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- typeSizeInBytes = sizeof(<#=type.Name#>);
+ typeSizeInBytes = sizeof(<#=typeAliases[type]#>);
}
<#
- }
+ }
#>
else
{
@@ -139,41 +144,43 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
- fixed (<#=type.Name#>* basePtr = &this.<#=GetRegisterFieldName(type, 0)#>)
+ fixed (<#=typeAliases[type]#>* basePtr = &this.<#=GetRegisterFieldName(type, 0)#>)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (<#=type.Name#>)(object)value;
+ *(basePtr + g) = (<#=typeAliases[type]#>)(object)value;
}
}
}
<#
- }
+ }
#>
}
else
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < totalSize / Marshal.SizeOf(type); g++)
- {
+ for (int g = 0; g < totalSize / Marshal.SizeOf(type); g++)
+ {
#>
- <#=GetRegisterFieldName(type, g)#> = (<#=type.Name#>)(object)value;
+ <#=GetRegisterFieldName(type, g)#> = (<#=typeAliases[type]#>)(object)value;
<#
- }
+ }
#>
}
<#
- }
+ }
#>
}
}
@@ -198,49 +205,51 @@ namespace System.Numerics
}
if (index < 0 || (values.Length - index) < Count)
{
- throw new IndexOutOfRangeException();
+ throw new IndexOutOfRangeException(SR.Format(SR.Arg_InsufficientNumberOfElements, Vector<T>.Count, nameof(values)));
}
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
- fixed (<#=type.Name#>* basePtr = &this.<#=GetRegisterFieldName(type, 0)#>)
+ fixed (<#=typeAliases[type]#>* basePtr = &this.<#=GetRegisterFieldName(type, 0)#>)
{
for (int g = 0; g < Count; g++)
{
- *(basePtr + g) = (<#=type.Name#>)(object)values[g + index];
+ *(basePtr + g) = (<#=typeAliases[type]#>)(object)values[g + index];
}
}
}
<#
- }
+ }
#>
}
else
{
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
- fixed (<#=type.Name#>* basePtr = &this.<#=GetRegisterFieldName(type, 0)#>)
+ fixed (<#=typeAliases[type]#>* basePtr = &this.<#=GetRegisterFieldName(type, 0)#>)
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
- *(basePtr + <#=g#>) = (<#=type.Name#>)(object)values[<#=g#> + index];
+ *(basePtr + <#=g#>) = (<#=typeAliases[type]#>)(object)values[<#=g#> + index];
<#
- }
+ }
#>
}
}
<#
- }
+ }
#>
}
}
@@ -254,14 +263,15 @@ namespace System.Numerics
internal unsafe Vector(void* dataPointer, int offset)
: this()
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* castedPtr = (<#=type.Name#>*)dataPointer;
+ <#=typeAliases[type]#>* castedPtr = (<#=typeAliases[type]#>*)dataPointer;
castedPtr += offset;
- fixed (<#=type.Name#>* registerBase = &this.<#=GetRegisterFieldName(type, 0)#>)
+ fixed (<#=typeAliases[type]#>* registerBase = &this.<#=GetRegisterFieldName(type, 0)#>)
{
for (int g = 0; g < Count; g++)
{
@@ -270,7 +280,7 @@ namespace System.Numerics
}
}
<#
- }
+ }
#>
else
{
@@ -283,6 +293,28 @@ namespace System.Numerics
{
this.register = existingRegister;
}
+
+#if netcoreapp
+ /// <summary>
+ /// Constructs a vector from the given span. The span must contain at least Vector'T.Count elements.
+ /// </summary>
+ public Vector(Span<T> values)
+ : this()
+ {
+ <#=GenerateIfConditionAllTypes(supportedTypes)#>
+ {
+ if (values.Length < Count)
+ {
+ throw new IndexOutOfRangeException(SR.Format(SR.Arg_InsufficientNumberOfElements, Vector<T>.Count, nameof(values)));
+ }
+ this = Unsafe.ReadUnaligned<Vector<T>>(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference(values)));
+ }
+ else
+ {
+ throw new NotSupportedException(SR.Arg_TypeNotSupported);
+ }
+ }
+#endif
#endregion Constructors
#region Public Instance Methods
@@ -325,46 +357,48 @@ namespace System.Numerics
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>[] <#=type.Name.ToLowerInvariant()#>Array = (<#=type.Name#>[])(object)destination;
- fixed (<#=type.Name#>* destinationBase = <#=type.Name.ToLowerInvariant()#>Array)
+ <#=typeAliases[type]#>[] <#=type.Name.ToLowerInvariant()#>Array = (<#=typeAliases[type]#>[])(object)destination;
+ fixed (<#=typeAliases[type]#>* destinationBase = <#=type.Name.ToLowerInvariant()#>Array)
{
for (int g = 0; g < Count; g++)
{
- destinationBase[startIndex + g] = (<#=type.Name#>)(object)this[g];
+ destinationBase[startIndex + g] = (<#=typeAliases[type]#>)(object)this[g];
}
}
}
<#
- }
+ }
#>
}
else
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>[] <#=type.Name.ToLowerInvariant()#>Array = (<#=type.Name#>[])(object)destination;
- fixed (<#=type.Name#>* destinationBase = <#=type.Name.ToLowerInvariant()#>Array)
+ <#=typeAliases[type]#>[] <#=type.Name.ToLowerInvariant()#>Array = (<#=typeAliases[type]#>[])(object)destination;
+ fixed (<#=typeAliases[type]#>* destinationBase = <#=type.Name.ToLowerInvariant()#>Array)
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
destinationBase[startIndex + <#=g#>] = this.<#=GetRegisterFieldName(type, g)#>;
<#
- }
+ }
#>
}
}
<#
- }
+ }
#>
}
}
@@ -381,12 +415,13 @@ namespace System.Numerics
{
throw new IndexOutOfRangeException(SR.Format(SR.Arg_ArgumentOutOfRangeException, index));
}
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
- fixed (<#=type.Name#>* basePtr = &this.<#=GetRegisterFieldName(type, 0)#>)
+ fixed (<#=typeAliases[type]#>* basePtr = &this.<#=GetRegisterFieldName(type, 0)#>)
{
return (T)(object)*(basePtr + index);
}
@@ -437,36 +472,37 @@ namespace System.Numerics
}
else
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
return
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
<#
- if (g == 0)
- {
+ if (g == 0)
+ {
#>
this.<#=GetRegisterFieldName(type, g)#> == other.<#=GetRegisterFieldName(type, g)#>
<#
- }
- else
- {
+ }
+ else
+ {
#>
&& this.<#=GetRegisterFieldName(type, g)#> == other.<#=GetRegisterFieldName(type, g)#><#=(g == (GetNumFields(type, totalSize) -1)) ? ";" : ""#>
<#
- }
+ }
#>
<#
- }
+ }
#>
}
<#
- }
+ }
#>
else
{
@@ -485,19 +521,20 @@ namespace System.Numerics
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
for (int g = 0; g < Count; g++)
{
- hash = HashHelpers.Combine(hash, ((<#=type.Name#>)(object)this[g]).GetHashCode());
+ hash = HashHelpers.Combine(hash, ((<#=typeAliases[type]#>)(object)this[g]).GetHashCode());
}
return hash;
}
<#
- }
+ }
#>
else
{
@@ -506,23 +543,24 @@ namespace System.Numerics
}
else
{
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
hash = HashHelpers.Combine(hash, this.<#=GetRegisterFieldName(type, g)#>.GetHashCode());
<#
- }
+ }
#>
return hash;
}
<#
- }
+ }
#>
else
{
@@ -588,20 +626,21 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (<#=type.Name#>)(object)ScalarAdd(left[g], right[g]);
+ dataPtr[g] = (<#=typeAliases[type]#>)(object)ScalarAdd(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
<#
- }
+ }
#>
else
{
@@ -611,8 +650,9 @@ namespace System.Numerics
else
{
Vector<T> sum = new Vector<T>();
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
@@ -620,13 +660,13 @@ namespace System.Numerics
for (int g = 0; g < GetNumFields(type, totalSize); g++)
{
#>
- sum.<#= GetRegisterFieldName(type, g) #> = (<#=type.Name#>)(left.<#= GetRegisterFieldName(type, g) #> + right.<#= GetRegisterFieldName(type, g) #>);
+ sum.<#= GetRegisterFieldName(type, g) #> = (<#=typeAliases[type]#>)(left.<#= GetRegisterFieldName(type, g) #> + right.<#= GetRegisterFieldName(type, g) #>);
<#
}
#>
}
<#
- }
+ }
#>
return sum;
}
@@ -645,20 +685,21 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (<#=type.Name#>)(object)ScalarSubtract(left[g], right[g]);
+ dataPtr[g] = (<#=typeAliases[type]#>)(object)ScalarSubtract(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
<#
- }
+ }
#>
else
{
@@ -668,22 +709,23 @@ namespace System.Numerics
else
{
Vector<T> difference = new Vector<T>();
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
- difference.<#= GetRegisterFieldName(type, g) #> = (<#=type.Name#>)(left.<#= GetRegisterFieldName(type, g) #> - right.<#= GetRegisterFieldName(type, g) #>);
+ difference.<#= GetRegisterFieldName(type, g) #> = (<#=typeAliases[type]#>)(left.<#= GetRegisterFieldName(type, g) #> - right.<#= GetRegisterFieldName(type, g) #>);
<#
- }
+ }
#>
}
<#
- }
+ }
#>
return difference;
}
@@ -703,20 +745,21 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (<#=type.Name#>)(object)ScalarMultiply(left[g], right[g]);
+ dataPtr[g] = (<#=typeAliases[type]#>)(object)ScalarMultiply(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
<#
- }
+ }
#>
else
{
@@ -726,18 +769,19 @@ namespace System.Numerics
else
{
Vector<T> product = new Vector<T>();
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
- product.<#= GetRegisterFieldName(type, g) #> = (<#=type.Name#>)(left.<#= GetRegisterFieldName(type, g) #> * right.<#= GetRegisterFieldName(type, g) #>);
+ product.<#= GetRegisterFieldName(type, g) #> = (<#=typeAliases[type]#>)(left.<#= GetRegisterFieldName(type, g) #> * right.<#= GetRegisterFieldName(type, g) #>);
<#
- }
+ }
#>
}
<#
@@ -766,18 +810,19 @@ namespace System.Numerics
else
{
Vector<T> product = new Vector<T>();
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
- product.<#= GetRegisterFieldName(type, g) #> = (<#=type.Name#>)(value.<#= GetRegisterFieldName(type, g) #> * (<#=type.Name#>)(object)factor);
+ product.<#= GetRegisterFieldName(type, g) #> = (<#=typeAliases[type]#>)(value.<#= GetRegisterFieldName(type, g) #> * (<#=typeAliases[type]#>)(object)factor);
<#
- }
+ }
#>
}
<#
@@ -806,18 +851,19 @@ namespace System.Numerics
else
{
Vector<T> product = new Vector<T>();
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
- product.<#= GetRegisterFieldName(type, g) #> = (<#=type.Name#>)(value.<#= GetRegisterFieldName(type, g) #> * (<#=type.Name#>)(object)factor);
+ product.<#= GetRegisterFieldName(type, g) #> = (<#=typeAliases[type]#>)(value.<#= GetRegisterFieldName(type, g) #> * (<#=typeAliases[type]#>)(object)factor);
<#
- }
+ }
#>
}
<#
@@ -841,20 +887,21 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (<#=type.Name#>)(object)ScalarDivide(left[g], right[g]);
+ dataPtr[g] = (<#=typeAliases[type]#>)(object)ScalarDivide(left[g], right[g]);
}
return new Vector<T>(dataPtr);
}
<#
- }
+ }
#>
else
{
@@ -864,18 +911,19 @@ namespace System.Numerics
else
{
Vector<T> quotient = new Vector<T>();
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
- quotient.<#= GetRegisterFieldName(type, g) #> = (<#=type.Name#>)(left.<#= GetRegisterFieldName(type, g) #> / right.<#= GetRegisterFieldName(type, g) #>);
+ quotient.<#= GetRegisterFieldName(type, g) #> = (<#=typeAliases[type]#>)(left.<#= GetRegisterFieldName(type, g) #> / right.<#= GetRegisterFieldName(type, g) #>);
<#
- }
+ }
#>
}
<#
@@ -912,18 +960,18 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- Int64* resultBase = &result.register.int64_0;
- Int64* leftBase = &left.register.int64_0;
- Int64* rightBase = &right.register.int64_0;
- for (int g = 0; g < Vector<Int64>.Count; g++)
+ long* resultBase = &result.register.int64_0;
+ long* leftBase = &left.register.int64_0;
+ long* rightBase = &right.register.int64_0;
+ for (int g = 0; g < Vector<long>.Count; g++)
{
resultBase[g] = leftBase[g] & rightBase[g];
}
}
else
{
- result.<#=GetRegisterFieldName(typeof(Int64), 0)#> = left.<#=GetRegisterFieldName(typeof(Int64), 0)#> & right.<#=GetRegisterFieldName(typeof(Int64), 0)#>;
- result.<#=GetRegisterFieldName(typeof(Int64), 1)#> = left.<#=GetRegisterFieldName(typeof(Int64), 1)#> & right.<#=GetRegisterFieldName(typeof(Int64), 1)#>;
+ result.<#=GetRegisterFieldName(typeof(long), 0)#> = left.<#=GetRegisterFieldName(typeof(long), 0)#> & right.<#=GetRegisterFieldName(typeof(long), 0)#>;
+ result.<#=GetRegisterFieldName(typeof(long), 1)#> = left.<#=GetRegisterFieldName(typeof(long), 1)#> & right.<#=GetRegisterFieldName(typeof(long), 1)#>;
}
}
return result;
@@ -943,18 +991,18 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- Int64* resultBase = &result.register.int64_0;
- Int64* leftBase = &left.register.int64_0;
- Int64* rightBase = &right.register.int64_0;
- for (int g = 0; g < Vector<Int64>.Count; g++)
+ long* resultBase = &result.register.int64_0;
+ long* leftBase = &left.register.int64_0;
+ long* rightBase = &right.register.int64_0;
+ for (int g = 0; g < Vector<long>.Count; g++)
{
resultBase[g] = leftBase[g] | rightBase[g];
}
}
else
{
- result.<#=GetRegisterFieldName(typeof(Int64), 0)#> = left.<#=GetRegisterFieldName(typeof(Int64), 0)#> | right.<#=GetRegisterFieldName(typeof(Int64), 0)#>;
- result.<#=GetRegisterFieldName(typeof(Int64), 1)#> = left.<#=GetRegisterFieldName(typeof(Int64), 1)#> | right.<#=GetRegisterFieldName(typeof(Int64), 1)#>;
+ result.<#=GetRegisterFieldName(typeof(long), 0)#> = left.<#=GetRegisterFieldName(typeof(long), 0)#> | right.<#=GetRegisterFieldName(typeof(long), 0)#>;
+ result.<#=GetRegisterFieldName(typeof(long), 1)#> = left.<#=GetRegisterFieldName(typeof(long), 1)#> | right.<#=GetRegisterFieldName(typeof(long), 1)#>;
}
}
return result;
@@ -974,18 +1022,18 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
- Int64* resultBase = &result.register.int64_0;
- Int64* leftBase = &left.register.int64_0;
- Int64* rightBase = &right.register.int64_0;
- for (int g = 0; g < Vector<Int64>.Count; g++)
+ long* resultBase = &result.register.int64_0;
+ long* leftBase = &left.register.int64_0;
+ long* rightBase = &right.register.int64_0;
+ for (int g = 0; g < Vector<long>.Count; g++)
{
resultBase[g] = leftBase[g] ^ rightBase[g];
}
}
else
{
- result.<#=GetRegisterFieldName(typeof(Int64), 0)#> = left.<#=GetRegisterFieldName(typeof(Int64), 0)#> ^ right.<#=GetRegisterFieldName(typeof(Int64), 0)#>;
- result.<#=GetRegisterFieldName(typeof(Int64), 1)#> = left.<#=GetRegisterFieldName(typeof(Int64), 1)#> ^ right.<#=GetRegisterFieldName(typeof(Int64), 1)#>;
+ result.<#=GetRegisterFieldName(typeof(long), 0)#> = left.<#=GetRegisterFieldName(typeof(long), 0)#> ^ right.<#=GetRegisterFieldName(typeof(long), 0)#>;
+ result.<#=GetRegisterFieldName(typeof(long), 1)#> = left.<#=GetRegisterFieldName(typeof(long), 1)#> ^ right.<#=GetRegisterFieldName(typeof(long), 1)#>;
}
}
return result;
@@ -1030,7 +1078,8 @@ namespace System.Numerics
#endregion Logical Operators
#region Conversions
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
/// <summary>
@@ -1047,9 +1096,9 @@ namespace System.Numerics
}
#>
[Intrinsic]
- public static explicit operator Vector<<#=type.Name#>>(Vector<T> value)
+ public static explicit operator Vector<<#=typeAliases[type]#>>(Vector<T> value)
{
- return new Vector<<#=type.Name#>>(ref value.register);
+ return new Vector<<#=typeAliases[type]#>>(ref value.register);
}
<#
@@ -1064,15 +1113,16 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=type.Name#>)0;
+ dataPtr[g] = ScalarEquals(left[g], right[g]) ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=typeAliases[type]#>)0;
}
return new Vector<T>(dataPtr);
}
@@ -1087,23 +1137,24 @@ namespace System.Numerics
else
{
Register register = new Register();
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
- <#= GetRegisterFieldName(type, g) #> = left.<#= GetRegisterFieldName(type, g) #> == right.<#= GetRegisterFieldName(type, g) #> ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=type.Name#>)0;
+ <#= GetRegisterFieldName(type, g) #> = left.<#= GetRegisterFieldName(type, g) #> == right.<#= GetRegisterFieldName(type, g) #> ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=typeAliases[type]#>)0;
<#
- }
+ }
#>
return new Vector<T>(ref register);
}
<#
- }
+ }
#>
else
{
@@ -1118,15 +1169,16 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=type.Name#>)0;
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=typeAliases[type]#>)0;
}
return new Vector<T>(dataPtr);
}
@@ -1141,8 +1193,9 @@ namespace System.Numerics
else
{
Register register = new Register();
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
@@ -1150,14 +1203,14 @@ namespace System.Numerics
for (int g = 0; g < GetNumFields(type, totalSize); g++)
{
#>
- <#= GetRegisterFieldName(type, g) #> = left.<#= GetRegisterFieldName(type, g) #> < right.<#= GetRegisterFieldName(type, g) #> ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=type.Name#>)0;
+ <#= GetRegisterFieldName(type, g) #> = left.<#= GetRegisterFieldName(type, g) #> < right.<#= GetRegisterFieldName(type, g) #> ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=typeAliases[type]#>)0;
<#
}
#>
return new Vector<T>(ref register);
}
<#
- }
+ }
#>
else
{
@@ -1172,15 +1225,16 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=type.Name#>)0;
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=typeAliases[type]#>)0;
}
return new Vector<T>(dataPtr);
}
@@ -1195,23 +1249,24 @@ namespace System.Numerics
else
{
Register register = new Register();
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
- <#= GetRegisterFieldName(type, g) #> = left.<#= GetRegisterFieldName(type, g) #> > right.<#= GetRegisterFieldName(type, g) #> ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=type.Name#>)0;
+ <#= GetRegisterFieldName(type, g) #> = left.<#= GetRegisterFieldName(type, g) #> > right.<#= GetRegisterFieldName(type, g) #> ? ConstantHelper.Get<#=type.Name#>WithAllBitsSet() : (<#=typeAliases[type]#>)0;
<#
- }
+ }
#>
return new Vector<T>(ref register);
}
<#
- }
+ }
#>
else
{
@@ -1265,10 +1320,10 @@ namespace System.Numerics
#>
<#=GenerateIfStatementHeader(type, supportedTypes.Except(unsignedTypes))#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = (<#=type.Name#>)(object)(Math.Abs((<#=type.Name#>)(object)value[g]));
+ dataPtr[g] = (<#=typeAliases[type]#>)(object)(Math.Abs((<#=typeAliases[type]#>)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
@@ -1292,7 +1347,7 @@ namespace System.Numerics
for (int g = 0; g < GetNumFields(type, totalSize); g++)
{
#>
- value.<#=GetRegisterFieldName(type, g)#> = (<#=type.Name#>)(Math.Abs(value.<#=GetRegisterFieldName(type, g)#>));
+ value.<#=GetRegisterFieldName(type, g)#> = (<#=typeAliases[type]#>)(Math.Abs(value.<#=GetRegisterFieldName(type, g)#>));
<#
}
#>
@@ -1313,15 +1368,16 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (<#=type.Name#>)(object)left[g] : (<#=type.Name#>)(object)right[g];
+ dataPtr[g] = ScalarLessThan(left[g], right[g]) ? (<#=typeAliases[type]#>)(object)left[g] : (<#=typeAliases[type]#>)(object)right[g];
}
return new Vector<T>(dataPtr);
}
@@ -1336,23 +1392,24 @@ namespace System.Numerics
else
{
Vector<T> vec = new Vector<T>();
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
vec.<#=GetRegisterFieldName(type, g)#> = left.<#=GetRegisterFieldName(type, g)#> < right.<#=GetRegisterFieldName(type, g)#> ? left.<#=GetRegisterFieldName(type, g)#> : right.<#=GetRegisterFieldName(type, g)#>;
<#
- }
+ }
#>
return vec;
}
<#
- }
+ }
#>
else
{
@@ -1366,15 +1423,16 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
+<#
+ foreach (Type type in supportedTypes)
{
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (<#=type.Name#>)(object)left[g] : (<#=type.Name#>)(object)right[g];
+ dataPtr[g] = ScalarGreaterThan(left[g], right[g]) ? (<#=typeAliases[type]#>)(object)left[g] : (<#=typeAliases[type]#>)(object)right[g];
}
return new Vector<T>(dataPtr);
}
@@ -1389,23 +1447,24 @@ namespace System.Numerics
else
{
Vector<T> vec = new Vector<T>();
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
vec.<#=GetRegisterFieldName(type, g)#> = left.<#=GetRegisterFieldName(type, g)#> > right.<#=GetRegisterFieldName(type, g)#> ? left.<#=GetRegisterFieldName(type, g)#> : right.<#=GetRegisterFieldName(type, g)#>;
<#
- }
+ }
#>
return vec;
}
<#
- }
+ }
#>
else
{
@@ -1428,24 +1487,25 @@ namespace System.Numerics
}
else
{
-<# foreach (Type type in supportedTypes)
- {
- #>
+<#
+ foreach (Type type in supportedTypes)
+ {
+#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#> product = 0;
+ <#=typeAliases[type]#> product = 0;
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
- product += (<#=type.Name#>)(left.<#=GetRegisterFieldName(type, g)#> * right.<#=GetRegisterFieldName(type, g)#>);
+ product += (<#=typeAliases[type]#>)(left.<#=GetRegisterFieldName(type, g)#> * right.<#=GetRegisterFieldName(type, g)#>);
<#
- }
+ }
#>
return (T)(object)product;
}
<#
- }
+ }
#>
else
{
@@ -1459,20 +1519,21 @@ namespace System.Numerics
{
if (Vector.IsHardwareAccelerated)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#>* dataPtr = stackalloc <#=type.Name#>[Count];
+ <#=typeAliases[type]#>* dataPtr = stackalloc <#=typeAliases[type]#>[Count];
for (int g = 0; g < Count; g++)
{
- dataPtr[g] = unchecked((<#=type.Name#>)Math.Sqrt((<#=type.Name#>)(object)value[g]));
+ dataPtr[g] = unchecked((<#=typeAliases[type]#>)Math.Sqrt((<#=typeAliases[type]#>)(object)value[g]));
}
return new Vector<T>(dataPtr);
}
<#
- }
+ }
#>
else
{
@@ -1481,23 +1542,24 @@ namespace System.Numerics
}
else
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
<#
- for (int g = 0; g < GetNumFields(type, totalSize); g++)
- {
+ for (int g = 0; g < GetNumFields(type, totalSize); g++)
+ {
#>
- value.<#=GetRegisterFieldName(type, g)#> = (<#=type.Name#>)Math.Sqrt(value.<#=GetRegisterFieldName(type, g)#>);
+ value.<#=GetRegisterFieldName(type, g)#> = (<#=typeAliases[type]#>)Math.Sqrt(value.<#=GetRegisterFieldName(type, g)#>);
<#
- }
+ }
#>
return value;
}
<#
- }
+ }
#>
else
{
@@ -1511,15 +1573,16 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static bool ScalarEquals(T left, T right)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- return (<#=type.Name#>)(object)left == (<#=type.Name#>)(object)right;
+ return (<#=typeAliases[type]#>)(object)left == (<#=typeAliases[type]#>)(object)right;
}
<#
- }
+ }
#>
else
{
@@ -1530,15 +1593,16 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static bool ScalarLessThan(T left, T right)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- return (<#=type.Name#>)(object)left < (<#=type.Name#>)(object)right;
+ return (<#=typeAliases[type]#>)(object)left < (<#=typeAliases[type]#>)(object)right;
}
<#
- }
+ }
#>
else
{
@@ -1549,15 +1613,16 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static bool ScalarGreaterThan(T left, T right)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- return (<#=type.Name#>)(object)left > (<#=type.Name#>)(object)right;
+ return (<#=typeAliases[type]#>)(object)left > (<#=typeAliases[type]#>)(object)right;
}
<#
- }
+ }
#>
else
{
@@ -1568,15 +1633,16 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T ScalarAdd(T left, T right)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- return (T)(object)unchecked((<#=type.Name#>)((<#=type.Name#>)(object)left + (<#=type.Name#>)(object)right));
+ return (T)(object)unchecked((<#=typeAliases[type]#>)((<#=typeAliases[type]#>)(object)left + (<#=typeAliases[type]#>)(object)right));
}
<#
- }
+ }
#>
else
{
@@ -1587,15 +1653,16 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T ScalarSubtract(T left, T right)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- return (T)(object)(<#=type.Name#>)((<#=type.Name#>)(object)left - (<#=type.Name#>)(object)right);
+ return (T)(object)(<#=typeAliases[type]#>)((<#=typeAliases[type]#>)(object)left - (<#=typeAliases[type]#>)(object)right);
}
<#
- }
+ }
#>
else
{
@@ -1606,15 +1673,16 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T ScalarMultiply(T left, T right)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- return (T)(object)unchecked((<#=type.Name#>)((<#=type.Name#>)(object)left * (<#=type.Name#>)(object)right));
+ return (T)(object)unchecked((<#=typeAliases[type]#>)((<#=typeAliases[type]#>)(object)left * (<#=typeAliases[type]#>)(object)right));
}
<#
- }
+ }
#>
else
{
@@ -1625,15 +1693,16 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T ScalarDivide(T left, T right)
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- return (T)(object)(<#=type.Name#>)((<#=type.Name#>)(object)left / (<#=type.Name#>)(object)right);
+ return (T)(object)(<#=typeAliases[type]#>)((<#=typeAliases[type]#>)(object)left / (<#=typeAliases[type]#>)(object)right);
}
<#
- }
+ }
#>
else
{
@@ -1644,16 +1713,17 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T GetOneValue()
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
- <#=type.Name#> value = 1;
+ <#=typeAliases[type]#> value = 1;
return (T)(object)value;
}
<#
- }
+ }
#>
else
{
@@ -1664,15 +1734,16 @@ namespace System.Numerics
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
private static T GetAllBitsSetValue()
{
-<# foreach (Type type in supportedTypes)
- {
+<#
+ foreach (Type type in supportedTypes)
+ {
#>
<#=GenerateIfStatementHeader(type)#>
{
return (T)(object)ConstantHelper.Get<#=type.Name#>WithAllBitsSet();
}
<#
- }
+ }
#>
else
{
@@ -1686,7 +1757,8 @@ namespace System.Numerics
public static partial class Vector
{
#region Widen/Narrow
-<# foreach (Type type in WidenableTypes)
+<#
+ foreach (Type type in WidenableTypes)
{
Type widenTarget = GetWidenTarget(type);
#>
@@ -1705,28 +1777,28 @@ namespace System.Numerics
}
#>
[Intrinsic]
- public static unsafe void Widen(Vector<<#=type.Name#>> source, out Vector<<#=widenTarget.Name#>> low, out Vector<<#=widenTarget.Name#>> high)
+ public static unsafe void Widen(Vector<<#=typeAliases[type]#>> source, out Vector<<#=typeAliases[widenTarget]#>> low, out Vector<<#=typeAliases[widenTarget]#>> high)
{
- int elements = Vector<<#=type.Name#>>.Count;
- <#=widenTarget.Name#>* lowPtr = stackalloc <#=widenTarget.Name#>[elements / 2];
+ int elements = Vector<<#=typeAliases[type]#>>.Count;
+ <#=typeAliases[widenTarget]#>* lowPtr = stackalloc <#=typeAliases[widenTarget]#>[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- lowPtr[i] = (<#=widenTarget.Name#>)source[i];
+ lowPtr[i] = (<#=typeAliases[widenTarget]#>)source[i];
}
- <#=widenTarget.Name#>* highPtr = stackalloc <#=widenTarget.Name#>[elements / 2];
+ <#=typeAliases[widenTarget]#>* highPtr = stackalloc <#=typeAliases[widenTarget]#>[elements / 2];
for (int i = 0; i < elements / 2; i++)
{
- highPtr[i] = (<#=widenTarget.Name#>)source[i + (elements / 2)];
+ highPtr[i] = (<#=typeAliases[widenTarget]#>)source[i + (elements / 2)];
}
- low = new Vector<<#=widenTarget.Name#>>(lowPtr);
- high = new Vector<<#=widenTarget.Name#>>(highPtr);
+ low = new Vector<<#=typeAliases[widenTarget]#>>(lowPtr);
+ high = new Vector<<#=typeAliases[widenTarget]#>>(highPtr);
}
<#
}
-#>
-<# foreach (Type narrowSource in NarrowableTypes)
+
+ foreach (Type narrowSource in NarrowableTypes)
{
Type narrowTarget = GetNarrowTarget(narrowSource);
#>
@@ -1745,23 +1817,23 @@ namespace System.Numerics
}
#>
[Intrinsic]
- public static unsafe Vector<<#=narrowTarget.Name#>> Narrow(Vector<<#=narrowSource.Name#>> low, Vector<<#=narrowSource.Name#>> high)
+ public static unsafe Vector<<#=typeAliases[narrowTarget]#>> Narrow(Vector<<#=typeAliases[narrowSource]#>> low, Vector<<#=typeAliases[narrowSource]#>> high)
{
- unchecked
- {
- int elements = Vector<<#=narrowTarget.Name#>>.Count;
- <#=narrowTarget.Name#>* retPtr = stackalloc <#=narrowTarget.Name#>[elements];
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i] = (<#=narrowTarget.Name#>)low[i];
- }
- for (int i = 0; i < elements / 2; i++)
- {
- retPtr[i + (elements / 2)] = (<#=narrowTarget.Name#>)high[i];
- }
+ unchecked
+ {
+ int elements = Vector<<#=typeAliases[narrowTarget]#>>.Count;
+ <#=typeAliases[narrowTarget]#>* retPtr = stackalloc <#=typeAliases[narrowTarget]#>[elements];
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i] = (<#=typeAliases[narrowTarget]#>)low[i];
+ }
+ for (int i = 0; i < elements / 2; i++)
+ {
+ retPtr[i + (elements / 2)] = (<#=typeAliases[narrowTarget]#>)high[i];
+ }
- return new Vector<<#=narrowTarget.Name#>>(retPtr);
- }
+ return new Vector<<#=typeAliases[narrowTarget]#>>(retPtr);
+ }
}
<#
@@ -1770,7 +1842,8 @@ namespace System.Numerics
#endregion Widen/Narrow
#region Same-Size Conversion
-<# foreach (var pair in SameSizeConversionPairs)
+<#
+ foreach (var pair in SameSizeConversionPairs)
{
#>
/// <summary>
@@ -1787,22 +1860,24 @@ namespace System.Numerics
}
#>
[Intrinsic]
- public static unsafe Vector<<#=pair.Value.Name#>> ConvertTo<#=pair.Value.Name#>(Vector<<#=pair.Key.Name#>> value)
+ public static unsafe Vector<<#=typeAliases[pair.Value]#>> ConvertTo<#=pair.Value.Name#>(Vector<<#=typeAliases[pair.Key]#>> value)
{
- unchecked
- {
- int elements = Vector<<#=pair.Value.Name#>>.Count;
- <#=pair.Value.Name#>* retPtr = stackalloc <#=pair.Value.Name#>[elements];
- for (int i = 0; i < elements; i++)
- {
- retPtr[i] = (<#=pair.Value.Name#>)value[i];
- }
+ unchecked
+ {
+ int elements = Vector<<#=typeAliases[pair.Value]#>>.Count;
+ <#=typeAliases[pair.Value]#>* retPtr = stackalloc <#=typeAliases[pair.Value]#>[elements];
+ for (int i = 0; i < elements; i++)
+ {
+ retPtr[i] = (<#=typeAliases[pair.Value]#>)value[i];
+ }
- return new Vector<<#=pair.Value.Name#>>(retPtr);
- }
+ return new Vector<<#=typeAliases[pair.Value]#>>(retPtr);
+ }
}
-<# } #>
+<#
+ }
+#>
#endregion Same-Size Conversion
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Numerics/Vector_Operations.cs b/src/System.Private.CoreLib/shared/System/Numerics/Vector_Operations.cs
index b69b058be..d3ed2509d 100644
--- a/src/System.Private.CoreLib/shared/System/Numerics/Vector_Operations.cs
+++ b/src/System.Private.CoreLib/shared/System/Numerics/Vector_Operations.cs
@@ -22,9 +22,9 @@ namespace System.Numerics
/// <param name="right">The second source vector.</param>
/// <returns>The new vector with elements selected based on the mask.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<Single> ConditionalSelect(Vector<int> condition, Vector<Single> left, Vector<Single> right)
+ public static Vector<float> ConditionalSelect(Vector<int> condition, Vector<float> left, Vector<float> right)
{
- return (Vector<Single>)Vector<Single>.ConditionalSelect((Vector<Single>)condition, left, right);
+ return (Vector<float>)Vector<float>.ConditionalSelect((Vector<float>)condition, left, right);
}
/// <summary>
@@ -75,9 +75,9 @@ namespace System.Numerics
/// <param name="right">The second vector to compare.</param>
/// <returns>The resultant vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<int> Equals(Vector<Single> left, Vector<Single> right)
+ public static Vector<int> Equals(Vector<float> left, Vector<float> right)
{
- return (Vector<int>)Vector<Single>.Equals(left, right);
+ return (Vector<int>)Vector<float>.Equals(left, right);
}
/// <summary>
@@ -163,9 +163,9 @@ namespace System.Numerics
/// <param name="right">The second vector to compare.</param>
/// <returns>The resultant integral vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<int> LessThan(Vector<Single> left, Vector<Single> right)
+ public static Vector<int> LessThan(Vector<float> left, Vector<float> right)
{
- return (Vector<int>)Vector<Single>.LessThan(left, right);
+ return (Vector<int>)Vector<float>.LessThan(left, right);
}
/// <summary>
@@ -256,9 +256,9 @@ namespace System.Numerics
/// <param name="right">The second vector to compare.</param>
/// <returns>The resultant integral vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<int> LessThanOrEqual(Vector<Single> left, Vector<Single> right)
+ public static Vector<int> LessThanOrEqual(Vector<float> left, Vector<float> right)
{
- return (Vector<int>)Vector<Single>.LessThanOrEqual(left, right);
+ return (Vector<int>)Vector<float>.LessThanOrEqual(left, right);
}
/// <summary>
@@ -349,9 +349,9 @@ namespace System.Numerics
/// <param name="right">The second vector to compare.</param>
/// <returns>The resultant integral vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<int> GreaterThan(Vector<Single> left, Vector<Single> right)
+ public static Vector<int> GreaterThan(Vector<float> left, Vector<float> right)
{
- return (Vector<int>)Vector<Single>.GreaterThan(left, right);
+ return (Vector<int>)Vector<float>.GreaterThan(left, right);
}
/// <summary>
@@ -443,9 +443,9 @@ namespace System.Numerics
/// <param name="right">The second vector to compare.</param>
/// <returns>The resultant integral vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<int> GreaterThanOrEqual(Vector<Single> left, Vector<Single> right)
+ public static Vector<int> GreaterThanOrEqual(Vector<float> left, Vector<float> right)
{
- return (Vector<int>)Vector<Single>.GreaterThanOrEqual(left, right);
+ return (Vector<int>)Vector<float>.GreaterThanOrEqual(left, right);
}
/// <summary>
@@ -752,9 +752,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<Byte> AsVectorByte<T>(Vector<T> value) where T : struct
+ public static Vector<byte> AsVectorByte<T>(Vector<T> value) where T : struct
{
- return (Vector<Byte>)value;
+ return (Vector<byte>)value;
}
/// <summary>
@@ -764,9 +764,9 @@ namespace System.Numerics
/// <returns>The reinterpreted vector.</returns>
[CLSCompliant(false)]
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<SByte> AsVectorSByte<T>(Vector<T> value) where T : struct
+ public static Vector<sbyte> AsVectorSByte<T>(Vector<T> value) where T : struct
{
- return (Vector<SByte>)value;
+ return (Vector<sbyte>)value;
}
/// <summary>
@@ -776,9 +776,9 @@ namespace System.Numerics
/// <returns>The reinterpreted vector.</returns>
[CLSCompliant(false)]
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<UInt16> AsVectorUInt16<T>(Vector<T> value) where T : struct
+ public static Vector<ushort> AsVectorUInt16<T>(Vector<T> value) where T : struct
{
- return (Vector<UInt16>)value;
+ return (Vector<ushort>)value;
}
/// <summary>
@@ -787,9 +787,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<Int16> AsVectorInt16<T>(Vector<T> value) where T : struct
+ public static Vector<short> AsVectorInt16<T>(Vector<T> value) where T : struct
{
- return (Vector<Int16>)value;
+ return (Vector<short>)value;
}
/// <summary>
@@ -799,9 +799,9 @@ namespace System.Numerics
/// <returns>The reinterpreted vector.</returns>
[CLSCompliant(false)]
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<UInt32> AsVectorUInt32<T>(Vector<T> value) where T : struct
+ public static Vector<uint> AsVectorUInt32<T>(Vector<T> value) where T : struct
{
- return (Vector<UInt32>)value;
+ return (Vector<uint>)value;
}
/// <summary>
@@ -810,9 +810,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<Int32> AsVectorInt32<T>(Vector<T> value) where T : struct
+ public static Vector<int> AsVectorInt32<T>(Vector<T> value) where T : struct
{
- return (Vector<Int32>)value;
+ return (Vector<int>)value;
}
/// <summary>
@@ -822,9 +822,9 @@ namespace System.Numerics
/// <returns>The reinterpreted vector.</returns>
[CLSCompliant(false)]
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<UInt64> AsVectorUInt64<T>(Vector<T> value) where T : struct
+ public static Vector<ulong> AsVectorUInt64<T>(Vector<T> value) where T : struct
{
- return (Vector<UInt64>)value;
+ return (Vector<ulong>)value;
}
@@ -834,9 +834,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<Int64> AsVectorInt64<T>(Vector<T> value) where T : struct
+ public static Vector<long> AsVectorInt64<T>(Vector<T> value) where T : struct
{
- return (Vector<Int64>)value;
+ return (Vector<long>)value;
}
/// <summary>
@@ -845,9 +845,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<Single> AsVectorSingle<T>(Vector<T> value) where T : struct
+ public static Vector<float> AsVectorSingle<T>(Vector<T> value) where T : struct
{
- return (Vector<Single>)value;
+ return (Vector<float>)value;
}
/// <summary>
@@ -856,9 +856,9 @@ namespace System.Numerics
/// <param name="value">The source vector</param>
/// <returns>The reinterpreted vector.</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static Vector<Double> AsVectorDouble<T>(Vector<T> value) where T : struct
+ public static Vector<double> AsVectorDouble<T>(Vector<T> value) where T : struct
{
- return (Vector<Double>)value;
+ return (Vector<double>)value;
}
#endregion Conversion Methods
}
diff --git a/src/System.Private.CoreLib/shared/System/ObjectDisposedException.cs b/src/System.Private.CoreLib/shared/System/ObjectDisposedException.cs
index 3daed13bb..8f13055b9 100644
--- a/src/System.Private.CoreLib/shared/System/ObjectDisposedException.cs
+++ b/src/System.Private.CoreLib/shared/System/ObjectDisposedException.cs
@@ -15,7 +15,7 @@ namespace System
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class ObjectDisposedException : InvalidOperationException
{
- private String _objectName;
+ private string _objectName;
// This constructor should only be called by the EE (COMPlusThrow)
private ObjectDisposedException() :
@@ -23,18 +23,18 @@ namespace System
{
}
- public ObjectDisposedException(String objectName) :
+ public ObjectDisposedException(string objectName) :
this(objectName, SR.ObjectDisposed_Generic)
{
}
- public ObjectDisposedException(String objectName, String message) : base(message)
+ public ObjectDisposedException(string objectName, string message) : base(message)
{
HResult = HResults.COR_E_OBJECTDISPOSED;
_objectName = objectName;
}
- public ObjectDisposedException(String message, Exception innerException)
+ public ObjectDisposedException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_OBJECTDISPOSED;
@@ -55,26 +55,26 @@ namespace System
/// <devdoc>
/// <para>Gets the text for the message for this exception.</para>
/// </devdoc>
- public override String Message
+ public override string Message
{
get
{
- String name = ObjectName;
+ string name = ObjectName;
if (name == null || name.Length == 0)
return base.Message;
- String objectDisposed = SR.Format(SR.ObjectDisposed_ObjectName_Name, name);
+ string objectDisposed = SR.Format(SR.ObjectDisposed_ObjectName_Name, name);
return base.Message + Environment.NewLine + objectDisposed;
}
}
- public String ObjectName
+ public string ObjectName
{
get
{
if (_objectName == null)
{
- return String.Empty;
+ return string.Empty;
}
return _objectName;
}
diff --git a/src/System.Private.CoreLib/shared/System/ObsoleteAttribute.cs b/src/System.Private.CoreLib/shared/System/ObsoleteAttribute.cs
index a63db137f..748681756 100644
--- a/src/System.Private.CoreLib/shared/System/ObsoleteAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/ObsoleteAttribute.cs
@@ -26,7 +26,7 @@ namespace System
, Inherited = false)]
public sealed class ObsoleteAttribute : Attribute
{
- private String _message;
+ private string _message;
private bool _error;
public ObsoleteAttribute()
@@ -35,19 +35,19 @@ namespace System
_error = false;
}
- public ObsoleteAttribute(String message)
+ public ObsoleteAttribute(string message)
{
_message = message;
_error = false;
}
- public ObsoleteAttribute(String message, bool error)
+ public ObsoleteAttribute(string message, bool error)
{
_message = message;
_error = error;
}
- public String Message
+ public string Message
{
get { return _message; }
}
diff --git a/src/System.Private.CoreLib/shared/System/OperationCanceledException.cs b/src/System.Private.CoreLib/shared/System/OperationCanceledException.cs
index 8a472c9ff..0c311afd7 100644
--- a/src/System.Private.CoreLib/shared/System/OperationCanceledException.cs
+++ b/src/System.Private.CoreLib/shared/System/OperationCanceledException.cs
@@ -36,13 +36,13 @@ namespace System
HResult = HResults.COR_E_OPERATIONCANCELED;
}
- public OperationCanceledException(String message)
+ public OperationCanceledException(string message)
: base(message)
{
HResult = HResults.COR_E_OPERATIONCANCELED;
}
- public OperationCanceledException(String message, Exception innerException)
+ public OperationCanceledException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_OPERATIONCANCELED;
@@ -55,13 +55,13 @@ namespace System
CancellationToken = token;
}
- public OperationCanceledException(String message, CancellationToken token)
+ public OperationCanceledException(string message, CancellationToken token)
: this(message)
{
CancellationToken = token;
}
- public OperationCanceledException(String message, Exception innerException, CancellationToken token)
+ public OperationCanceledException(string message, Exception innerException, CancellationToken token)
: this(message, innerException)
{
CancellationToken = token;
diff --git a/src/System.Private.CoreLib/src/System/OutOfMemoryException.cs b/src/System.Private.CoreLib/shared/System/OutOfMemoryException.cs
index 5bd4f21e8..c59852f78 100644
--- a/src/System.Private.CoreLib/src/System/OutOfMemoryException.cs
+++ b/src/System.Private.CoreLib/shared/System/OutOfMemoryException.cs
@@ -2,38 +2,37 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-/*=============================================================================
-**
-**
-**
-** Purpose: The exception class for OOM.
-**
-**
-=============================================================================*/
-
using System.Runtime.Serialization;
namespace System
{
+ /// <summary>
+ /// The exception class for OOM.
+ /// </summary>
[Serializable]
#if !MONO
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
#endif
public class OutOfMemoryException : SystemException
{
- public OutOfMemoryException()
- : base(SR.Arg_OutOfMemoryException)
+ public OutOfMemoryException() : base(
+#if CORECLR
+ GetMessageFromNativeResources(ExceptionMessageKind.OutOfMemory)
+#else
+ SR.Arg_OutOfMemoryException
+#endif
+ )
{
HResult = HResults.COR_E_OUTOFMEMORY;
}
- public OutOfMemoryException(String message)
+ public OutOfMemoryException(string message)
: base(message)
{
HResult = HResults.COR_E_OUTOFMEMORY;
}
- public OutOfMemoryException(String message, Exception innerException)
+ public OutOfMemoryException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_OUTOFMEMORY;
diff --git a/src/System.Private.CoreLib/shared/System/OverflowException.cs b/src/System.Private.CoreLib/shared/System/OverflowException.cs
index e28dcb87e..c18fe3f7b 100644
--- a/src/System.Private.CoreLib/shared/System/OverflowException.cs
+++ b/src/System.Private.CoreLib/shared/System/OverflowException.cs
@@ -25,13 +25,13 @@ namespace System
HResult = HResults.COR_E_OVERFLOW;
}
- public OverflowException(String message)
+ public OverflowException(string message)
: base(message)
{
HResult = HResults.COR_E_OVERFLOW;
}
- public OverflowException(String message, Exception innerException)
+ public OverflowException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_OVERFLOW;
diff --git a/src/System.Private.CoreLib/shared/System/PlatformNotSupportedException.cs b/src/System.Private.CoreLib/shared/System/PlatformNotSupportedException.cs
index 5039f3f44..f9e461ed0 100644
--- a/src/System.Private.CoreLib/shared/System/PlatformNotSupportedException.cs
+++ b/src/System.Private.CoreLib/shared/System/PlatformNotSupportedException.cs
@@ -25,13 +25,13 @@ namespace System
HResult = HResults.COR_E_PLATFORMNOTSUPPORTED;
}
- public PlatformNotSupportedException(String message)
+ public PlatformNotSupportedException(string message)
: base(message)
{
HResult = HResults.COR_E_PLATFORMNOTSUPPORTED;
}
- public PlatformNotSupportedException(String message, Exception inner)
+ public PlatformNotSupportedException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_PLATFORMNOTSUPPORTED;
diff --git a/src/System.Private.CoreLib/shared/System/Random.cs b/src/System.Private.CoreLib/shared/System/Random.cs
index 20f035e2e..ed79732c2 100644
--- a/src/System.Private.CoreLib/shared/System/Random.cs
+++ b/src/System.Private.CoreLib/shared/System/Random.cs
@@ -156,7 +156,7 @@ namespace System
/*=====================================Next=====================================
- **Returns: An int [0..Int32.MaxValue)
+ **Returns: An int [0..int.MaxValue)
**Arguments: None
**Exceptions: None.
==============================================================================*/
@@ -169,7 +169,7 @@ namespace System
{
// The distribution of double value returned by Sample
// is not distributed well enough for a large range.
- // If we use Sample for a range [Int32.MinValue..Int32.MaxValue)
+ // If we use Sample for a range [int.MinValue..int.MaxValue)
// We will end up getting even numbers only.
int result = InternalSample();
diff --git a/src/System.Private.CoreLib/shared/System/RankException.cs b/src/System.Private.CoreLib/shared/System/RankException.cs
index bdd2cd51f..e1e7d169b 100644
--- a/src/System.Private.CoreLib/shared/System/RankException.cs
+++ b/src/System.Private.CoreLib/shared/System/RankException.cs
@@ -26,13 +26,13 @@ namespace System
HResult = HResults.COR_E_RANK;
}
- public RankException(String message)
+ public RankException(string message)
: base(message)
{
HResult = HResults.COR_E_RANK;
}
- public RankException(String message, Exception innerException)
+ public RankException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_RANK;
diff --git a/src/System.Private.CoreLib/shared/System/ReadOnlyMemory.cs b/src/System.Private.CoreLib/shared/System/ReadOnlyMemory.cs
index 166a204ed..02445ec5c 100644
--- a/src/System.Private.CoreLib/shared/System/ReadOnlyMemory.cs
+++ b/src/System.Private.CoreLib/shared/System/ReadOnlyMemory.cs
@@ -8,9 +8,8 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute;
using EditorBrowsableState = System.ComponentModel.EditorBrowsableState;
-#if !FEATURE_PORTABLE_SPAN
+
using Internal.Runtime.CompilerServices;
-#endif // FEATURE_PORTABLE_SPAN
namespace System
{
@@ -18,21 +17,23 @@ namespace System
/// Represents a contiguous region of memory, similar to <see cref="ReadOnlySpan{T}"/>.
/// Unlike <see cref="ReadOnlySpan{T}"/>, it is not a byref-like type.
/// </summary>
- [DebuggerDisplay("{DebuggerDisplay,nq}")]
[DebuggerTypeProxy(typeof(MemoryDebugView<>))]
+ [DebuggerDisplay("{ToString(),raw}")]
public readonly struct ReadOnlyMemory<T>
{
// NOTE: With the current implementation, Memory<T> and ReadOnlyMemory<T> must have the same layout,
// as code uses Unsafe.As to cast between them.
// The highest order bit of _index is used to discern whether _object is an array/string or an owned memory
- // if (_index >> 31) == 1, _object is an OwnedMemory<T>
- // else, _object is a T[] or string
+ // if (_index >> 31) == 1, _object is an MemoryManager<T>
+ // else, _object is a T[] or string.
+ // if (_length >> 31) == 1, _object is a pre-pinned array, so Pin() will not allocate a new GCHandle
+ // else, Pin() needs to allocate a new GCHandle to pin the object.
private readonly object _object;
private readonly int _index;
private readonly int _length;
- internal const int RemoveOwnedFlagBitMask = 0x7FFFFFFF;
+ internal const int RemoveFlagsBitMask = 0x7FFFFFFF;
/// <summary>
/// Creates a new memory over the entirety of the target array.
@@ -97,9 +98,6 @@ namespace System
_length = length;
}
- //Debugger Display = {T[length]}
- private string DebuggerDisplay => string.Format("{{{0}[{1}]}}", typeof(T).Name, _length);
-
/// <summary>
/// Defines an implicit conversion of an array to a <see cref="ReadOnlyMemory{T}"/>
/// </summary>
@@ -108,7 +106,7 @@ namespace System
/// <summary>
/// Defines an implicit conversion of a <see cref="ArraySegment{T}"/> to a <see cref="ReadOnlyMemory{T}"/>
/// </summary>
- public static implicit operator ReadOnlyMemory<T>(ArraySegment<T> arraySegment) => new ReadOnlyMemory<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
+ public static implicit operator ReadOnlyMemory<T>(ArraySegment<T> segment) => new ReadOnlyMemory<T>(segment.Array, segment.Offset, segment.Count);
/// <summary>
/// Returns an empty <see cref="ReadOnlyMemory{T}"/>
@@ -118,12 +116,25 @@ namespace System
/// <summary>
/// The number of items in the memory.
/// </summary>
- public int Length => _length;
+ public int Length => _length & RemoveFlagsBitMask;
/// <summary>
/// Returns true if Length is 0.
/// </summary>
- public bool IsEmpty => _length == 0;
+ public bool IsEmpty => (_length & RemoveFlagsBitMask) == 0;
+
+ /// <summary>
+ /// For <see cref="ReadOnlyMemory{Char}"/>, returns a new instance of string that represents the characters pointed to by the memory.
+ /// Otherwise, returns a <see cref="string"/> with the name of the type and the number of elements.
+ /// </summary>
+ public override string ToString()
+ {
+ if (typeof(T) == typeof(char))
+ {
+ return (_object is string str) ? str.Substring(_index, _length & RemoveFlagsBitMask) : Span.ToString();
+ }
+ return string.Format("System.ReadOnlyMemory<{0}>[{1}]", typeof(T).Name, _length & RemoveFlagsBitMask);
+ }
/// <summary>
/// Forms a slice out of the given memory, beginning at 'start'.
@@ -135,12 +146,16 @@ namespace System
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlyMemory<T> Slice(int start)
{
- if ((uint)start > (uint)_length)
+ // Used to maintain the high-bit which indicates whether the Memory has been pre-pinned or not.
+ int capturedLength = _length;
+ int actualLength = capturedLength & RemoveFlagsBitMask;
+ if ((uint)start > (uint)actualLength)
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
}
- return new ReadOnlyMemory<T>(_object, _index + start, _length - start);
+ // It is expected for (capturedLength - start) to be negative if the memory is already pre-pinned.
+ return new ReadOnlyMemory<T>(_object, _index + start, capturedLength - start);
}
/// <summary>
@@ -154,12 +169,16 @@ namespace System
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlyMemory<T> Slice(int start, int length)
{
- if ((uint)start > (uint)_length || (uint)length > (uint)(_length - start))
+ // Used to maintain the high-bit which indicates whether the Memory has been pre-pinned or not.
+ int capturedLength = _length;
+ int actualLength = _length & RemoveFlagsBitMask;
+ if ((uint)start > (uint)actualLength || (uint)length > (uint)(actualLength - start))
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
}
- return new ReadOnlyMemory<T>(_object, _index + start, length);
+ // Set the high-bit to match the this._length high bit (1 for pre-pinned, 0 for unpinned).
+ return new ReadOnlyMemory<T>(_object, _index + start, length | (capturedLength & ~RemoveFlagsBitMask));
}
/// <summary>
@@ -172,19 +191,18 @@ namespace System
{
if (_index < 0)
{
- return ((OwnedMemory<T>)_object).Span.Slice(_index & RemoveOwnedFlagBitMask, _length);
+ Debug.Assert(_length >= 0);
+ Debug.Assert(_object != null);
+ return ((MemoryManager<T>)_object).GetSpan().Slice(_index & RemoveFlagsBitMask, _length);
}
else if (typeof(T) == typeof(char) && _object is string s)
{
-#if FEATURE_PORTABLE_SPAN
- return new ReadOnlySpan<T>(Unsafe.As<Pinnable<T>>(s), MemoryExtensions.StringAdjustment, s.Length).Slice(_index, _length);
-#else
+ Debug.Assert(_length >= 0);
return new ReadOnlySpan<T>(ref Unsafe.As<char, T>(ref s.GetRawStringData()), s.Length).Slice(_index, _length);
-#endif // FEATURE_PORTABLE_SPAN
}
else if (_object != null)
{
- return new ReadOnlySpan<T>((T[])_object, _index, _length);
+ return new ReadOnlySpan<T>((T[])_object, _index, _length & RemoveFlagsBitMask);
}
else
{
@@ -216,50 +234,43 @@ namespace System
/// <param name="destination">The span to copy items into.</param>
public bool TryCopyTo(Memory<T> destination) => Span.TryCopyTo(destination.Span);
- /// <summary>Creates a handle for the memory.</summary>
- /// <param name="pin">
- /// If pin is true, the GC will not move the array until the returned <see cref="MemoryHandle"/>
- /// is disposed, enabling the memory's address can be taken and used.
- /// </param>
- public unsafe MemoryHandle Retain(bool pin = false)
+ /// <summary>
+ /// Creates a handle for the memory.
+ /// The GC will not move the memory until the returned <see cref="MemoryHandle"/>
+ /// is disposed, enabling taking and using the memory's address.
+ /// <exception cref="System.ArgumentException">
+ /// An instance with nonprimitive (non-blittable) members cannot be pinned.
+ /// </exception>
+ /// </summary>
+ public unsafe MemoryHandle Pin()
{
- MemoryHandle memoryHandle = default;
- if (pin)
+ if (_index < 0)
{
- if (_index < 0)
- {
- memoryHandle = ((OwnedMemory<T>)_object).Pin((_index & RemoveOwnedFlagBitMask) * Unsafe.SizeOf<T>());
- }
- else if (typeof(T) == typeof(char) && _object is string s)
- {
- GCHandle handle = GCHandle.Alloc(s, GCHandleType.Pinned);
-#if FEATURE_PORTABLE_SPAN
- void* pointer = Unsafe.Add<T>((void*)handle.AddrOfPinnedObject(), _index);
-#else
- void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref s.GetRawStringData()), _index);
-#endif // FEATURE_PORTABLE_SPAN
- memoryHandle = new MemoryHandle(null, pointer, handle);
- }
- else if (_object is T[] array)
+ Debug.Assert(_object != null);
+ return ((MemoryManager<T>)_object).Pin((_index & RemoveFlagsBitMask));
+ }
+ else if (typeof(T) == typeof(char) && _object is string s)
+ {
+ GCHandle handle = GCHandle.Alloc(s, GCHandleType.Pinned);
+ void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref s.GetRawStringData()), _index);
+ return new MemoryHandle(pointer, handle);
+ }
+ else if (_object is T[] array)
+ {
+ // Array is already pre-pinned
+ if (_length < 0)
{
- var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
-#if FEATURE_PORTABLE_SPAN
- void* pointer = Unsafe.Add<T>((void*)handle.AddrOfPinnedObject(), _index);
-#else
void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index);
-#endif // FEATURE_PORTABLE_SPAN
- memoryHandle = new MemoryHandle(null, pointer, handle);
+ return new MemoryHandle(pointer);
}
- }
- else
- {
- if (_index < 0)
+ else
{
- ((OwnedMemory<T>)_object).Retain();
- memoryHandle = new MemoryHandle((OwnedMemory<T>)_object);
+ GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
+ void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index);
+ return new MemoryHandle(pointer, handle);
}
}
- return memoryHandle;
+ return default;
}
/// <summary>
diff --git a/src/System.Private.CoreLib/shared/System/ReadOnlySpan.Fast.cs b/src/System.Private.CoreLib/shared/System/ReadOnlySpan.Fast.cs
index 9bf3f211a..4fb039a0f 100644
--- a/src/System.Private.CoreLib/shared/System/ReadOnlySpan.Fast.cs
+++ b/src/System.Private.CoreLib/shared/System/ReadOnlySpan.Fast.cs
@@ -2,10 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
+using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute;
+using EditorBrowsableState = System.ComponentModel.EditorBrowsableState;
using Internal.Runtime.CompilerServices;
#pragma warning disable 0809 //warning CS0809: Obsolete member 'Span<T>.Equals(object)' overrides non-obsolete member 'object.Equals(object)'
@@ -22,8 +23,6 @@ namespace System
/// ReadOnlySpan represents a contiguous region of arbitrary memory. Unlike arrays, it can point to either managed
/// or native memory, or to memory allocated on the stack. It is type- and memory-safe.
/// </summary>
- [DebuggerTypeProxy(typeof(SpanDebugView<>))]
- [DebuggerDisplay("{ToString(),raw}")]
[NonVersionable]
public readonly ref partial struct ReadOnlySpan<T>
{
@@ -150,6 +149,13 @@ namespace System
}
/// <summary>
+ /// Returns a reference to the 0th element of the Span. If the Span is empty, returns null reference.
+ /// It can be used for pinning and is required to support the use of span within a fixed statement.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public unsafe ref readonly T GetPinnableReference() => ref (_length != 0) ? ref _pointer.Value : ref Unsafe.AsRef<T>(null);
+
+ /// <summary>
/// Copies the contents of this read-only span into destination span. If the source
/// and destinations overlap, this method behaves as if the original values in
/// a temporary location before the destination is overwritten.
@@ -159,6 +165,7 @@ namespace System
/// Thrown when the destination Span is shorter than the source Span.
/// </exception>
/// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyTo(Span<T> destination)
{
// Using "if (!TryCopyTo(...))" results in two branches: one for the length
@@ -204,7 +211,7 @@ namespace System
/// <summary>
/// For <see cref="ReadOnlySpan{Char}"/>, returns a new instance of string that represents the characters pointed to by the span.
- /// Otherwise, returns a <see cref="String"/> with the name of the type and the number of elements.
+ /// Otherwise, returns a <see cref="string"/> with the name of the type and the number of elements.
/// </summary>
public override string ToString()
{
diff --git a/src/System.Private.CoreLib/shared/System/ReadOnlySpan.cs b/src/System.Private.CoreLib/shared/System/ReadOnlySpan.cs
index 906a3c431..17b7134e2 100644
--- a/src/System.Private.CoreLib/shared/System/ReadOnlySpan.cs
+++ b/src/System.Private.CoreLib/shared/System/ReadOnlySpan.cs
@@ -5,9 +5,8 @@
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
-#if !FEATURE_PORTABLE_SPAN
+
using System.Runtime.Versioning;
-#endif // !FEATURE_PORTABLE_SPAN
#pragma warning disable 0809 //warning CS0809: Obsolete member 'Span<T>.Equals(object)' overrides non-obsolete member 'object.Equals(object)'
@@ -26,9 +25,7 @@ namespace System
/// </summary>
public int Length
{
-#if !FEATURE_PORTABLE_SPAN
[NonVersionable]
-#endif // !FEATURE_PORTABLE_SPAN
get
{
return _length;
@@ -40,12 +37,11 @@ namespace System
/// </summary>
public bool IsEmpty
{
-#if !FEATURE_PORTABLE_SPAN
[NonVersionable]
-#endif // !FEATURE_PORTABLE_SPAN
get
{
- return _length == 0;
+ // Workaround for https://github.com/dotnet/coreclr/issues/19620
+ return 0 >= (uint)_length;
}
}
/// <summary>
@@ -88,13 +84,13 @@ namespace System
/// <summary>
/// Defines an implicit conversion of a <see cref="ArraySegment{T}"/> to a <see cref="ReadOnlySpan{T}"/>
/// </summary>
- public static implicit operator ReadOnlySpan<T>(ArraySegment<T> arraySegment)
- => new ReadOnlySpan<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
+ public static implicit operator ReadOnlySpan<T>(ArraySegment<T> segment)
+ => new ReadOnlySpan<T>(segment.Array, segment.Offset, segment.Count);
/// <summary>
/// Returns a 0-length read-only span whose base is the null pointer.
/// </summary>
- public static ReadOnlySpan<T> Empty => default(ReadOnlySpan<T>);
+ public static ReadOnlySpan<T> Empty => default;
/// <summary>Gets an enumerator for this span.</summary>
public Enumerator GetEnumerator() => new Enumerator(this);
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs b/src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs
index 7280869c0..f22c8c40e 100644
--- a/src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Assembly.cs
@@ -141,7 +141,7 @@ namespace System.Reflection
Returns true if the assembly was loaded from the global assembly cache.
*/
public virtual bool GlobalAssemblyCache { get { throw NotImplemented.ByDesign; } }
- public virtual Int64 HostContext { get { throw NotImplemented.ByDesign; } }
+ public virtual long HostContext { get { throw NotImplemented.ByDesign; } }
public override bool Equals(object o) => base.Equals(o);
public override int GetHashCode() => base.GetHashCode();
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyNameFormatter.cs b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyNameFormatter.cs
index 716afb045..90ccd1fe5 100644
--- a/src/System.Private.CoreLib/shared/System/Reflection/AssemblyNameFormatter.cs
+++ b/src/System.Private.CoreLib/shared/System/Reflection/AssemblyNameFormatter.cs
@@ -111,8 +111,7 @@ namespace System.Reflection
continue;
if ((s.Length - i) < escapeReplacement.Length)
continue;
- string prefix = s.Substring(i, escapeReplacement.Length);
- if (prefix == escapeReplacement)
+ if (s.AsSpan(i, escapeReplacement.Length).SequenceEqual(escapeReplacement))
{
sb.Append('\\');
sb.Append(kv.Key);
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/AssemblyBuilderAccess.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/AssemblyBuilderAccess.cs
new file mode 100644
index 000000000..b09696040
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/AssemblyBuilderAccess.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+// This enumeration defines the access modes for a dynamic assembly.
+// EE uses these enum values..look for m_dwDynamicAssemblyAccess in Assembly.hpp
+
+namespace System.Reflection.Emit
+{
+ [Flags]
+ public enum AssemblyBuilderAccess
+ {
+ Run = 1,
+ RunAndCollect = 8 | Run
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/FlowControl.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/FlowControl.cs
new file mode 100644
index 000000000..8905a7f1d
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/FlowControl.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Enumeration: FlowControl
+**
+** Purpose: Exposes FlowControl Attribute of IL.
+**
+** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND!
+** See $(RepoRoot)\src\inc\OpCodeGen.pl for more information.**
+==============================================================*/
+
+using System;
+
+namespace System.Reflection.Emit
+{
+ public enum FlowControl
+ {
+ Branch = 0,
+ Break = 1,
+ Call = 2,
+ Cond_Branch = 3,
+ Meta = 4,
+ Next = 5,
+ [Obsolete("This API has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
+ Phi = 6,
+ Return = 7,
+ Throw = 8,
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/Label.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/Label.cs
new file mode 100644
index 000000000..e49d471a9
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/Label.cs
@@ -0,0 +1,75 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+**
+** Purpose: Represents a Label to the ILGenerator class.
+**
+**
+===========================================================*/
+
+using System;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+namespace System.Reflection.Emit
+{
+ // The Label class is an opaque representation of a label used by the
+ // ILGenerator class. The token is used to mark where labels occur in the IL
+ // stream and then the necessary offsets are put back in the code when the ILGenerator
+ // is passed to the MethodWriter.
+ // Labels are created by using ILGenerator.CreateLabel and their position is set
+ // by using ILGenerator.MarkLabel.
+ public struct Label
+ {
+ internal int m_label;
+
+ //public Label() {
+ // m_label=0;
+ //}
+
+ internal Label(int label)
+ {
+ m_label = label;
+ }
+
+ internal int GetLabelValue()
+ {
+ return m_label;
+ }
+
+ public override int GetHashCode()
+ {
+ return m_label;
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is Label)
+ return Equals((Label)obj);
+ else
+ return false;
+ }
+
+ public bool Equals(Label obj)
+ {
+ return obj.m_label == m_label;
+ }
+
+ public static bool operator ==(Label a, Label b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(Label a, Label b)
+ {
+ return !(a == b);
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodeType.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodeType.cs
new file mode 100644
index 000000000..17435c576
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodeType.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Enumeration: OpCodeType
+**
+** Purpose: Exposes OpCodeType Attribute of IL.
+**
+** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND!
+** See $(RepoRoot)\src\inc\OpCodeGen.pl for more information.**
+==============================================================*/
+
+using System;
+
+namespace System.Reflection.Emit
+{
+ public enum OpCodeType
+ {
+ [Obsolete("This API has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
+ Annotation = 0,
+ Macro = 1,
+ Nternal = 2,
+ Objmodel = 3,
+ Prefix = 4,
+ Primitive = 5,
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodes.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodes.cs
new file mode 100644
index 000000000..7690005e2
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/OpCodes.cs
@@ -0,0 +1,2539 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Reflection.Emit
+{
+ //
+ // Internal enums for opcode values. Note that the value names are used to construct
+ // publicly visible ilasm-compatible opcode names, so their exact form is important!
+ //
+ internal enum OpCodeValues
+ {
+ Nop = 0x00,
+ Break = 0x01,
+ Ldarg_0 = 0x02,
+ Ldarg_1 = 0x03,
+ Ldarg_2 = 0x04,
+ Ldarg_3 = 0x05,
+ Ldloc_0 = 0x06,
+ Ldloc_1 = 0x07,
+ Ldloc_2 = 0x08,
+ Ldloc_3 = 0x09,
+ Stloc_0 = 0x0a,
+ Stloc_1 = 0x0b,
+ Stloc_2 = 0x0c,
+ Stloc_3 = 0x0d,
+ Ldarg_S = 0x0e,
+ Ldarga_S = 0x0f,
+ Starg_S = 0x10,
+ Ldloc_S = 0x11,
+ Ldloca_S = 0x12,
+ Stloc_S = 0x13,
+ Ldnull = 0x14,
+ Ldc_I4_M1 = 0x15,
+ Ldc_I4_0 = 0x16,
+ Ldc_I4_1 = 0x17,
+ Ldc_I4_2 = 0x18,
+ Ldc_I4_3 = 0x19,
+ Ldc_I4_4 = 0x1a,
+ Ldc_I4_5 = 0x1b,
+ Ldc_I4_6 = 0x1c,
+ Ldc_I4_7 = 0x1d,
+ Ldc_I4_8 = 0x1e,
+ Ldc_I4_S = 0x1f,
+ Ldc_I4 = 0x20,
+ Ldc_I8 = 0x21,
+ Ldc_R4 = 0x22,
+ Ldc_R8 = 0x23,
+ Dup = 0x25,
+ Pop = 0x26,
+ Jmp = 0x27,
+ Call = 0x28,
+ Calli = 0x29,
+ Ret = 0x2a,
+ Br_S = 0x2b,
+ Brfalse_S = 0x2c,
+ Brtrue_S = 0x2d,
+ Beq_S = 0x2e,
+ Bge_S = 0x2f,
+ Bgt_S = 0x30,
+ Ble_S = 0x31,
+ Blt_S = 0x32,
+ Bne_Un_S = 0x33,
+ Bge_Un_S = 0x34,
+ Bgt_Un_S = 0x35,
+ Ble_Un_S = 0x36,
+ Blt_Un_S = 0x37,
+ Br = 0x38,
+ Brfalse = 0x39,
+ Brtrue = 0x3a,
+ Beq = 0x3b,
+ Bge = 0x3c,
+ Bgt = 0x3d,
+ Ble = 0x3e,
+ Blt = 0x3f,
+ Bne_Un = 0x40,
+ Bge_Un = 0x41,
+ Bgt_Un = 0x42,
+ Ble_Un = 0x43,
+ Blt_Un = 0x44,
+ Switch = 0x45,
+ Ldind_I1 = 0x46,
+ Ldind_U1 = 0x47,
+ Ldind_I2 = 0x48,
+ Ldind_U2 = 0x49,
+ Ldind_I4 = 0x4a,
+ Ldind_U4 = 0x4b,
+ Ldind_I8 = 0x4c,
+ Ldind_I = 0x4d,
+ Ldind_R4 = 0x4e,
+ Ldind_R8 = 0x4f,
+ Ldind_Ref = 0x50,
+ Stind_Ref = 0x51,
+ Stind_I1 = 0x52,
+ Stind_I2 = 0x53,
+ Stind_I4 = 0x54,
+ Stind_I8 = 0x55,
+ Stind_R4 = 0x56,
+ Stind_R8 = 0x57,
+ Add = 0x58,
+ Sub = 0x59,
+ Mul = 0x5a,
+ Div = 0x5b,
+ Div_Un = 0x5c,
+ Rem = 0x5d,
+ Rem_Un = 0x5e,
+ And = 0x5f,
+ Or = 0x60,
+ Xor = 0x61,
+ Shl = 0x62,
+ Shr = 0x63,
+ Shr_Un = 0x64,
+ Neg = 0x65,
+ Not = 0x66,
+ Conv_I1 = 0x67,
+ Conv_I2 = 0x68,
+ Conv_I4 = 0x69,
+ Conv_I8 = 0x6a,
+ Conv_R4 = 0x6b,
+ Conv_R8 = 0x6c,
+ Conv_U4 = 0x6d,
+ Conv_U8 = 0x6e,
+ Callvirt = 0x6f,
+ Cpobj = 0x70,
+ Ldobj = 0x71,
+ Ldstr = 0x72,
+ Newobj = 0x73,
+ Castclass = 0x74,
+ Isinst = 0x75,
+ Conv_R_Un = 0x76,
+ Unbox = 0x79,
+ Throw = 0x7a,
+ Ldfld = 0x7b,
+ Ldflda = 0x7c,
+ Stfld = 0x7d,
+ Ldsfld = 0x7e,
+ Ldsflda = 0x7f,
+ Stsfld = 0x80,
+ Stobj = 0x81,
+ Conv_Ovf_I1_Un = 0x82,
+ Conv_Ovf_I2_Un = 0x83,
+ Conv_Ovf_I4_Un = 0x84,
+ Conv_Ovf_I8_Un = 0x85,
+ Conv_Ovf_U1_Un = 0x86,
+ Conv_Ovf_U2_Un = 0x87,
+ Conv_Ovf_U4_Un = 0x88,
+ Conv_Ovf_U8_Un = 0x89,
+ Conv_Ovf_I_Un = 0x8a,
+ Conv_Ovf_U_Un = 0x8b,
+ Box = 0x8c,
+ Newarr = 0x8d,
+ Ldlen = 0x8e,
+ Ldelema = 0x8f,
+ Ldelem_I1 = 0x90,
+ Ldelem_U1 = 0x91,
+ Ldelem_I2 = 0x92,
+ Ldelem_U2 = 0x93,
+ Ldelem_I4 = 0x94,
+ Ldelem_U4 = 0x95,
+ Ldelem_I8 = 0x96,
+ Ldelem_I = 0x97,
+ Ldelem_R4 = 0x98,
+ Ldelem_R8 = 0x99,
+ Ldelem_Ref = 0x9a,
+ Stelem_I = 0x9b,
+ Stelem_I1 = 0x9c,
+ Stelem_I2 = 0x9d,
+ Stelem_I4 = 0x9e,
+ Stelem_I8 = 0x9f,
+ Stelem_R4 = 0xa0,
+ Stelem_R8 = 0xa1,
+ Stelem_Ref = 0xa2,
+ Ldelem = 0xa3,
+ Stelem = 0xa4,
+ Unbox_Any = 0xa5,
+ Conv_Ovf_I1 = 0xb3,
+ Conv_Ovf_U1 = 0xb4,
+ Conv_Ovf_I2 = 0xb5,
+ Conv_Ovf_U2 = 0xb6,
+ Conv_Ovf_I4 = 0xb7,
+ Conv_Ovf_U4 = 0xb8,
+ Conv_Ovf_I8 = 0xb9,
+ Conv_Ovf_U8 = 0xba,
+ Refanyval = 0xc2,
+ Ckfinite = 0xc3,
+ Mkrefany = 0xc6,
+ Ldtoken = 0xd0,
+ Conv_U2 = 0xd1,
+ Conv_U1 = 0xd2,
+ Conv_I = 0xd3,
+ Conv_Ovf_I = 0xd4,
+ Conv_Ovf_U = 0xd5,
+ Add_Ovf = 0xd6,
+ Add_Ovf_Un = 0xd7,
+ Mul_Ovf = 0xd8,
+ Mul_Ovf_Un = 0xd9,
+ Sub_Ovf = 0xda,
+ Sub_Ovf_Un = 0xdb,
+ Endfinally = 0xdc,
+ Leave = 0xdd,
+ Leave_S = 0xde,
+ Stind_I = 0xdf,
+ Conv_U = 0xe0,
+ Prefix7 = 0xf8,
+ Prefix6 = 0xf9,
+ Prefix5 = 0xfa,
+ Prefix4 = 0xfb,
+ Prefix3 = 0xfc,
+ Prefix2 = 0xfd,
+ Prefix1 = 0xfe,
+ Prefixref = 0xff,
+ Arglist = 0xfe00,
+ Ceq = 0xfe01,
+ Cgt = 0xfe02,
+ Cgt_Un = 0xfe03,
+ Clt = 0xfe04,
+ Clt_Un = 0xfe05,
+ Ldftn = 0xfe06,
+ Ldvirtftn = 0xfe07,
+ Ldarg = 0xfe09,
+ Ldarga = 0xfe0a,
+ Starg = 0xfe0b,
+ Ldloc = 0xfe0c,
+ Ldloca = 0xfe0d,
+ Stloc = 0xfe0e,
+ Localloc = 0xfe0f,
+ Endfilter = 0xfe11,
+ Unaligned_ = 0xfe12,
+ Volatile_ = 0xfe13,
+ Tail_ = 0xfe14,
+ Initobj = 0xfe15,
+ Constrained_ = 0xfe16,
+ Cpblk = 0xfe17,
+ Initblk = 0xfe18,
+ Rethrow = 0xfe1a,
+ Sizeof = 0xfe1c,
+ Refanytype = 0xfe1d,
+ Readonly_ = 0xfe1e,
+ // If you add more opcodes here, modify OpCode.Name to handle them correctly
+ }
+
+ /// <summary>
+ /// <para>
+ /// The IL instruction opcodes supported by the
+ /// runtime. The IL Instruction Specification describes each
+ /// Opcode.
+ /// </para>
+ /// </summary>
+ /// <seealso topic='IL Instruction Set Specification'/>
+ public class OpCodes
+ {
+ private OpCodes()
+ {
+ }
+
+ public static readonly OpCode Nop = new OpCode(OpCodeValues.Nop,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Break = new OpCode(OpCodeValues.Break,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Break << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarg_0 = new OpCode(OpCodeValues.Ldarg_0,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarg_1 = new OpCode(OpCodeValues.Ldarg_1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarg_2 = new OpCode(OpCodeValues.Ldarg_2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarg_3 = new OpCode(OpCodeValues.Ldarg_3,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloc_0 = new OpCode(OpCodeValues.Ldloc_0,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloc_1 = new OpCode(OpCodeValues.Ldloc_1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloc_2 = new OpCode(OpCodeValues.Ldloc_2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloc_3 = new OpCode(OpCodeValues.Ldloc_3,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stloc_0 = new OpCode(OpCodeValues.Stloc_0,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stloc_1 = new OpCode(OpCodeValues.Stloc_1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stloc_2 = new OpCode(OpCodeValues.Stloc_2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stloc_3 = new OpCode(OpCodeValues.Stloc_3,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarg_S = new OpCode(OpCodeValues.Ldarg_S,
+ ((int)OperandType.ShortInlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarga_S = new OpCode(OpCodeValues.Ldarga_S,
+ ((int)OperandType.ShortInlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Starg_S = new OpCode(OpCodeValues.Starg_S,
+ ((int)OperandType.ShortInlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloc_S = new OpCode(OpCodeValues.Ldloc_S,
+ ((int)OperandType.ShortInlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloca_S = new OpCode(OpCodeValues.Ldloca_S,
+ ((int)OperandType.ShortInlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stloc_S = new OpCode(OpCodeValues.Stloc_S,
+ ((int)OperandType.ShortInlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldnull = new OpCode(OpCodeValues.Ldnull,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_M1 = new OpCode(OpCodeValues.Ldc_I4_M1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_0 = new OpCode(OpCodeValues.Ldc_I4_0,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_1 = new OpCode(OpCodeValues.Ldc_I4_1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_2 = new OpCode(OpCodeValues.Ldc_I4_2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_3 = new OpCode(OpCodeValues.Ldc_I4_3,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_4 = new OpCode(OpCodeValues.Ldc_I4_4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_5 = new OpCode(OpCodeValues.Ldc_I4_5,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_6 = new OpCode(OpCodeValues.Ldc_I4_6,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_7 = new OpCode(OpCodeValues.Ldc_I4_7,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_8 = new OpCode(OpCodeValues.Ldc_I4_8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_S = new OpCode(OpCodeValues.Ldc_I4_S,
+ ((int)OperandType.ShortInlineI) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4 = new OpCode(OpCodeValues.Ldc_I4,
+ ((int)OperandType.InlineI) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I8 = new OpCode(OpCodeValues.Ldc_I8,
+ ((int)OperandType.InlineI8) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_R4 = new OpCode(OpCodeValues.Ldc_R4,
+ ((int)OperandType.ShortInlineR) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr4 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_R8 = new OpCode(OpCodeValues.Ldc_R8,
+ ((int)OperandType.InlineR) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Dup = new OpCode(OpCodeValues.Dup,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1_push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Pop = new OpCode(OpCodeValues.Pop,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Jmp = new OpCode(OpCodeValues.Jmp,
+ ((int)OperandType.InlineMethod) |
+ ((int)FlowControl.Call << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Call = new OpCode(OpCodeValues.Call,
+ ((int)OperandType.InlineMethod) |
+ ((int)FlowControl.Call << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Varpop << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Varpush << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Calli = new OpCode(OpCodeValues.Calli,
+ ((int)OperandType.InlineSig) |
+ ((int)FlowControl.Call << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Varpop << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Varpush << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ret = new OpCode(OpCodeValues.Ret,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Return << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Varpop << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Br_S = new OpCode(OpCodeValues.Br_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Brfalse_S = new OpCode(OpCodeValues.Brfalse_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Brtrue_S = new OpCode(OpCodeValues.Brtrue_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Beq_S = new OpCode(OpCodeValues.Beq_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bge_S = new OpCode(OpCodeValues.Bge_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bgt_S = new OpCode(OpCodeValues.Bgt_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ble_S = new OpCode(OpCodeValues.Ble_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Blt_S = new OpCode(OpCodeValues.Blt_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bne_Un_S = new OpCode(OpCodeValues.Bne_Un_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bge_Un_S = new OpCode(OpCodeValues.Bge_Un_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bgt_Un_S = new OpCode(OpCodeValues.Bgt_Un_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ble_Un_S = new OpCode(OpCodeValues.Ble_Un_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Blt_Un_S = new OpCode(OpCodeValues.Blt_Un_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Br = new OpCode(OpCodeValues.Br,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Brfalse = new OpCode(OpCodeValues.Brfalse,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Brtrue = new OpCode(OpCodeValues.Brtrue,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Beq = new OpCode(OpCodeValues.Beq,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bge = new OpCode(OpCodeValues.Bge,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bgt = new OpCode(OpCodeValues.Bgt,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ble = new OpCode(OpCodeValues.Ble,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Blt = new OpCode(OpCodeValues.Blt,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bne_Un = new OpCode(OpCodeValues.Bne_Un,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bge_Un = new OpCode(OpCodeValues.Bge_Un,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bgt_Un = new OpCode(OpCodeValues.Bgt_Un,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ble_Un = new OpCode(OpCodeValues.Ble_Un,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Blt_Un = new OpCode(OpCodeValues.Blt_Un,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Switch = new OpCode(OpCodeValues.Switch,
+ ((int)OperandType.InlineSwitch) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_I1 = new OpCode(OpCodeValues.Ldind_I1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_U1 = new OpCode(OpCodeValues.Ldind_U1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_I2 = new OpCode(OpCodeValues.Ldind_I2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_U2 = new OpCode(OpCodeValues.Ldind_U2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_I4 = new OpCode(OpCodeValues.Ldind_I4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_U4 = new OpCode(OpCodeValues.Ldind_U4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_I8 = new OpCode(OpCodeValues.Ldind_I8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_I = new OpCode(OpCodeValues.Ldind_I,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_R4 = new OpCode(OpCodeValues.Ldind_R4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr4 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_R8 = new OpCode(OpCodeValues.Ldind_R8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_Ref = new OpCode(OpCodeValues.Ldind_Ref,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_Ref = new OpCode(OpCodeValues.Stind_Ref,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_I1 = new OpCode(OpCodeValues.Stind_I1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_I2 = new OpCode(OpCodeValues.Stind_I2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_I4 = new OpCode(OpCodeValues.Stind_I4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_I8 = new OpCode(OpCodeValues.Stind_I8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi8 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_R4 = new OpCode(OpCodeValues.Stind_R4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popr4 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_R8 = new OpCode(OpCodeValues.Stind_R8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popr8 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Add = new OpCode(OpCodeValues.Add,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Sub = new OpCode(OpCodeValues.Sub,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Mul = new OpCode(OpCodeValues.Mul,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Div = new OpCode(OpCodeValues.Div,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Div_Un = new OpCode(OpCodeValues.Div_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Rem = new OpCode(OpCodeValues.Rem,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Rem_Un = new OpCode(OpCodeValues.Rem_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode And = new OpCode(OpCodeValues.And,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Or = new OpCode(OpCodeValues.Or,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Xor = new OpCode(OpCodeValues.Xor,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Shl = new OpCode(OpCodeValues.Shl,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Shr = new OpCode(OpCodeValues.Shr,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Shr_Un = new OpCode(OpCodeValues.Shr_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Neg = new OpCode(OpCodeValues.Neg,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Not = new OpCode(OpCodeValues.Not,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_I1 = new OpCode(OpCodeValues.Conv_I1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_I2 = new OpCode(OpCodeValues.Conv_I2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_I4 = new OpCode(OpCodeValues.Conv_I4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_I8 = new OpCode(OpCodeValues.Conv_I8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_R4 = new OpCode(OpCodeValues.Conv_R4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr4 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_R8 = new OpCode(OpCodeValues.Conv_R8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_U4 = new OpCode(OpCodeValues.Conv_U4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_U8 = new OpCode(OpCodeValues.Conv_U8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Callvirt = new OpCode(OpCodeValues.Callvirt,
+ ((int)OperandType.InlineMethod) |
+ ((int)FlowControl.Call << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Varpop << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Varpush << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Cpobj = new OpCode(OpCodeValues.Cpobj,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldobj = new OpCode(OpCodeValues.Ldobj,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldstr = new OpCode(OpCodeValues.Ldstr,
+ ((int)OperandType.InlineString) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Newobj = new OpCode(OpCodeValues.Newobj,
+ ((int)OperandType.InlineMethod) |
+ ((int)FlowControl.Call << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Varpop << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Castclass = new OpCode(OpCodeValues.Castclass,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Isinst = new OpCode(OpCodeValues.Isinst,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_R_Un = new OpCode(OpCodeValues.Conv_R_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Unbox = new OpCode(OpCodeValues.Unbox,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Throw = new OpCode(OpCodeValues.Throw,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Throw << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldfld = new OpCode(OpCodeValues.Ldfld,
+ ((int)OperandType.InlineField) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldflda = new OpCode(OpCodeValues.Ldflda,
+ ((int)OperandType.InlineField) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stfld = new OpCode(OpCodeValues.Stfld,
+ ((int)OperandType.InlineField) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldsfld = new OpCode(OpCodeValues.Ldsfld,
+ ((int)OperandType.InlineField) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldsflda = new OpCode(OpCodeValues.Ldsflda,
+ ((int)OperandType.InlineField) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stsfld = new OpCode(OpCodeValues.Stsfld,
+ ((int)OperandType.InlineField) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stobj = new OpCode(OpCodeValues.Stobj,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I1_Un = new OpCode(OpCodeValues.Conv_Ovf_I1_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I2_Un = new OpCode(OpCodeValues.Conv_Ovf_I2_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I4_Un = new OpCode(OpCodeValues.Conv_Ovf_I4_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I8_Un = new OpCode(OpCodeValues.Conv_Ovf_I8_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U1_Un = new OpCode(OpCodeValues.Conv_Ovf_U1_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U2_Un = new OpCode(OpCodeValues.Conv_Ovf_U2_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U4_Un = new OpCode(OpCodeValues.Conv_Ovf_U4_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U8_Un = new OpCode(OpCodeValues.Conv_Ovf_U8_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I_Un = new OpCode(OpCodeValues.Conv_Ovf_I_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U_Un = new OpCode(OpCodeValues.Conv_Ovf_U_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Box = new OpCode(OpCodeValues.Box,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Newarr = new OpCode(OpCodeValues.Newarr,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldlen = new OpCode(OpCodeValues.Ldlen,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelema = new OpCode(OpCodeValues.Ldelema,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_I1 = new OpCode(OpCodeValues.Ldelem_I1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_U1 = new OpCode(OpCodeValues.Ldelem_U1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_I2 = new OpCode(OpCodeValues.Ldelem_I2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_U2 = new OpCode(OpCodeValues.Ldelem_U2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_I4 = new OpCode(OpCodeValues.Ldelem_I4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_U4 = new OpCode(OpCodeValues.Ldelem_U4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_I8 = new OpCode(OpCodeValues.Ldelem_I8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_I = new OpCode(OpCodeValues.Ldelem_I,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_R4 = new OpCode(OpCodeValues.Ldelem_R4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr4 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_R8 = new OpCode(OpCodeValues.Ldelem_R8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_Ref = new OpCode(OpCodeValues.Ldelem_Ref,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_I = new OpCode(OpCodeValues.Stelem_I,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_I1 = new OpCode(OpCodeValues.Stelem_I1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_I2 = new OpCode(OpCodeValues.Stelem_I2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_I4 = new OpCode(OpCodeValues.Stelem_I4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_I8 = new OpCode(OpCodeValues.Stelem_I8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popi8 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_R4 = new OpCode(OpCodeValues.Stelem_R4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popr4 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_R8 = new OpCode(OpCodeValues.Stelem_R8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popr8 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_Ref = new OpCode(OpCodeValues.Stelem_Ref,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem = new OpCode(OpCodeValues.Ldelem,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem = new OpCode(OpCodeValues.Stelem,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Unbox_Any = new OpCode(OpCodeValues.Unbox_Any,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I1 = new OpCode(OpCodeValues.Conv_Ovf_I1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U1 = new OpCode(OpCodeValues.Conv_Ovf_U1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I2 = new OpCode(OpCodeValues.Conv_Ovf_I2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U2 = new OpCode(OpCodeValues.Conv_Ovf_U2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I4 = new OpCode(OpCodeValues.Conv_Ovf_I4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U4 = new OpCode(OpCodeValues.Conv_Ovf_U4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I8 = new OpCode(OpCodeValues.Conv_Ovf_I8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U8 = new OpCode(OpCodeValues.Conv_Ovf_U8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Refanyval = new OpCode(OpCodeValues.Refanyval,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ckfinite = new OpCode(OpCodeValues.Ckfinite,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Mkrefany = new OpCode(OpCodeValues.Mkrefany,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldtoken = new OpCode(OpCodeValues.Ldtoken,
+ ((int)OperandType.InlineTok) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_U2 = new OpCode(OpCodeValues.Conv_U2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_U1 = new OpCode(OpCodeValues.Conv_U1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_I = new OpCode(OpCodeValues.Conv_I,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I = new OpCode(OpCodeValues.Conv_Ovf_I,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U = new OpCode(OpCodeValues.Conv_Ovf_U,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Add_Ovf = new OpCode(OpCodeValues.Add_Ovf,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Add_Ovf_Un = new OpCode(OpCodeValues.Add_Ovf_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Mul_Ovf = new OpCode(OpCodeValues.Mul_Ovf,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Mul_Ovf_Un = new OpCode(OpCodeValues.Mul_Ovf_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Sub_Ovf = new OpCode(OpCodeValues.Sub_Ovf,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Sub_Ovf_Un = new OpCode(OpCodeValues.Sub_Ovf_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Endfinally = new OpCode(OpCodeValues.Endfinally,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Return << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Leave = new OpCode(OpCodeValues.Leave,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Leave_S = new OpCode(OpCodeValues.Leave_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_I = new OpCode(OpCodeValues.Stind_I,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_U = new OpCode(OpCodeValues.Conv_U,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix7 = new OpCode(OpCodeValues.Prefix7,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix6 = new OpCode(OpCodeValues.Prefix6,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix5 = new OpCode(OpCodeValues.Prefix5,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix4 = new OpCode(OpCodeValues.Prefix4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix3 = new OpCode(OpCodeValues.Prefix3,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix2 = new OpCode(OpCodeValues.Prefix2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix1 = new OpCode(OpCodeValues.Prefix1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefixref = new OpCode(OpCodeValues.Prefixref,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Arglist = new OpCode(OpCodeValues.Arglist,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ceq = new OpCode(OpCodeValues.Ceq,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Cgt = new OpCode(OpCodeValues.Cgt,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Cgt_Un = new OpCode(OpCodeValues.Cgt_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Clt = new OpCode(OpCodeValues.Clt,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Clt_Un = new OpCode(OpCodeValues.Clt_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldftn = new OpCode(OpCodeValues.Ldftn,
+ ((int)OperandType.InlineMethod) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldvirtftn = new OpCode(OpCodeValues.Ldvirtftn,
+ ((int)OperandType.InlineMethod) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarg = new OpCode(OpCodeValues.Ldarg,
+ ((int)OperandType.InlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarga = new OpCode(OpCodeValues.Ldarga,
+ ((int)OperandType.InlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Starg = new OpCode(OpCodeValues.Starg,
+ ((int)OperandType.InlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloc = new OpCode(OpCodeValues.Ldloc,
+ ((int)OperandType.InlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloca = new OpCode(OpCodeValues.Ldloca,
+ ((int)OperandType.InlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stloc = new OpCode(OpCodeValues.Stloc,
+ ((int)OperandType.InlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Localloc = new OpCode(OpCodeValues.Localloc,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Endfilter = new OpCode(OpCodeValues.Endfilter,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Return << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Unaligned = new OpCode(OpCodeValues.Unaligned_,
+ ((int)OperandType.ShortInlineI) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Prefix << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Volatile = new OpCode(OpCodeValues.Volatile_,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Prefix << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Tailcall = new OpCode(OpCodeValues.Tail_,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Prefix << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Initobj = new OpCode(OpCodeValues.Initobj,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Constrained = new OpCode(OpCodeValues.Constrained_,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Prefix << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Cpblk = new OpCode(OpCodeValues.Cpblk,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Initblk = new OpCode(OpCodeValues.Initblk,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Rethrow = new OpCode(OpCodeValues.Rethrow,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Throw << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Sizeof = new OpCode(OpCodeValues.Sizeof,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Refanytype = new OpCode(OpCodeValues.Refanytype,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Readonly = new OpCode(OpCodeValues.Readonly_,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Prefix << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+
+ public static bool TakesSingleByteArgument(OpCode inst)
+ {
+ switch (inst.OperandType)
+ {
+ case OperandType.ShortInlineBrTarget:
+ case OperandType.ShortInlineI:
+ case OperandType.ShortInlineVar:
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/Opcode.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/Opcode.cs
new file mode 100644
index 000000000..1a144fcf4
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/Opcode.cs
@@ -0,0 +1,191 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Threading;
+
+namespace System.Reflection.Emit
+{
+ public struct OpCode
+ {
+ //
+ // Use packed bitfield for flags to avoid code bloat
+ //
+
+ internal const int OperandTypeMask = 0x1F; // 000000000000000000000000000XXXXX
+
+ internal const int FlowControlShift = 5; // 00000000000000000000000XXXX00000
+ internal const int FlowControlMask = 0x0F;
+
+ internal const int OpCodeTypeShift = 9; // 00000000000000000000XXX000000000
+ internal const int OpCodeTypeMask = 0x07;
+
+ internal const int StackBehaviourPopShift = 12; // 000000000000000XXXXX000000000000
+ internal const int StackBehaviourPushShift = 17; // 0000000000XXXXX00000000000000000
+ internal const int StackBehaviourMask = 0x1F;
+
+ internal const int SizeShift = 22; // 00000000XX0000000000000000000000
+ internal const int SizeMask = 0x03;
+
+ internal const int EndsUncondJmpBlkFlag = 0x01000000; // 0000000X000000000000000000000000
+
+ // unused // 0000XXX0000000000000000000000000
+
+ internal const int StackChangeShift = 28; // XXXX0000000000000000000000000000
+
+ private OpCodeValues m_value;
+ private int m_flags;
+
+ internal OpCode(OpCodeValues value, int flags)
+ {
+ m_value = value;
+ m_flags = flags;
+ }
+
+ internal bool EndsUncondJmpBlk()
+ {
+ return (m_flags & EndsUncondJmpBlkFlag) != 0;
+ }
+
+ internal int StackChange()
+ {
+ return (m_flags >> StackChangeShift);
+ }
+
+ public OperandType OperandType
+ {
+ get
+ {
+ return (OperandType)(m_flags & OperandTypeMask);
+ }
+ }
+
+ public FlowControl FlowControl
+ {
+ get
+ {
+ return (FlowControl)((m_flags >> FlowControlShift) & FlowControlMask);
+ }
+ }
+
+ public OpCodeType OpCodeType
+ {
+ get
+ {
+ return (OpCodeType)((m_flags >> OpCodeTypeShift) & OpCodeTypeMask);
+ }
+ }
+
+ public StackBehaviour StackBehaviourPop
+ {
+ get
+ {
+ return (StackBehaviour)((m_flags >> StackBehaviourPopShift) & StackBehaviourMask);
+ }
+ }
+
+ public StackBehaviour StackBehaviourPush
+ {
+ get
+ {
+ return (StackBehaviour)((m_flags >> StackBehaviourPushShift) & StackBehaviourMask);
+ }
+ }
+
+ public int Size
+ {
+ get
+ {
+ return (m_flags >> SizeShift) & SizeMask;
+ }
+ }
+
+ public short Value
+ {
+ get
+ {
+ return (short)m_value;
+ }
+ }
+
+ private static volatile string[] g_nameCache;
+
+ public string Name
+ {
+ get
+ {
+ if (Size == 0)
+ return null;
+
+ // Create and cache the opcode names lazily. They should be rarely used (only for logging, etc.)
+ // Note that we do not any locks here because of we always get the same names. The last one wins.
+ string[] nameCache = g_nameCache;
+ if (nameCache == null)
+ {
+ nameCache = new string[0x11f];
+ g_nameCache = nameCache;
+ }
+
+ OpCodeValues opCodeValue = (OpCodeValues)(ushort)Value;
+
+ int idx = (int)opCodeValue;
+ if (idx > 0xFF)
+ {
+ if (idx >= 0xfe00 && idx <= 0xfe1e)
+ {
+ // Transform two byte opcode value to lower range that's suitable
+ // for array index
+ idx = 0x100 + (idx - 0xfe00);
+ }
+ else
+ {
+ // Unknown opcode
+ return null;
+ }
+ }
+
+ string name = Volatile.Read(ref nameCache[idx]);
+ if (name != null)
+ return name;
+
+ // Create ilasm style name from the enum value name.
+ name = Enum.GetName(typeof(OpCodeValues), opCodeValue).ToLowerInvariant().Replace("_", ".");
+ Volatile.Write(ref nameCache[idx], name);
+ return name;
+ }
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (obj is OpCode)
+ return Equals((OpCode)obj);
+ else
+ return false;
+ }
+
+ public bool Equals(OpCode obj)
+ {
+ return obj.Value == Value;
+ }
+
+ public static bool operator ==(OpCode a, OpCode b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(OpCode a, OpCode b)
+ {
+ return !(a == b);
+ }
+
+ public override int GetHashCode()
+ {
+ return Value;
+ }
+
+ public override string ToString()
+ {
+ return Name;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/OperandType.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/OperandType.cs
new file mode 100644
index 000000000..6257c5674
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/OperandType.cs
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Enumeration: OperandType
+**
+** Purpose: Exposes OperandType Attribute of IL.
+**
+** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND!
+** See $(RepoRoot)\src\inc\OpCodeGen.pl for more information.**
+==============================================================*/
+
+using System;
+
+namespace System.Reflection.Emit
+{
+ public enum OperandType
+ {
+ InlineBrTarget = 0,
+ InlineField = 1,
+ InlineI = 2,
+ InlineI8 = 3,
+ InlineMethod = 4,
+ InlineNone = 5,
+ [Obsolete("This API has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
+ InlinePhi = 6,
+ InlineR = 7,
+ InlineSig = 9,
+ InlineString = 10,
+ InlineSwitch = 11,
+ InlineTok = 12,
+ InlineType = 13,
+ InlineVar = 14,
+ ShortInlineBrTarget = 15,
+ ShortInlineI = 16,
+ ShortInlineR = 17,
+ ShortInlineVar = 18,
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/PEFileKinds.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/PEFileKinds.cs
new file mode 100644
index 000000000..f6606c477
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/PEFileKinds.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System;
+
+namespace System.Reflection.Emit
+{
+ // This Enum matchs the CorFieldAttr defined in CorHdr.h
+ public enum PEFileKinds
+ {
+ Dll = 0x0001,
+ ConsoleApplication = 0x0002,
+ WindowApplication = 0x0003,
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/PackingSize.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/PackingSize.cs
new file mode 100644
index 000000000..f734e1a34
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/PackingSize.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Reflection.Emit
+{
+ public enum PackingSize
+ {
+ Unspecified = 0,
+ Size1 = 1,
+ Size2 = 2,
+ Size4 = 4,
+ Size8 = 8,
+ Size16 = 16,
+ Size32 = 32,
+ Size64 = 64,
+ Size128 = 128,
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Emit/StackBehaviour.cs b/src/System.Private.CoreLib/shared/System/Reflection/Emit/StackBehaviour.cs
new file mode 100644
index 000000000..3e64b4879
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Emit/StackBehaviour.cs
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Enumeration: StackBehaviour
+**
+** Purpose: Exposes StackBehaviour Attribute of IL.
+**
+** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND!
+** See $(RepoRoot)\src\inc\OpCodeGen.pl for more information.**
+==============================================================*/
+
+using System;
+
+namespace System.Reflection.Emit
+{
+ public enum StackBehaviour
+ {
+ Pop0 = 0,
+ Pop1 = 1,
+ Pop1_pop1 = 2,
+ Popi = 3,
+ Popi_pop1 = 4,
+ Popi_popi = 5,
+ Popi_popi8 = 6,
+ Popi_popi_popi = 7,
+ Popi_popr4 = 8,
+ Popi_popr8 = 9,
+ Popref = 10,
+ Popref_pop1 = 11,
+ Popref_popi = 12,
+ Popref_popi_popi = 13,
+ Popref_popi_popi8 = 14,
+ Popref_popi_popr4 = 15,
+ Popref_popi_popr8 = 16,
+ Popref_popi_popref = 17,
+ Push0 = 18,
+ Push1 = 19,
+ Push1_push1 = 20,
+ Pushi = 21,
+ Pushi8 = 22,
+ Pushr4 = 23,
+ Pushr8 = 24,
+ Pushref = 25,
+ Varpop = 26,
+ Varpush = 27,
+ Popref_popi_pop1 = 28,
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Reflection/ExceptionHandlingClause.cs b/src/System.Private.CoreLib/shared/System/Reflection/ExceptionHandlingClause.cs
index 8598256b3..15780f11c 100644
--- a/src/System.Private.CoreLib/src/System/Reflection/ExceptionHandlingClause.cs
+++ b/src/System.Private.CoreLib/shared/System/Reflection/ExceptionHandlingClause.cs
@@ -9,17 +9,13 @@ namespace System.Reflection
public class ExceptionHandlingClause
{
protected ExceptionHandlingClause() { }
-
- // Desktop compat: These default implementations behave strangely because this class was originally
- // creatable only from the native runtime, not through subclass inheritance.
-
- public virtual Type CatchType => null;
- public virtual int FilterOffset { get { throw new InvalidOperationException(); } }
- public virtual ExceptionHandlingClauseOptions Flags => default(ExceptionHandlingClauseOptions);
- public virtual int HandlerLength => 0;
- public virtual int HandlerOffset => 0;
- public virtual int TryLength => 0;
+ public virtual ExceptionHandlingClauseOptions Flags => default;
public virtual int TryOffset => 0;
+ public virtual int TryLength => 0;
+ public virtual int HandlerOffset => 0;
+ public virtual int HandlerLength => 0;
+ public virtual int FilterOffset => throw new InvalidOperationException(SR.Arg_EHClauseNotFilter);
+ public virtual Type CatchType => null;
public override string ToString()
{
@@ -29,3 +25,4 @@ namespace System.Reflection
}
}
}
+
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/LocalVariableInfo.cs b/src/System.Private.CoreLib/shared/System/Reflection/LocalVariableInfo.cs
new file mode 100644
index 000000000..1540bde53
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Reflection/LocalVariableInfo.cs
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+
+namespace System.Reflection
+{
+ public class LocalVariableInfo
+ {
+ public virtual Type LocalType { get { Debug.Fail("type must be set!"); return null; } }
+ public virtual int LocalIndex => 0;
+ public virtual bool IsPinned => false;
+ protected LocalVariableInfo() { }
+ public override string ToString()
+ {
+ string toString = LocalType.ToString() + " (" + LocalIndex + ")";
+
+ if (IsPinned)
+ toString += " (pinned)";
+
+ return toString;
+ }
+ }
+}
+
diff --git a/src/System.Private.CoreLib/src/System/Reflection/MethodBody.cs b/src/System.Private.CoreLib/shared/System/Reflection/MethodBody.cs
index b87558573..bdf53ad12 100644
--- a/src/System.Private.CoreLib/src/System/Reflection/MethodBody.cs
+++ b/src/System.Private.CoreLib/shared/System/Reflection/MethodBody.cs
@@ -9,14 +9,12 @@ namespace System.Reflection
public class MethodBody
{
protected MethodBody() { }
-
- // Desktop compat: These default implementations behave strangely because this class was originally
- // creatable only from the native runtime, not through subclass inheritance.
public virtual int LocalSignatureMetadataToken => 0;
- public virtual IList<LocalVariableInfo> LocalVariables { get { throw new ArgumentNullException("array"); } }
+ public virtual IList<LocalVariableInfo> LocalVariables => throw new ArgumentNullException("array");
public virtual int MaxStackSize => 0;
public virtual bool InitLocals => false;
public virtual byte[] GetILAsByteArray() => null;
- public virtual IList<ExceptionHandlingClause> ExceptionHandlingClauses { get { throw new ArgumentNullException("array"); } }
+ public virtual IList<ExceptionHandlingClause> ExceptionHandlingClauses => throw new ArgumentNullException("array");
}
}
+
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/Module.cs b/src/System.Private.CoreLib/shared/System/Reflection/Module.cs
index 56f83c40d..d290f7803 100644
--- a/src/System.Private.CoreLib/shared/System/Reflection/Module.cs
+++ b/src/System.Private.CoreLib/shared/System/Reflection/Module.cs
@@ -130,53 +130,29 @@ namespace System.Reflection
public override string ToString() => ScopeName;
- public static readonly TypeFilter FilterTypeName = FilterTypeNameImpl;
- public static readonly TypeFilter FilterTypeNameIgnoreCase = FilterTypeNameIgnoreCaseImpl;
+ public static readonly TypeFilter FilterTypeName = (m, c) => FilterTypeNameImpl(m, c, StringComparison.Ordinal);
+ public static readonly TypeFilter FilterTypeNameIgnoreCase = (m, c) => FilterTypeNameImpl(m, c, StringComparison.OrdinalIgnoreCase);
private const BindingFlags DefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
// FilterTypeName
// This method will filter the class based upon the name. It supports
// a trailing wild card.
- private static bool FilterTypeNameImpl(Type cls, object filterCriteria)
+ private static bool FilterTypeNameImpl(Type cls, object filterCriteria, StringComparison comparison)
{
// Check that the criteria object is a String object
- if (filterCriteria == null || !(filterCriteria is string))
- throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritString);
-
- string str = (string)filterCriteria;
-
- // Check to see if this is a prefix or exact match requirement
- if (str.Length > 0 && str[str.Length - 1] == '*')
+ if (!(filterCriteria is string str))
{
- str = str.Substring(0, str.Length - 1);
- return cls.Name.StartsWith(str, StringComparison.Ordinal);
- }
-
- return cls.Name.Equals(str);
- }
-
- // FilterFieldNameIgnoreCase
- // This method filter the Type based upon name, it ignores case.
- private static bool FilterTypeNameIgnoreCaseImpl(Type cls, object filterCriteria)
- {
- // Check that the criteria object is a String object
- if (filterCriteria == null || !(filterCriteria is string))
throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritString);
-
- string str = (string)filterCriteria;
-
+ }
// Check to see if this is a prefix or exact match requirement
if (str.Length > 0 && str[str.Length - 1] == '*')
{
- str = str.Substring(0, str.Length - 1);
- string name = cls.Name;
- if (name.Length >= str.Length)
- return (string.Compare(name, 0, str, 0, str.Length, StringComparison.OrdinalIgnoreCase) == 0);
- else
- return false;
+ ReadOnlySpan<char> slice = str.AsSpan(0, str.Length - 1);
+ return cls.Name.AsSpan().StartsWith(slice, comparison);
}
- return (string.Compare(str, cls.Name, StringComparison.OrdinalIgnoreCase) == 0);
+
+ return cls.Name.Equals(str, comparison);
}
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Reflection/SignatureConstructedGenericType.cs b/src/System.Private.CoreLib/shared/System/Reflection/SignatureConstructedGenericType.cs
index cd97ffa21..d3d88520f 100644
--- a/src/System.Private.CoreLib/shared/System/Reflection/SignatureConstructedGenericType.cs
+++ b/src/System.Private.CoreLib/shared/System/Reflection/SignatureConstructedGenericType.cs
@@ -10,11 +10,25 @@ namespace System.Reflection
{
internal sealed class SignatureConstructedGenericType : SignatureType
{
- internal SignatureConstructedGenericType(Type genericTypeDefinition, Type[] genericTypeArguments)
+ // The exception-visible name "typeArguments" is chosen to match the parameter name to Type.MakeGenericType() since that's the
+ // intended user of this constructor.
+ internal SignatureConstructedGenericType(Type genericTypeDefinition, Type[] typeArguments)
{
- Debug.Assert(genericTypeDefinition != null && genericTypeArguments != null);
+ if (genericTypeDefinition == null)
+ throw new ArgumentNullException(nameof(genericTypeDefinition));
+
+ if (typeArguments == null)
+ throw new ArgumentNullException(nameof(typeArguments));
+
+ typeArguments = (Type[])(typeArguments.Clone());
+ for (int i = 0; i < typeArguments.Length; i++)
+ {
+ if (typeArguments[i] == null)
+ throw new ArgumentNullException(nameof(typeArguments));
+ }
+
_genericTypeDefinition = genericTypeDefinition;
- _genericTypeArguments = (Type[])(genericTypeArguments.Clone());
+ _genericTypeArguments = typeArguments;
}
public sealed override bool IsTypeDefinition => false;
diff --git a/src/System.Private.CoreLib/src/System/Resources/FastResourceComparer.cs b/src/System.Private.CoreLib/shared/System/Resources/FastResourceComparer.cs
index 3af7a1546..6b813a0ce 100644
--- a/src/System.Private.CoreLib/src/System/Resources/FastResourceComparer.cs
+++ b/src/System.Private.CoreLib/shared/System/Resources/FastResourceComparer.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -21,18 +21,18 @@ using System.Diagnostics;
namespace System.Resources
{
- internal sealed class FastResourceComparer : IComparer, IEqualityComparer, IComparer<String>, IEqualityComparer<String>
+ internal sealed class FastResourceComparer : IComparer, IEqualityComparer, IComparer<string>, IEqualityComparer<string>
{
internal static readonly FastResourceComparer Default = new FastResourceComparer();
// Implements IHashCodeProvider too, due to Hashtable requirements.
- public int GetHashCode(Object key)
+ public int GetHashCode(object key)
{
- String s = (String)key;
+ string s = (string)key;
return FastResourceComparer.HashFunction(s);
}
- public int GetHashCode(String key)
+ public int GetHashCode(string key)
{
return FastResourceComparer.HashFunction(key);
}
@@ -40,7 +40,7 @@ namespace System.Resources
// This hash function MUST be publically documented with the resource
// file format, AND we may NEVER change this hash function's return
// value (without changing the file format).
- internal static int HashFunction(String key)
+ internal static int HashFunction(string key)
{
// Never change this hash function. We must standardize it so that
// others can read & write our .resources files. Additionally, we
@@ -52,35 +52,35 @@ namespace System.Resources
}
// Compares Strings quickly in a case-sensitive way
- public int Compare(Object a, Object b)
+ public int Compare(object a, object b)
{
if (a == b) return 0;
- String sa = (String)a;
- String sb = (String)b;
- return String.CompareOrdinal(sa, sb);
+ string sa = (string)a;
+ string sb = (string)b;
+ return string.CompareOrdinal(sa, sb);
}
- public int Compare(String a, String b)
+ public int Compare(string a, string b)
{
- return String.CompareOrdinal(a, b);
+ return string.CompareOrdinal(a, b);
}
- public bool Equals(String a, String b)
+ public bool Equals(string a, string b)
{
- return String.Equals(a, b);
+ return string.Equals(a, b);
}
- public new bool Equals(Object a, Object b)
+ public new bool Equals(object a, object b)
{
if (a == b) return true;
- String sa = (String)a;
- String sb = (String)b;
- return String.Equals(sa, sb);
+ string sa = (string)a;
+ string sb = (string)b;
+ return string.Equals(sa, sb);
}
// Input is one string to compare with, and a byte[] containing chars in
// little endian unicode. Pass in the number of valid chars.
- public unsafe static int CompareOrdinal(String a, byte[] bytes, int bCharLength)
+ public static unsafe int CompareOrdinal(string a, byte[] bytes, int bCharLength)
{
Debug.Assert(a != null && bytes != null, "FastResourceComparer::CompareOrdinal must have non-null params");
Debug.Assert(bCharLength * 2 <= bytes.Length, "FastResourceComparer::CompareOrdinal - numChars is too big!");
@@ -109,14 +109,14 @@ namespace System.Resources
return a.Length - bCharLength;
}
- public static int CompareOrdinal(byte[] bytes, int aCharLength, String b)
+ public static int CompareOrdinal(byte[] bytes, int aCharLength, string b)
{
return -CompareOrdinal(b, bytes, aCharLength);
}
// This method is to handle potentially misaligned data accesses.
// The byte* must point to little endian Unicode characters.
- internal unsafe static int CompareOrdinal(byte* a, int byteLen, String b)
+ internal static unsafe int CompareOrdinal(byte* a, int byteLen, string b)
{
Debug.Assert((byteLen & 1) == 0, "CompareOrdinal is expecting a UTF-16 string length, which must be even!");
Debug.Assert(a != null && b != null, "Null args not allowed.");
@@ -139,3 +139,4 @@ namespace System.Resources
}
}
}
+
diff --git a/src/System.Private.CoreLib/shared/System/Resources/MissingSatelliteAssemblyException.cs b/src/System.Private.CoreLib/shared/System/Resources/MissingSatelliteAssemblyException.cs
index af547b21f..0bbc62673 100644
--- a/src/System.Private.CoreLib/shared/System/Resources/MissingSatelliteAssemblyException.cs
+++ b/src/System.Private.CoreLib/shared/System/Resources/MissingSatelliteAssemblyException.cs
@@ -24,7 +24,7 @@ namespace System.Resources
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class MissingSatelliteAssemblyException : SystemException
{
- private String _cultureName;
+ private string _cultureName;
public MissingSatelliteAssemblyException()
: base(SR.MissingSatelliteAssembly_Default)
@@ -38,7 +38,7 @@ namespace System.Resources
HResult = System.HResults.COR_E_MISSINGSATELLITEASSEMBLY;
}
- public MissingSatelliteAssemblyException(string message, String cultureName)
+ public MissingSatelliteAssemblyException(string message, string cultureName)
: base(message)
{
HResult = System.HResults.COR_E_MISSINGSATELLITEASSEMBLY;
@@ -56,7 +56,7 @@ namespace System.Resources
{
}
- public String CultureName
+ public string CultureName
{
get { return _cultureName; }
}
diff --git a/src/System.Private.CoreLib/src/System/Resources/ResourceReader.cs b/src/System.Private.CoreLib/shared/System/Resources/ResourceReader.cs
index 96fea18f6..cd2b0d080 100644
--- a/src/System.Private.CoreLib/src/System/Resources/ResourceReader.cs
+++ b/src/System.Private.CoreLib/shared/System/Resources/ResourceReader.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -15,18 +15,21 @@
**
===========================================================*/
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Globalization;
-using System.IO;
-using System.Reflection;
-using System.Runtime.Versioning;
-using System.Text;
-
namespace System.Resources
{
+ using System;
+ using System.IO;
+ using System.Text;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Reflection;
+ using System.Security;
+ using System.Globalization;
+ using System.Configuration.Assemblies;
+ using System.Runtime.Versioning;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+
// Provides the default implementation of IResourceReader, reading
// .resources file from the system default binary format. This class
// can be treated as an enumerator once.
@@ -37,10 +40,10 @@ namespace System.Resources
internal struct ResourceLocator
{
- internal Object _value; // Can be null. Consider WeakReference instead?
+ internal object _value; // Can be null. Consider WeakReference instead?
internal int _dataPos;
- internal ResourceLocator(int dataPos, Object value)
+ internal ResourceLocator(int dataPos, object value)
{
_dataPos = dataPos;
_value = value;
@@ -54,7 +57,7 @@ namespace System.Resources
// Allows adding in profiling data in a future version, or a special
// resource profiling build. We could also use WeakReference.
- internal Object Value
+ internal object Value
{
get { return _value; }
set { _value = value; }
@@ -78,7 +81,7 @@ namespace System.Resources
// Used by RuntimeResourceSet and this class's enumerator. Maps
// resource name to a value, a ResourceLocator, or a
// LooselyLinkedManifestResource.
- internal Dictionary<String, ResourceLocator> _resCache;
+ internal Dictionary<string, ResourceLocator> _resCache;
private long _nameSectionOffset; // Offset to name section of file.
private long _dataSectionOffset; // Offset to Data section of file.
@@ -102,13 +105,10 @@ namespace System.Resources
// Version number of .resources file, for compatibility
private int _version;
-#if RESOURCE_FILE_FORMAT_DEBUG
- private bool _debug; // Whether this file has debugging stuff in it.
-#endif
- public ResourceReader(String fileName)
+ public ResourceReader(string fileName)
{
- _resCache = new Dictionary<String, ResourceLocator>(FastResourceComparer.Default);
+ _resCache = new Dictionary<string, ResourceLocator>(FastResourceComparer.Default);
_store = new BinaryReader(new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize, FileOptions.RandomAccess), Encoding.UTF8);
try
@@ -117,7 +117,7 @@ namespace System.Resources
}
catch
{
- _store.Dispose(); // If we threw an exception, close the file.
+ _store.Close(); // If we threw an exception, close the file.
throw;
}
}
@@ -129,7 +129,7 @@ namespace System.Resources
if (!stream.CanRead)
throw new ArgumentException(SR.Argument_StreamNotReadable);
- _resCache = new Dictionary<String, ResourceLocator>(FastResourceComparer.Default);
+ _resCache = new Dictionary<string, ResourceLocator>(FastResourceComparer.Default);
_store = new BinaryReader(stream, Encoding.UTF8);
// We have a faster code path for reading resource files from an assembly.
_ums = stream as UnmanagedMemoryStream;
@@ -141,7 +141,7 @@ namespace System.Resources
// passing in the stream to read from and the RuntimeResourceSet's
// internal hash table (hash table of names with file offsets
// and values, coupled to this ResourceReader).
- internal ResourceReader(Stream stream, Dictionary<String, ResourceLocator> resCache)
+ internal ResourceReader(Stream stream, Dictionary<string, ResourceLocator> resCache)
{
Debug.Assert(stream != null, "Need a stream!");
Debug.Assert(stream.CanRead, "Stream should be readable!");
@@ -178,7 +178,7 @@ namespace System.Resources
BinaryReader copyOfStore = _store;
_store = null;
if (copyOfStore != null)
- copyOfStore.Dispose();
+ copyOfStore.Close();
}
_store = null;
_namePositions = null;
@@ -196,38 +196,10 @@ namespace System.Resources
return buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
}
- internal int Read7BitEncodedInt()
- {
- // Read out an Int32 7 bits at a time. The high bit
- // of the byte when on means to continue reading more bytes.
- int count = 0;
- int shift = 0;
- byte b;
- do
- {
- // Check for a corrupted stream. Read a max of 5 bytes.
- // In a future version, add a DataFormatException.
- if (shift == 5 * 7) // 5 bytes max per Int32, shift += 7
- throw new FormatException(SR.Format_Bad7BitInt32);
-
- // ReadByte handles end of stream cases for us.
- b = _store.ReadByte();
- count |= (b & 0x7F) << shift;
- shift += 7;
- } while ((b & 0x80) != 0);
- return count;
- }
-
-
- private void SkipInt32()
- {
- _store.BaseStream.Seek(4, SeekOrigin.Current);
- }
-
private void SkipString()
{
- int stringLength = Read7BitEncodedInt();
+ int stringLength = _store.Read7BitEncodedInt();
if (stringLength < 0)
{
throw new BadImageFormatException(SR.BadImageFormat_NegativeStringLength);
@@ -284,10 +256,11 @@ namespace System.Resources
// To read the data, seek to _dataSectionOffset + dataPos, then
// read the resource type & data.
// This does a binary search through the names.
- internal int FindPosForResource(String name)
+ internal int FindPosForResource(string name)
{
Debug.Assert(_store != null, "ResourceReader is closed!");
int hash = FastResourceComparer.HashFunction(name);
+
// Binary search over the hashes. Use the _namePositions array to
// determine where they exist in the underlying stream.
int lo = 0;
@@ -307,7 +280,7 @@ namespace System.Resources
c = -1;
else
c = 1;
- //BCLDebug.Log("RESMGRFILEFORMAT", " Probing index "+index+" lo: "+lo+" hi: "+hi+" c: "+c);
+
if (c == 0)
{
success = true;
@@ -364,10 +337,10 @@ namespace System.Resources
// with the string you pass in.
// Whoever calls this method should make sure that they take a lock
// so no one else can cause us to seek in the stream.
- private unsafe bool CompareStringEqualsName(String name)
+ private unsafe bool CompareStringEqualsName(string name)
{
Debug.Assert(_store != null, "ResourceReader is closed!");
- int byteLen = Read7BitEncodedInt();
+ int byteLen = _store.Read7BitEncodedInt();
if (byteLen < 0)
{
throw new BadImageFormatException(SR.BadImageFormat_NegativeStringLength);
@@ -406,7 +379,7 @@ namespace System.Resources
// This is used in the enumerator. The enumerator iterates from 0 to n
// of our resources and this returns the resource name for a particular
// index. The parameter is NOT a virtual offset.
- private unsafe String AllocateStringForNameIndex(int index, out int dataOffset)
+ private unsafe string AllocateStringForNameIndex(int index, out int dataOffset)
{
Debug.Assert(_store != null, "ResourceReader is closed!");
byte[] bytes;
@@ -416,7 +389,7 @@ namespace System.Resources
{
_store.BaseStream.Seek(nameVA + _nameSectionOffset, SeekOrigin.Begin);
// Can't use _store.ReadString, since it's using UTF-8!
- byteLen = Read7BitEncodedInt();
+ byteLen = _store.Read7BitEncodedInt();
if (byteLen < 0)
{
throw new BadImageFormatException(SR.BadImageFormat_NegativeStringLength);
@@ -427,9 +400,10 @@ namespace System.Resources
if (_ums.Position > _ums.Length - byteLen)
throw new BadImageFormatException(SR.Format(SR.BadImageFormat_ResourcesIndexTooLong, index));
- String s = null;
+ string s = null;
char* charPtr = (char*)_ums.PositionPointer;
- s = new String(charPtr, 0, byteLen / 2);
+
+ s = new string(charPtr, 0, byteLen / 2);
_ums.Position += byteLen;
dataOffset = _store.ReadInt32();
@@ -464,7 +438,7 @@ namespace System.Resources
// This is used in the enumerator. The enumerator iterates from 0 to n
// of our resources and this returns the resource value for a particular
// index. The parameter is NOT a virtual offset.
- private Object GetValueForNameIndex(int index)
+ private object GetValueForNameIndex(int index)
{
Debug.Assert(_store != null, "ResourceReader is closed!");
long nameVA = GetNamePosition(index);
@@ -472,7 +446,7 @@ namespace System.Resources
{
_store.BaseStream.Seek(nameVA + _nameSectionOffset, SeekOrigin.Begin);
SkipString();
- //BCLDebug.Log("RESMGRFILEFORMAT", "GetValueForNameIndex for index: "+index+" skip (name length): "+skip);
+
int dataPos = _store.ReadInt32();
if (dataPos < 0 || dataPos >= _store.BaseStream.Length - _dataSectionOffset)
{
@@ -490,17 +464,17 @@ namespace System.Resources
// from that location.
// Anyone who calls LoadObject should make sure they take a lock so
// no one can cause us to do a seek in here.
- internal String LoadString(int pos)
+ internal string LoadString(int pos)
{
Debug.Assert(_store != null, "ResourceReader is closed!");
_store.BaseStream.Seek(_dataSectionOffset + pos, SeekOrigin.Begin);
- String s = null;
- int typeIndex = Read7BitEncodedInt();
+ string s = null;
+ int typeIndex = _store.Read7BitEncodedInt();
if (_version == 1)
{
if (typeIndex == -1)
return null;
- if (FindType(typeIndex) != typeof(String))
+ if (FindType(typeIndex) != typeof(string))
throw new InvalidOperationException(SR.Format(SR.InvalidOperation_ResourceNotString_Type, FindType(typeIndex).FullName));
s = _store.ReadString();
}
@@ -509,7 +483,7 @@ namespace System.Resources
ResourceTypeCode typeCode = (ResourceTypeCode)typeIndex;
if (typeCode != ResourceTypeCode.String && typeCode != ResourceTypeCode.Null)
{
- String typeString;
+ string typeString;
if (typeCode < ResourceTypeCode.StartOfUserTypes)
typeString = typeCode.ToString();
else
@@ -523,7 +497,7 @@ namespace System.Resources
}
// Called from RuntimeResourceSet
- internal Object LoadObject(int pos)
+ internal object LoadObject(int pos)
{
if (_version == 1)
return LoadObjectV1(pos);
@@ -531,12 +505,12 @@ namespace System.Resources
return LoadObjectV2(pos, out typeCode);
}
- internal Object LoadObject(int pos, out ResourceTypeCode typeCode)
+ internal object LoadObject(int pos, out ResourceTypeCode typeCode)
{
if (_version == 1)
{
- Object o = LoadObjectV1(pos);
- typeCode = (o is String) ? ResourceTypeCode.String : ResourceTypeCode.StartOfUserTypes;
+ object o = LoadObjectV1(pos);
+ typeCode = (o is string) ? ResourceTypeCode.String : ResourceTypeCode.StartOfUserTypes;
return o;
}
return LoadObjectV2(pos, out typeCode);
@@ -546,7 +520,7 @@ namespace System.Resources
// from that location.
// Anyone who calls LoadObject should make sure they take a lock so
// no one can cause us to do a seek in here.
- internal Object LoadObjectV1(int pos)
+ internal object LoadObjectV1(int pos)
{
Debug.Assert(_store != null, "ResourceReader is closed!");
Debug.Assert(_version == 1, ".resources file was not a V1 .resources file!");
@@ -567,10 +541,10 @@ namespace System.Resources
}
}
- private Object _LoadObjectV1(int pos)
+ private object _LoadObjectV1(int pos)
{
_store.BaseStream.Seek(_dataSectionOffset + pos, SeekOrigin.Begin);
- int typeIndex = Read7BitEncodedInt();
+ int typeIndex = _store.Read7BitEncodedInt();
if (typeIndex == -1)
return null;
Type type = FindType(typeIndex);
@@ -578,27 +552,27 @@ namespace System.Resources
// primitive or a value type first, so we can reach the
// deserialization code faster for arbitrary objects.
- if (type == typeof(String))
+ if (type == typeof(string))
return _store.ReadString();
- else if (type == typeof(Int32))
+ else if (type == typeof(int))
return _store.ReadInt32();
- else if (type == typeof(Byte))
+ else if (type == typeof(byte))
return _store.ReadByte();
- else if (type == typeof(SByte))
+ else if (type == typeof(sbyte))
return _store.ReadSByte();
- else if (type == typeof(Int16))
+ else if (type == typeof(short))
return _store.ReadInt16();
- else if (type == typeof(Int64))
+ else if (type == typeof(long))
return _store.ReadInt64();
- else if (type == typeof(UInt16))
+ else if (type == typeof(ushort))
return _store.ReadUInt16();
- else if (type == typeof(UInt32))
+ else if (type == typeof(uint))
return _store.ReadUInt32();
- else if (type == typeof(UInt64))
+ else if (type == typeof(ulong))
return _store.ReadUInt64();
- else if (type == typeof(Single))
+ else if (type == typeof(float))
return _store.ReadSingle();
- else if (type == typeof(Double))
+ else if (type == typeof(double))
return _store.ReadDouble();
else if (type == typeof(DateTime))
{
@@ -608,12 +582,12 @@ namespace System.Resources
}
else if (type == typeof(TimeSpan))
return new TimeSpan(_store.ReadInt64());
- else if (type == typeof(Decimal))
+ else if (type == typeof(decimal))
{
int[] bits = new int[4];
for (int i = 0; i < bits.Length; i++)
bits[i] = _store.ReadInt32();
- return new Decimal(bits);
+ return new decimal(bits);
}
else
{
@@ -621,7 +595,7 @@ namespace System.Resources
}
}
- internal Object LoadObjectV2(int pos, out ResourceTypeCode typeCode)
+ internal object LoadObjectV2(int pos, out ResourceTypeCode typeCode)
{
Debug.Assert(_store != null, "ResourceReader is closed!");
Debug.Assert(_version >= 2, ".resources file was not a V2 (or higher) .resources file!");
@@ -642,10 +616,10 @@ namespace System.Resources
}
}
- private Object _LoadObjectV2(int pos, out ResourceTypeCode typeCode)
+ private object _LoadObjectV2(int pos, out ResourceTypeCode typeCode)
{
_store.BaseStream.Seek(_dataSectionOffset + pos, SeekOrigin.Begin);
- typeCode = (ResourceTypeCode)Read7BitEncodedInt();
+ typeCode = (ResourceTypeCode)_store.Read7BitEncodedInt();
switch (typeCode)
{
@@ -696,11 +670,11 @@ namespace System.Resources
case ResourceTypeCode.DateTime:
// Use DateTime's ToBinary & FromBinary.
- Int64 data = _store.ReadInt64();
+ long data = _store.ReadInt64();
return DateTime.FromBinary(data);
case ResourceTypeCode.TimeSpan:
- Int64 ticks = _store.ReadInt64();
+ long ticks = _store.ReadInt64();
return new TimeSpan(ticks);
// Special types
@@ -822,7 +796,7 @@ namespace System.Resources
// Read in type name for a suitable ResourceReader
// Note ResourceWriter & InternalResGen use different Strings.
- String readerType = _store.ReadString();
+ string readerType = _store.ReadString();
readerType = System.CoreLib.FixupCoreLibName(readerType);
AssemblyName mscorlib = new AssemblyName(ResourceManager.MscorlibName);
@@ -969,7 +943,7 @@ namespace System.Resources
try
{
_store.BaseStream.Position = _typeNamePositions[typeIndex];
- String typeName = _store.ReadString();
+ string typeName = _store.ReadString();
_typeTable[typeIndex] = Type.GetType(typeName, true);
}
// If serialization isn't supported, we convert FileNotFoundException to
@@ -995,7 +969,7 @@ namespace System.Resources
return _typeTable[typeIndex];
}
- public void GetResourceData(String resourceName, out String resourceType, out byte[] resourceData)
+ public void GetResourceData(string resourceName, out string resourceType, out byte[] resourceData)
{
if (resourceName == null)
throw new ArgumentNullException(nameof(resourceName));
@@ -1020,7 +994,7 @@ namespace System.Resources
{
_store.BaseStream.Position = _nameSectionOffset + GetNamePosition(i);
// Skip over name of resource
- int numBytesToSkip = Read7BitEncodedInt();
+ int numBytesToSkip = _store.Read7BitEncodedInt();
if (numBytesToSkip < 0)
{
throw new FormatException(SR.Format(SR.BadImageFormat_ResourcesNameInvalidOffset, numBytesToSkip));
@@ -1044,7 +1018,7 @@ namespace System.Resources
// Read type code then byte[]
_store.BaseStream.Position = _dataSectionOffset + dataPos;
- ResourceTypeCode typeCode = (ResourceTypeCode)Read7BitEncodedInt();
+ ResourceTypeCode typeCode = (ResourceTypeCode)_store.Read7BitEncodedInt();
if (typeCode < 0 || typeCode >= ResourceTypeCode.StartOfUserTypes + _typeTable.Length)
{
throw new BadImageFormatException(SR.BadImageFormat_InvalidType);
@@ -1061,12 +1035,12 @@ namespace System.Resources
}
}
- private String TypeNameFromTypeCode(ResourceTypeCode typeCode)
+ private string TypeNameFromTypeCode(ResourceTypeCode typeCode)
{
Debug.Assert(typeCode >= 0, "can't be negative");
if (typeCode < ResourceTypeCode.StartOfUserTypes)
{
- Debug.Assert(!String.Equals(typeCode.ToString(), "LastPrimitive"), "Change ResourceTypeCode metadata order so LastPrimitive isn't what Enum.ToString prefers.");
+ Debug.Assert(!string.Equals(typeCode.ToString(), "LastPrimitive"), "Change ResourceTypeCode metadata order so LastPrimitive isn't what Enum.ToString prefers.");
return "ResourceTypeCode." + typeCode.ToString();
}
else
@@ -1088,7 +1062,7 @@ namespace System.Resources
internal sealed class ResourceEnumerator : IDictionaryEnumerator
{
- private const int ENUM_DONE = Int32.MinValue;
+ private const int ENUM_DONE = int.MinValue;
private const int ENUM_NOT_STARTED = -1;
private ResourceReader _reader;
@@ -1116,7 +1090,7 @@ namespace System.Resources
return true;
}
- public Object Key
+ public object Key
{
get
{
@@ -1128,7 +1102,7 @@ namespace System.Resources
}
}
- public Object Current
+ public object Current
{
get
{
@@ -1153,8 +1127,8 @@ namespace System.Resources
if (!_currentIsValid) throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted);
if (_reader._resCache == null) throw new InvalidOperationException(SR.ResourceReaderIsClosed);
- String key;
- Object value = null;
+ string key;
+ object value = null;
lock (_reader)
{ // locks should be taken in the same order as in RuntimeResourceSet.GetObject to avoid deadlock
lock (_reader._resCache)
@@ -1183,7 +1157,7 @@ namespace System.Resources
}
}
- public Object Value
+ public object Value
{
get
{
diff --git a/src/System.Private.CoreLib/src/System/Resources/ResourceSet.cs b/src/System.Private.CoreLib/shared/System/Resources/ResourceSet.cs
index 5b1fd99a7..2d33f3a8b 100644
--- a/src/System.Private.CoreLib/src/System/Resources/ResourceSet.cs
+++ b/src/System.Private.CoreLib/shared/System/Resources/ResourceSet.cs
@@ -13,15 +13,9 @@
**
===========================================================*/
-using System;
using System.Collections;
using System.IO;
-using System.Globalization;
-using System.Runtime.InteropServices;
using System.Reflection;
-using System.Runtime.Serialization;
-using System.Runtime.Versioning;
-using System.Collections.Generic;
namespace System.Resources
{
@@ -33,11 +27,10 @@ namespace System.Resources
//
public class ResourceSet : IDisposable, IEnumerable
{
- [NonSerialized]
protected IResourceReader Reader;
+ internal Hashtable Table;
- private Dictionary<object, object> _table;
- private Dictionary<object, object> _caseInsensitiveTable; // For case-insensitive lookups.
+ private Hashtable _caseInsensitiveTable; // For case-insensitive lookups.
protected ResourceSet()
{
@@ -56,7 +49,7 @@ namespace System.Resources
// implementation. Use this constructor to open & read from a file
// on disk.
//
- public ResourceSet(String fileName)
+ public ResourceSet(string fileName)
{
Reader = new ResourceReader(fileName);
CommonInit();
@@ -85,7 +78,7 @@ namespace System.Resources
private void CommonInit()
{
- _table = new Dictionary<object, object>();
+ Table = new Hashtable();
}
// Closes and releases any resources used by this ResourceSet, if any.
@@ -109,7 +102,7 @@ namespace System.Resources
}
Reader = null;
_caseInsensitiveTable = null;
- _table = null;
+ Table = null;
}
public void Dispose()
@@ -146,7 +139,7 @@ namespace System.Resources
private IDictionaryEnumerator GetEnumeratorHelper()
{
- Dictionary<object, object> copyOfTable = _table; // Avoid a race with Dispose
+ Hashtable copyOfTable = Table; // Avoid a race with Dispose
if (copyOfTable == null)
throw new ObjectDisposedException(null, SR.ObjectDisposed_ResourceSet);
return copyOfTable.GetEnumerator();
@@ -154,12 +147,12 @@ namespace System.Resources
// Look up a string value for a resource given its name.
//
- public virtual String GetString(String name)
+ public virtual string GetString(string name)
{
- Object obj = GetObjectInternal(name);
+ object obj = GetObjectInternal(name);
try
{
- return (String)obj;
+ return (string)obj;
}
catch (InvalidCastException)
{
@@ -167,16 +160,16 @@ namespace System.Resources
}
}
- public virtual String GetString(String name, bool ignoreCase)
+ public virtual string GetString(string name, bool ignoreCase)
{
- Object obj;
- String s;
+ object obj;
+ string s;
// Case-sensitive lookup
obj = GetObjectInternal(name);
try
{
- s = (String)obj;
+ s = (string)obj;
}
catch (InvalidCastException)
{
@@ -193,7 +186,7 @@ namespace System.Resources
obj = GetCaseInsensitiveObjectInternal(name);
try
{
- return (String)obj;
+ return (string)obj;
}
catch (InvalidCastException)
{
@@ -203,14 +196,14 @@ namespace System.Resources
// Look up an object value for a resource given its name.
//
- public virtual Object GetObject(String name)
+ public virtual object GetObject(string name)
{
return GetObjectInternal(name);
}
- public virtual Object GetObject(String name, bool ignoreCase)
+ public virtual object GetObject(string name, bool ignoreCase)
{
- Object obj = GetObjectInternal(name);
+ object obj = GetObjectInternal(name);
if (obj != null || !ignoreCase)
return obj;
@@ -223,38 +216,37 @@ namespace System.Resources
IDictionaryEnumerator en = Reader.GetEnumerator();
while (en.MoveNext())
{
- Object value = en.Value;
- _table.Add(en.Key, value);
+ object value = en.Value;
+ Table.Add(en.Key, value);
}
// While technically possible to close the Reader here, don't close it
// to help with some WinRes lifetime issues.
}
- private Object GetObjectInternal(String name)
+ private object GetObjectInternal(string name)
{
if (name == null)
- throw new ArgumentNullException("name");
+ throw new ArgumentNullException(nameof(name));
- Dictionary<object, object> copyOfTable = _table; // Avoid a race with Dispose
+ Hashtable copyOfTable = Table; // Avoid a race with Dispose
if (copyOfTable == null)
throw new ObjectDisposedException(null, SR.ObjectDisposed_ResourceSet);
- object value;
- copyOfTable.TryGetValue(name, out value);
- return value;
+
+ return copyOfTable[name];
}
- private Object GetCaseInsensitiveObjectInternal(String name)
+ private object GetCaseInsensitiveObjectInternal(string name)
{
- Dictionary<object, object> copyOfTable = _table; // Avoid a race with Dispose
+ Hashtable copyOfTable = Table; // Avoid a race with Dispose
if (copyOfTable == null)
throw new ObjectDisposedException(null, SR.ObjectDisposed_ResourceSet);
- Dictionary<object, object> caseTable = _caseInsensitiveTable; // Avoid a race condition with Close
+ Hashtable caseTable = _caseInsensitiveTable; // Avoid a race condition with Close
if (caseTable == null)
{
- caseTable = new Dictionary<object, object>(CaseInsensitiveStringObjectComparer.Instance);
+ caseTable = new Hashtable(StringComparer.OrdinalIgnoreCase);
IDictionaryEnumerator en = copyOfTable.GetEnumerator();
while (en.MoveNext())
@@ -263,29 +255,8 @@ namespace System.Resources
}
_caseInsensitiveTable = caseTable;
}
- object value;
- caseTable.TryGetValue(name, out value);
- return value;
- }
-
- /// <summary>
- /// Adapter for StringComparer.OrdinalIgnoreCase to allow it to be used with Dictionary
- /// </summary>
- private class CaseInsensitiveStringObjectComparer : IEqualityComparer<object>
- {
- public static CaseInsensitiveStringObjectComparer Instance { get; } = new CaseInsensitiveStringObjectComparer();
-
- private CaseInsensitiveStringObjectComparer() { }
-
- public new bool Equals(object x, object y)
- {
- return ((IEqualityComparer)StringComparer.OrdinalIgnoreCase).Equals(x, y);
- }
- public int GetHashCode(object obj)
- {
- return ((IEqualityComparer)StringComparer.OrdinalIgnoreCase).GetHashCode(obj);
- }
+ return caseTable[name];
}
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Resources/RuntimeResourceSet.cs b/src/System.Private.CoreLib/shared/System/Resources/RuntimeResourceSet.cs
index a63e68c19..426e17bdb 100644
--- a/src/System.Private.CoreLib/shared/System/Resources/RuntimeResourceSet.cs
+++ b/src/System.Private.CoreLib/shared/System/Resources/RuntimeResourceSet.cs
@@ -173,7 +173,7 @@ namespace System.Resources
// for arbitrarily long times, since the object is usually a string
// literal that will live for the lifetime of the appdomain. The
// value is a ResourceLocator instance, which might cache the object.
- private Dictionary<String, ResourceLocator> _resCache;
+ private Dictionary<string, ResourceLocator> _resCache;
// For our special load-on-demand reader, cache the cast. The
@@ -185,15 +185,15 @@ namespace System.Resources
// want to fill this out if we can avoid it. The problem is resource
// fallback will somewhat regularly cause us to look up resources that
// don't exist.
- private Dictionary<String, ResourceLocator> _caseInsensitiveTable;
+ private Dictionary<string, ResourceLocator> _caseInsensitiveTable;
// If we're not using our custom reader, then enumerate through all
// the resources once, adding them into the table.
private bool _haveReadFromReader;
- internal RuntimeResourceSet(String fileName) : base(false)
+ internal RuntimeResourceSet(string fileName) : base(false)
{
- _resCache = new Dictionary<String, ResourceLocator>(FastResourceComparer.Default);
+ _resCache = new Dictionary<string, ResourceLocator>(FastResourceComparer.Default);
Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
_defaultReader = new ResourceReader(stream, _resCache);
Reader = _defaultReader;
@@ -201,7 +201,7 @@ namespace System.Resources
internal RuntimeResourceSet(Stream stream) : base(false)
{
- _resCache = new Dictionary<String, ResourceLocator>(FastResourceComparer.Default);
+ _resCache = new Dictionary<string, ResourceLocator>(FastResourceComparer.Default);
_defaultReader = new ResourceReader(stream, _resCache);
Reader = _defaultReader;
}
@@ -256,36 +256,36 @@ namespace System.Resources
}
- public override String GetString(String key)
+ public override string GetString(string key)
{
- Object o = GetObject(key, false, true);
- return (String)o;
+ object o = GetObject(key, false, true);
+ return (string)o;
}
- public override String GetString(String key, bool ignoreCase)
+ public override string GetString(string key, bool ignoreCase)
{
- Object o = GetObject(key, ignoreCase, true);
- return (String)o;
+ object o = GetObject(key, ignoreCase, true);
+ return (string)o;
}
- public override Object GetObject(String key)
+ public override object GetObject(string key)
{
return GetObject(key, false, false);
}
- public override Object GetObject(String key, bool ignoreCase)
+ public override object GetObject(string key, bool ignoreCase)
{
return GetObject(key, ignoreCase, false);
}
- private Object GetObject(String key, bool ignoreCase, bool isString)
+ private object GetObject(string key, bool ignoreCase, bool isString)
{
if (key == null)
throw new ArgumentNullException(nameof(key));
if (Reader == null || _resCache == null)
throw new ObjectDisposedException(null, SR.ObjectDisposed_ResourceSet);
- Object value = null;
+ object value = null;
ResourceLocator resLocation;
lock (Reader)
@@ -348,7 +348,7 @@ namespace System.Resources
// If necessary, init our case insensitive hash table.
if (ignoreCase && _caseInsensitiveTable == null)
{
- _caseInsensitiveTable = new Dictionary<String, ResourceLocator>(StringComparer.OrdinalIgnoreCase);
+ _caseInsensitiveTable = new Dictionary<string, ResourceLocator>(StringComparer.OrdinalIgnoreCase);
}
if (_defaultReader == null)
@@ -357,7 +357,7 @@ namespace System.Resources
while (en.MoveNext())
{
DictionaryEntry entry = en.Entry;
- String readKey = (String)entry.Key;
+ string readKey = (string)entry.Key;
ResourceLocator resLoc = new ResourceLocator(-1, entry.Value);
_resCache.Add(readKey, resLoc);
if (ignoreCase)
@@ -375,7 +375,7 @@ namespace System.Resources
while (en.MoveNext())
{
// Note: Always ask for the resource key before the data position.
- String currentKey = (String)en.Key;
+ string currentKey = (string)en.Key;
int dataPos = en.DataPosition;
ResourceLocator resLoc = new ResourceLocator(dataPos, null);
_caseInsensitiveTable.Add(currentKey, resLoc);
@@ -383,7 +383,7 @@ namespace System.Resources
}
_haveReadFromReader = true;
}
- Object obj = null;
+ object obj = null;
bool found = false;
bool keyInWrongCase = false;
if (_defaultReader != null)
@@ -410,11 +410,11 @@ namespace System.Resources
// The last parameter indicates whether the lookup required a
// case-insensitive lookup to succeed, indicating we shouldn't add
// the ResourceLocation to our case-sensitive cache.
- private Object ResolveResourceLocator(ResourceLocator resLocation, String key, Dictionary<String, ResourceLocator> copyOfCache, bool keyInWrongCase)
+ private object ResolveResourceLocator(ResourceLocator resLocation, string key, Dictionary<string, ResourceLocator> copyOfCache, bool keyInWrongCase)
{
// We need to explicitly resolve loosely linked manifest
// resources, and we need to resolve ResourceLocators with null objects.
- Object value = resLocation.Value;
+ object value = resLocation.Value;
if (value == null)
{
ResourceTypeCode typeCode;
diff --git a/src/System.Private.CoreLib/shared/System/Resources/SatelliteContractVersionAttribute.cs b/src/System.Private.CoreLib/shared/System/Resources/SatelliteContractVersionAttribute.cs
index 070744767..aeccadca9 100644
--- a/src/System.Private.CoreLib/shared/System/Resources/SatelliteContractVersionAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/Resources/SatelliteContractVersionAttribute.cs
@@ -19,13 +19,13 @@ namespace System.Resources
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
public sealed class SatelliteContractVersionAttribute : Attribute
{
- public SatelliteContractVersionAttribute(String version)
+ public SatelliteContractVersionAttribute(string version)
{
if (version == null)
throw new ArgumentNullException(nameof(version));
Version = version;
}
- public String Version { get; }
+ public string Version { get; }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerArgumentExpressionAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerArgumentExpressionAttribute.cs
new file mode 100644
index 000000000..6e1c4c56c
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CallerArgumentExpressionAttribute.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
+ public sealed class CallerArgumentExpressionAttribute : Attribute
+ {
+ public CallerArgumentExpressionAttribute(string parameterName)
+ {
+ ParameterName = parameterName;
+ }
+
+ public string ParameterName { get; }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs
index b6f12299b..8f7b0c809 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs
@@ -33,7 +33,7 @@ namespace System.Runtime.CompilerServices
[StructLayout(LayoutKind.Auto)]
public readonly struct ConfiguredValueTaskAwaiter : ICriticalNotifyCompletion
#if CORECLR
- , IValueTaskAwaiter
+ , IStateMachineBoxAwareAwaiter
#endif
{
/// <summary>The value being awaited.</summary>
@@ -59,55 +59,64 @@ namespace System.Runtime.CompilerServices
/// <summary>Schedules the continuation action for the <see cref="ConfiguredValueTaskAwaitable"/>.</summary>
public void OnCompleted(Action continuation)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj is Task t)
{
- _value.UnsafeGetTask().ConfigureAwait(_value.ContinueOnCapturedContext).GetAwaiter().OnCompleted(continuation);
+ t.ConfigureAwait(_value._continueOnCapturedContext).GetAwaiter().OnCompleted(continuation);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token,
+ Unsafe.As<IValueTaskSource>(obj).OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token,
ValueTaskSourceOnCompletedFlags.FlowExecutionContext |
- (_value.ContinueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None));
+ (_value._continueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None));
}
else
{
- ValueTask.CompletedTask.ConfigureAwait(_value.ContinueOnCapturedContext).GetAwaiter().OnCompleted(continuation);
+ ValueTask.CompletedTask.ConfigureAwait(_value._continueOnCapturedContext).GetAwaiter().OnCompleted(continuation);
}
}
/// <summary>Schedules the continuation action for the <see cref="ConfiguredValueTaskAwaitable"/>.</summary>
public void UnsafeOnCompleted(Action continuation)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj is Task t)
{
- _value.UnsafeGetTask().ConfigureAwait(_value.ContinueOnCapturedContext).GetAwaiter().UnsafeOnCompleted(continuation);
+ t.ConfigureAwait(_value._continueOnCapturedContext).GetAwaiter().UnsafeOnCompleted(continuation);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token,
- _value.ContinueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None);
+ Unsafe.As<IValueTaskSource>(obj).OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token,
+ _value._continueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None);
}
else
{
- ValueTask.CompletedTask.ConfigureAwait(_value.ContinueOnCapturedContext).GetAwaiter().UnsafeOnCompleted(continuation);
+ ValueTask.CompletedTask.ConfigureAwait(_value._continueOnCapturedContext).GetAwaiter().UnsafeOnCompleted(continuation);
}
}
#if CORECLR
- void IValueTaskAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box)
+ void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj is Task t)
{
- TaskAwaiter.UnsafeOnCompletedInternal(_value.UnsafeGetTask(), box, _value.ContinueOnCapturedContext);
+ TaskAwaiter.UnsafeOnCompletedInternal(t, box, _value._continueOnCapturedContext);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(ValueTaskAwaiter.s_invokeAsyncStateMachineBox, box, _value._token,
- _value.ContinueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None);
+ Unsafe.As<IValueTaskSource>(obj).OnCompleted(ValueTaskAwaiter.s_invokeAsyncStateMachineBox, box, _value._token,
+ _value._continueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None);
}
else
{
- TaskAwaiter.UnsafeOnCompletedInternal(Task.CompletedTask, box, _value.ContinueOnCapturedContext);
+ TaskAwaiter.UnsafeOnCompletedInternal(Task.CompletedTask, box, _value._continueOnCapturedContext);
}
}
#endif
@@ -135,7 +144,7 @@ namespace System.Runtime.CompilerServices
[StructLayout(LayoutKind.Auto)]
public readonly struct ConfiguredValueTaskAwaiter : ICriticalNotifyCompletion
#if CORECLR
- , IValueTaskAwaiter
+ , IStateMachineBoxAwareAwaiter
#endif
{
/// <summary>The value being awaited.</summary>
@@ -161,58 +170,67 @@ namespace System.Runtime.CompilerServices
/// <summary>Schedules the continuation action for the <see cref="ConfiguredValueTaskAwaitable{TResult}"/>.</summary>
public void OnCompleted(Action continuation)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj is Task<TResult> t)
{
- _value.UnsafeGetTask().ConfigureAwait(_value.ContinueOnCapturedContext).GetAwaiter().OnCompleted(continuation);
+ t.ConfigureAwait(_value._continueOnCapturedContext).GetAwaiter().OnCompleted(continuation);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token,
+ Unsafe.As<IValueTaskSource<TResult>>(obj).OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token,
ValueTaskSourceOnCompletedFlags.FlowExecutionContext |
- (_value.ContinueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None));
+ (_value._continueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None));
}
else
{
- ValueTask.CompletedTask.ConfigureAwait(_value.ContinueOnCapturedContext).GetAwaiter().OnCompleted(continuation);
+ ValueTask.CompletedTask.ConfigureAwait(_value._continueOnCapturedContext).GetAwaiter().OnCompleted(continuation);
}
}
/// <summary>Schedules the continuation action for the <see cref="ConfiguredValueTaskAwaitable{TResult}"/>.</summary>
public void UnsafeOnCompleted(Action continuation)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj is Task<TResult> t)
{
- _value.UnsafeGetTask().ConfigureAwait(_value.ContinueOnCapturedContext).GetAwaiter().UnsafeOnCompleted(continuation);
+ t.ConfigureAwait(_value._continueOnCapturedContext).GetAwaiter().UnsafeOnCompleted(continuation);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token,
- _value.ContinueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None);
+ Unsafe.As<IValueTaskSource<TResult>>(obj).OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token,
+ _value._continueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None);
}
else
{
- ValueTask.CompletedTask.ConfigureAwait(_value.ContinueOnCapturedContext).GetAwaiter().UnsafeOnCompleted(continuation);
+ ValueTask.CompletedTask.ConfigureAwait(_value._continueOnCapturedContext).GetAwaiter().UnsafeOnCompleted(continuation);
}
}
#if CORECLR
- void IValueTaskAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box)
+ void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj is Task<TResult> t)
{
- TaskAwaiter.UnsafeOnCompletedInternal(_value.UnsafeGetTask(), box, _value.ContinueOnCapturedContext);
+ TaskAwaiter.UnsafeOnCompletedInternal(t, box, _value._continueOnCapturedContext);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(ValueTaskAwaiter.s_invokeAsyncStateMachineBox, box, _value._token,
- _value.ContinueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None);
+ Unsafe.As<IValueTaskSource<TResult>>(obj).OnCompleted(ValueTaskAwaiter.s_invokeAsyncStateMachineBox, box, _value._token,
+ _value._continueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None);
}
else
{
- TaskAwaiter.UnsafeOnCompletedInternal(Task.CompletedTask, box, _value.ContinueOnCapturedContext);
+ TaskAwaiter.UnsafeOnCompletedInternal(Task.CompletedTask, box, _value._continueOnCapturedContext);
}
}
#endif
}
}
-} \ No newline at end of file
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CustomConstantAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CustomConstantAttribute.cs
index f75693eb4..d3116cc8a 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CustomConstantAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/CustomConstantAttribute.cs
@@ -7,6 +7,6 @@ namespace System.Runtime.CompilerServices
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)]
public abstract class CustomConstantAttribute : Attribute
{
- public abstract Object Value { get; }
+ public abstract object Value { get; }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs
index 813e6803b..44c497706 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs
@@ -14,6 +14,6 @@ namespace System.Runtime.CompilerServices
_date = new DateTime(ticks);
}
- public override Object Value => _date;
+ public override object Value => _date;
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DecimalConstantAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DecimalConstantAttribute.cs
index 19db84eb4..521a3abe9 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DecimalConstantAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DecimalConstantAttribute.cs
@@ -9,7 +9,7 @@ namespace System.Runtime.CompilerServices
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)]
public sealed class DecimalConstantAttribute : Attribute
{
- private Decimal _dec;
+ private decimal _dec;
[CLSCompliant(false)]
public DecimalConstantAttribute(
@@ -20,7 +20,7 @@ namespace System.Runtime.CompilerServices
uint low
)
{
- _dec = new Decimal((int)low, (int)mid, (int)hi, (sign != 0), scale);
+ _dec = new decimal((int)low, (int)mid, (int)hi, (sign != 0), scale);
}
public DecimalConstantAttribute(
@@ -31,9 +31,9 @@ namespace System.Runtime.CompilerServices
int low
)
{
- _dec = new Decimal(low, mid, hi, (sign != 0), scale);
+ _dec = new decimal(low, mid, hi, (sign != 0), scale);
}
- public Decimal Value => _dec;
+ public decimal Value => _dec;
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DependencyAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DependencyAttribute.cs
index 0fe07edc9..7bb7acec4 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DependencyAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/DependencyAttribute.cs
@@ -7,13 +7,13 @@ namespace System.Runtime.CompilerServices
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public sealed class DependencyAttribute : Attribute
{
- public DependencyAttribute(String dependentAssemblyArgument, LoadHint loadHintArgument)
+ public DependencyAttribute(string dependentAssemblyArgument, LoadHint loadHintArgument)
{
DependentAssembly = dependentAssemblyArgument;
LoadHint = loadHintArgument;
}
- public String DependentAssembly { get; }
+ public string DependentAssembly { get; }
public LoadHint LoadHint { get; }
}
} \ No newline at end of file
diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastable.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ICastable.cs
index aac87b8a8..37e77358a 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ICastable.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ICastable.cs
@@ -2,16 +2,15 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-//
-// Support for dynamic interface casting. Specifically implementing this interface on a type will allow the
-// type to support interfaces (for the purposes of casting and interface dispatch) that do not appear in its
-// interface map.
-//
-
using System;
namespace System.Runtime.CompilerServices
{
+ /// <summary>
+ /// Support for dynamic interface casting. Specifically implementing this interface on a type will allow the
+ /// type to support interfaces (for the purposes of casting and interface dispatch) that do not appear in its
+ /// interface map.
+ /// </summary>
public interface ICastable
{
// This is called if casting this object to the given interface type would otherwise fail. Casting
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IndexerNameAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IndexerNameAttribute.cs
index ea843b3da..bc76250ad 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IndexerNameAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/IndexerNameAttribute.cs
@@ -7,7 +7,7 @@ namespace System.Runtime.CompilerServices
[AttributeUsage(AttributeTargets.Property, Inherited = true)]
public sealed class IndexerNameAttribute : Attribute
{
- public IndexerNameAttribute(String indexerName)
+ public IndexerNameAttribute(string indexerName)
{
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs
index f3842ec56..6c6fe9e25 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs
@@ -22,11 +22,11 @@ namespace System.Runtime.CompilerServices
{
}
- public ReferenceAssemblyAttribute(String description)
+ public ReferenceAssemblyAttribute(string description)
{
Description = description;
}
- public String Description { get; }
+ public string Description { get; }
}
}
diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/TaskAwaiter.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TaskAwaiter.cs
index 33b5b0b26..030278dcf 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/TaskAwaiter.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/TaskAwaiter.cs
@@ -5,7 +5,6 @@
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
//
-
//
// Types for awaiting Task and Task<T>. These types are emitted from Task{<T>}.GetAwaiter
// and Task{<T>}.ConfigureAwait. They are meant to be used only by the compiler, e.g.
@@ -39,10 +38,12 @@
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
using System.Diagnostics;
+using System.Diagnostics.Tracing;
using System.Threading;
using System.Threading.Tasks;
-
+#if !CORECLR
using Internal.Threading.Tasks.Tracing;
+#endif
// NOTE: For performance reasons, initialization is not verified. If a developer
// incorrectly initializes a task awaiter, which should only be done by the compiler,
@@ -54,10 +55,13 @@ namespace System.Runtime.CompilerServices
{
/// <summary>Provides an awaiter for awaiting a <see cref="System.Threading.Tasks.Task"/>.</summary>
/// <remarks>This type is intended for compiler use only.</remarks>
- public readonly struct TaskAwaiter : ICriticalNotifyCompletion
+ public readonly struct TaskAwaiter : ICriticalNotifyCompletion, ITaskAwaiter
{
+ // WARNING: Unsafe.As is used to access the generic TaskAwaiter<> as TaskAwaiter.
+ // Its layout must remain the same.
+
/// <summary>The task being awaited.</summary>
- private readonly Task m_task;
+ internal readonly Task m_task;
/// <summary>Initializes the <see cref="TaskAwaiter"/>.</summary>
/// <param name="task">The <see cref="System.Threading.Tasks.Task"/> to be awaited.</param>
@@ -99,7 +103,7 @@ namespace System.Runtime.CompilerServices
/// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
/// <exception cref="System.Threading.Tasks.TaskCanceledException">The task was canceled.</exception>
/// <exception cref="System.Exception">The task completed in a Faulted state.</exception>
- [StackTraceHidden]
+ [StackTraceHidden]
public void GetResult()
{
ValidateEnd(m_task);
@@ -110,7 +114,7 @@ namespace System.Runtime.CompilerServices
/// prior to completing the await.
/// </summary>
/// <param name="task">The awaited task.</param>
- [StackTraceHidden]
+ [StackTraceHidden]
internal static void ValidateEnd(Task task)
{
// Fast checks that can be inlined.
@@ -139,7 +143,7 @@ namespace System.Runtime.CompilerServices
// but where for one reason or another synchronous rather than asynchronous waiting is needed.
if (!task.IsCompleted)
{
- bool taskCompleted = task.InternalWait(Timeout.Infinite, default(CancellationToken));
+ bool taskCompleted = task.InternalWait(Timeout.Infinite, default);
Debug.Assert(taskCompleted, "With an infinite timeout, the task should have always completed.");
}
@@ -195,6 +199,7 @@ namespace System.Runtime.CompilerServices
/// <param name="task">The task being awaited.</param>
/// <param name="continuation">The action to invoke when the await operation completes.</param>
/// <param name="continueOnCapturedContext">Whether to capture and marshal back to the current context.</param>
+ /// <param name="flowExecutionContext">Whether to flow ExecutionContext across the await.</param>
/// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
/// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
/// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
@@ -204,7 +209,13 @@ namespace System.Runtime.CompilerServices
// If TaskWait* ETW events are enabled, trace a beginning event for this await
// and set up an ending event to be traced when the asynchronous await completes.
- if (TaskTrace.Enabled)
+ if (
+#if CORECLR
+ TplEtwProvider.Log.IsEnabled() || Task.s_asyncDebuggingEnabled
+#else
+ TaskTrace.Enabled
+#endif
+ )
{
continuation = OutputWaitEtwEvents(task, continuation);
}
@@ -213,6 +224,31 @@ namespace System.Runtime.CompilerServices
task.SetContinuationForAwait(continuation, continueOnCapturedContext, flowExecutionContext);
}
+#if CORECLR
+ /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="task">The task being awaited.</param>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <param name="continueOnCapturedContext">Whether to capture and marshal back to the current context.</param>
+ /// <param name="flowExecutionContext">Whether to flow ExecutionContext across the await.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ internal static void UnsafeOnCompletedInternal(Task task, IAsyncStateMachineBox stateMachineBox, bool continueOnCapturedContext)
+ {
+ Debug.Assert(stateMachineBox != null);
+
+ // If TaskWait* ETW events are enabled, trace a beginning event for this await
+ // and set up an ending event to be traced when the asynchronous await completes.
+ if (TplEtwProvider.Log.IsEnabled() || Task.s_asyncDebuggingEnabled)
+ {
+ task.SetContinuationForAwait(OutputWaitEtwEvents(task, stateMachineBox.MoveNextAction), continueOnCapturedContext, flowExecutionContext: false);
+ }
+ else
+ {
+ task.UnsafeSetContinuationForAwait(stateMachineBox, continueOnCapturedContext);
+ }
+ }
+#endif
/// <summary>
/// Outputs a WaitBegin ETW event, and augments the continuation action to output a WaitEnd ETW event.
/// </summary>
@@ -223,6 +259,28 @@ namespace System.Runtime.CompilerServices
{
Debug.Assert(task != null, "Need a task to wait on");
Debug.Assert(continuation != null, "Need a continuation to invoke when the wait completes");
+#if CORECLR
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ Task.AddToActiveTasks(task);
+ }
+
+ var etwLog = TplEtwProvider.Log;
+
+ if (etwLog.IsEnabled())
+ {
+ // ETW event for Task Wait Begin
+ var currentTaskAtBegin = Task.InternalCurrent;
+
+ // If this task's continuation is another task, get it.
+ var continuationTask = AsyncMethodBuilderCore.TryGetContinuationTask(continuation);
+ etwLog.TaskWaitBegin(
+ (currentTaskAtBegin != null ? currentTaskAtBegin.m_taskScheduler.Id : TaskScheduler.Default.Id),
+ (currentTaskAtBegin != null ? currentTaskAtBegin.Id : 0),
+ task.Id, TplEtwProvider.TaskWaitBehavior.Asynchronous,
+ (continuationTask != null ? continuationTask.Id : 0));
+ }
+#else
Debug.Assert(TaskTrace.Enabled, "Should only be used when ETW tracing is enabled");
// ETW event for Task Wait Begin
@@ -231,12 +289,51 @@ namespace System.Runtime.CompilerServices
(currentTaskAtBegin != null ? currentTaskAtBegin.m_taskScheduler.Id : TaskScheduler.Default.Id),
(currentTaskAtBegin != null ? currentTaskAtBegin.Id : 0),
task.Id);
+#endif
// Create a continuation action that outputs the end event and then invokes the user
// provided delegate. This incurs the allocations for the closure/delegate, but only if the event
// is enabled, and in doing so it allows us to pass the awaited task's information into the end event
// in a purely pay-for-play manner (the alternatively would be to increase the size of TaskAwaiter
// just for this ETW purpose, not pay-for-play, since GetResult would need to know whether a real yield occurred).
+#if CORECLR
+ return AsyncMethodBuilderCore.CreateContinuationWrapper(continuation, (innerContinuation,innerTask) =>
+ {
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ Task.RemoveFromActiveTasks(innerTask.Id);
+ }
+
+ TplEtwProvider innerEtwLog = TplEtwProvider.Log;
+
+ // ETW event for Task Wait End.
+ Guid prevActivityId = new Guid();
+ bool bEtwLogEnabled = innerEtwLog.IsEnabled();
+ if (bEtwLogEnabled)
+ {
+ var currentTaskAtEnd = Task.InternalCurrent;
+ innerEtwLog.TaskWaitEnd(
+ (currentTaskAtEnd != null ? currentTaskAtEnd.m_taskScheduler.Id : TaskScheduler.Default.Id),
+ (currentTaskAtEnd != null ? currentTaskAtEnd.Id : 0),
+ innerTask.Id);
+
+ // Ensure the continuation runs under the activity ID of the task that completed for the
+ // case the antecedent is a promise (in the other cases this is already the case).
+ if (innerEtwLog.TasksSetActivityIds && (innerTask.Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0)
+ EventSource.SetCurrentThreadActivityId(TplEtwProvider.CreateGuidForTaskID(innerTask.Id), out prevActivityId);
+ }
+
+ // Invoke the original continuation provided to OnCompleted.
+ innerContinuation();
+
+ if (bEtwLogEnabled)
+ {
+ innerEtwLog.TaskWaitContinuationComplete(innerTask.Id);
+ if (innerEtwLog.TasksSetActivityIds && (innerTask.Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0)
+ EventSource.SetCurrentThreadActivityId(prevActivityId);
+ }
+ }, task);
+#else
return () =>
{
// ETW event for Task Wait End.
@@ -252,13 +349,17 @@ namespace System.Runtime.CompilerServices
// Invoke the original continuation provided to OnCompleted.
continuation();
};
+#endif
}
}
/// <summary>Provides an awaiter for awaiting a <see cref="System.Threading.Tasks.Task{TResult}"/>.</summary>
/// <remarks>This type is intended for compiler use only.</remarks>
- public readonly struct TaskAwaiter<TResult> : ICriticalNotifyCompletion
+ public readonly struct TaskAwaiter<TResult> : ICriticalNotifyCompletion, ITaskAwaiter
{
+ // WARNING: Unsafe.As is used to access TaskAwaiter<> as the non-generic TaskAwaiter.
+ // Its layout must remain the same.
+
/// <summary>The task being awaited.</summary>
private readonly Task<TResult> m_task;
@@ -311,6 +412,20 @@ namespace System.Runtime.CompilerServices
}
}
+ /// <summary>
+ /// Marker interface used to know whether a particular awaiter is either a
+ /// TaskAwaiter or a TaskAwaiter`1. It must not be implemented by any other
+ /// awaiters.
+ /// </summary>
+ internal interface ITaskAwaiter { }
+
+ /// <summary>
+ /// Marker interface used to know whether a particular awaiter is either a
+ /// CTA.ConfiguredTaskAwaiter or a CTA`1.ConfiguredTaskAwaiter. It must not
+ /// be implemented by any other awaiters.
+ /// </summary>
+ internal interface IConfiguredTaskAwaiter { }
+
/// <summary>Provides an awaitable object that allows for configured awaits on <see cref="System.Threading.Tasks.Task"/>.</summary>
/// <remarks>This type is intended for compiler use only.</remarks>
public readonly struct ConfiguredTaskAwaitable
@@ -338,12 +453,15 @@ namespace System.Runtime.CompilerServices
/// <summary>Provides an awaiter for a <see cref="ConfiguredTaskAwaitable"/>.</summary>
/// <remarks>This type is intended for compiler use only.</remarks>
- public readonly struct ConfiguredTaskAwaiter : ICriticalNotifyCompletion
+ public readonly struct ConfiguredTaskAwaiter : ICriticalNotifyCompletion, IConfiguredTaskAwaiter
{
+ // WARNING: Unsafe.As is used to access the generic ConfiguredTaskAwaiter as this.
+ // Its layout must remain the same.
+
/// <summary>The task being awaited.</summary>
- private readonly Task m_task;
+ internal readonly Task m_task;
/// <summary>Whether to attempt marshaling back to the original context.</summary>
- private readonly bool m_continueOnCapturedContext;
+ internal readonly bool m_continueOnCapturedContext;
/// <summary>Initializes the <see cref="ConfiguredTaskAwaiter"/>.</summary>
/// <param name="task">The <see cref="System.Threading.Tasks.Task"/> to await.</param>
@@ -425,8 +543,11 @@ namespace System.Runtime.CompilerServices
/// <summary>Provides an awaiter for a <see cref="ConfiguredTaskAwaitable{TResult}"/>.</summary>
/// <remarks>This type is intended for compiler use only.</remarks>
- public readonly struct ConfiguredTaskAwaiter : ICriticalNotifyCompletion
+ public readonly struct ConfiguredTaskAwaiter : ICriticalNotifyCompletion, IConfiguredTaskAwaiter
{
+ // WARNING: Unsafe.As is used to access this as the non-generic ConfiguredTaskAwaiter.
+ // Its layout must remain the same.
+
/// <summary>The task being awaited.</summary>
private readonly Task<TResult> m_task;
/// <summary>Whether to attempt marshaling back to the original context.</summary>
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs
index 221a1a437..02b5910b7 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs
@@ -6,12 +6,16 @@ using System.Diagnostics;
using System.Threading.Tasks;
using System.Threading.Tasks.Sources;
+#if !netstandard
+using Internal.Runtime.CompilerServices;
+#endif
+
namespace System.Runtime.CompilerServices
{
/// <summary>Provides an awaiter for a <see cref="ValueTask"/>.</summary>
public readonly struct ValueTaskAwaiter : ICriticalNotifyCompletion
#if CORECLR
- , IValueTaskAwaiter
+ , IStateMachineBoxAwareAwaiter
#endif
{
/// <summary>Shim used to invoke an <see cref="Action"/> passed as the state argument to a <see cref="Action{Object}"/>.</summary>
@@ -48,13 +52,16 @@ namespace System.Runtime.CompilerServices
/// <summary>Schedules the continuation action for this ValueTask.</summary>
public void OnCompleted(Action continuation)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj is Task t)
{
- _value.UnsafeGetTask().GetAwaiter().OnCompleted(continuation);
+ t.GetAwaiter().OnCompleted(continuation);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(s_invokeActionDelegate, continuation, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext | ValueTaskSourceOnCompletedFlags.FlowExecutionContext);
+ Unsafe.As<IValueTaskSource>(obj).OnCompleted(s_invokeActionDelegate, continuation, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext | ValueTaskSourceOnCompletedFlags.FlowExecutionContext);
}
else
{
@@ -65,13 +72,16 @@ namespace System.Runtime.CompilerServices
/// <summary>Schedules the continuation action for this ValueTask.</summary>
public void UnsafeOnCompleted(Action continuation)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj is Task t)
{
- _value.UnsafeGetTask().GetAwaiter().UnsafeOnCompleted(continuation);
+ t.GetAwaiter().UnsafeOnCompleted(continuation);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(s_invokeActionDelegate, continuation, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext);
+ Unsafe.As<IValueTaskSource>(obj).OnCompleted(s_invokeActionDelegate, continuation, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext);
}
else
{
@@ -80,15 +90,18 @@ namespace System.Runtime.CompilerServices
}
#if CORECLR
- void IValueTaskAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box)
+ void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj is Task t)
{
- TaskAwaiter.UnsafeOnCompletedInternal(_value.UnsafeGetTask(), box, continueOnCapturedContext: true);
+ TaskAwaiter.UnsafeOnCompletedInternal(t, box, continueOnCapturedContext: true);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(s_invokeAsyncStateMachineBox, box, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext);
+ Unsafe.As<IValueTaskSource>(obj).OnCompleted(s_invokeAsyncStateMachineBox, box, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext);
}
else
{
@@ -105,7 +118,7 @@ namespace System.Runtime.CompilerServices
return;
}
- box.Invoke(null);
+ box.MoveNext();
};
#endif
}
@@ -113,7 +126,7 @@ namespace System.Runtime.CompilerServices
/// <summary>Provides an awaiter for a <see cref="ValueTask{TResult}"/>.</summary>
public readonly struct ValueTaskAwaiter<TResult> : ICriticalNotifyCompletion
#if CORECLR
- , IValueTaskAwaiter
+ , IStateMachineBoxAwareAwaiter
#endif
{
/// <summary>The value being awaited.</summary>
@@ -139,13 +152,16 @@ namespace System.Runtime.CompilerServices
/// <summary>Schedules the continuation action for this ValueTask.</summary>
public void OnCompleted(Action continuation)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj is Task<TResult> t)
{
- _value.UnsafeGetTask().GetAwaiter().OnCompleted(continuation);
+ t.GetAwaiter().OnCompleted(continuation);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext | ValueTaskSourceOnCompletedFlags.FlowExecutionContext);
+ Unsafe.As<IValueTaskSource<TResult>>(obj).OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext | ValueTaskSourceOnCompletedFlags.FlowExecutionContext);
}
else
{
@@ -156,13 +172,16 @@ namespace System.Runtime.CompilerServices
/// <summary>Schedules the continuation action for this ValueTask.</summary>
public void UnsafeOnCompleted(Action continuation)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj is Task<TResult> t)
{
- _value.UnsafeGetTask().GetAwaiter().UnsafeOnCompleted(continuation);
+ t.GetAwaiter().UnsafeOnCompleted(continuation);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext);
+ Unsafe.As<IValueTaskSource<TResult>>(obj).OnCompleted(ValueTaskAwaiter.s_invokeActionDelegate, continuation, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext);
}
else
{
@@ -171,15 +190,18 @@ namespace System.Runtime.CompilerServices
}
#if CORECLR
- void IValueTaskAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box)
+ void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box)
{
- if (_value.ObjectIsTask)
+ object obj = _value._obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj is Task<TResult> t)
{
- TaskAwaiter.UnsafeOnCompletedInternal(_value.UnsafeGetTask(), box, continueOnCapturedContext: true);
+ TaskAwaiter.UnsafeOnCompletedInternal(t, box, continueOnCapturedContext: true);
}
- else if (_value._obj != null)
+ else if (obj != null)
{
- _value.UnsafeGetValueTaskSource().OnCompleted(ValueTaskAwaiter.s_invokeAsyncStateMachineBox, box, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext);
+ Unsafe.As<IValueTaskSource<TResult>>(obj).OnCompleted(ValueTaskAwaiter.s_invokeAsyncStateMachineBox, box, _value._token, ValueTaskSourceOnCompletedFlags.UseSchedulingContext);
}
else
{
@@ -190,12 +212,12 @@ namespace System.Runtime.CompilerServices
}
#if CORECLR
- /// <summary>Internal interface used to enable optimizations from <see cref="AsyncTaskMethodBuilder"/> on <see cref="ValueTask"/>.</summary>>
- internal interface IValueTaskAwaiter
+ /// <summary>Internal interface used to enable optimizations from <see cref="AsyncTaskMethodBuilder"/>.</summary>>
+ internal interface IStateMachineBoxAwareAwaiter
{
/// <summary>Invoked to set <see cref="ITaskCompletionAction.Invoke"/> of the <paramref name="box"/> as the awaiter's continuation.</summary>
/// <param name="box">The box object.</param>
void AwaitUnsafeOnCompleted(IAsyncStateMachineBox box);
}
#endif
-} \ No newline at end of file
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/YieldAwaitable.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/YieldAwaitable.cs
index c45ef2484..68fd5ab8d 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/YieldAwaitable.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/YieldAwaitable.cs
@@ -47,6 +47,9 @@ namespace System.Runtime.CompilerServices
/// <summary>Provides an awaiter that switches into a target environment.</summary>
/// <remarks>This type is intended for compiler use only.</remarks>
public readonly struct YieldAwaiter : ICriticalNotifyCompletion
+#if CORECLR
+ , IStateMachineBoxAwareAwaiter
+#endif
{
/// <summary>Gets whether a yield is not required.</summary>
/// <remarks>This property is intended for compiler user rather than use directly in code.</remarks>
@@ -110,11 +113,46 @@ namespace System.Runtime.CompilerServices
// We're targeting a custom scheduler, so queue a task.
else
{
- Task.Factory.StartNew(continuation, default(CancellationToken), TaskCreationOptions.PreferFairness, scheduler);
+ Task.Factory.StartNew(continuation, default, TaskCreationOptions.PreferFairness, scheduler);
}
}
}
+#if CORECLR
+ void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box)
+ {
+ Debug.Assert(box != null);
+
+ // If tracing is enabled, delegate the Action-based implementation.
+ if (TplEtwProvider.Log.IsEnabled())
+ {
+ QueueContinuation(box.MoveNextAction, flowContext: false);
+ return;
+ }
+
+ // Otherwise, this is the same logic as in QueueContinuation, except using
+ // an IAsyncStateMachineBox instead of an Action, and only for flowContext:false.
+
+ SynchronizationContext syncCtx = SynchronizationContext.Current;
+ if (syncCtx != null && syncCtx.GetType() != typeof(SynchronizationContext))
+ {
+ syncCtx.Post(s => ((IAsyncStateMachineBox)s).MoveNext(), box);
+ }
+ else
+ {
+ TaskScheduler scheduler = TaskScheduler.Current;
+ if (scheduler == TaskScheduler.Default)
+ {
+ ThreadPool.UnsafeQueueUserWorkItem(s => ((IAsyncStateMachineBox)s).MoveNext(), box);
+ }
+ else
+ {
+ Task.Factory.StartNew(s => ((IAsyncStateMachineBox)s).MoveNext(), box, default, TaskCreationOptions.PreferFairness, scheduler);
+ }
+ }
+ }
+#endif
+
private static Action OutputCorrelationEtwEvent(Action continuation)
{
#if CORERT
@@ -153,7 +191,6 @@ namespace System.Runtime.CompilerServices
private static readonly WaitCallback s_waitCallbackRunAction = RunAction;
/// <summary>SendOrPostCallback that invokes the Action supplied as object state.</summary>
private static readonly SendOrPostCallback s_sendOrPostCallbackRunAction = RunAction;
-
/// <summary>Runs an Action delegate provided as state.</summary>
/// <param name="state">The Action delegate to invoke.</param>
private static void RunAction(object state) { ((Action)state)(); }
diff --git a/src/System.Private.CoreLib/src/System/Runtime/ConstrainedExecution/CriticalFinalizerObject.cs b/src/System.Private.CoreLib/shared/System/Runtime/ConstrainedExecution/CriticalFinalizerObject.cs
index 3f35f816a..3f35f816a 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/ConstrainedExecution/CriticalFinalizerObject.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/ConstrainedExecution/CriticalFinalizerObject.cs
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ExternalException.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ExternalException.cs
index 160fe301e..ab5a84c08 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ExternalException.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/ExternalException.cs
@@ -68,7 +68,7 @@ namespace System.Runtime.InteropServices
string s = className + " (0x" + HResult.ToString("X8", CultureInfo.InvariantCulture) + ")";
- if (!(String.IsNullOrEmpty(message)))
+ if (!(string.IsNullOrEmpty(message)))
{
s = s + ": " + message;
}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/HandleRef.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/HandleRef.cs
index 64d055313..c81a70199 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/HandleRef.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/HandleRef.cs
@@ -4,12 +4,12 @@
namespace System.Runtime.InteropServices
{
- public struct HandleRef
+ public readonly struct HandleRef
{
// ! Do not add or rearrange fields as the EE depends on this layout.
//------------------------------------------------------------------
- private object _wrapper;
- private IntPtr _handle;
+ private readonly object _wrapper;
+ private readonly IntPtr _handle;
//------------------------------------------------------------------
public HandleRef(object wrapper, IntPtr handle)
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MarshalDirectiveException.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MarshalDirectiveException.cs
index 1d0d59fab..3bb1140f5 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MarshalDirectiveException.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MarshalDirectiveException.cs
@@ -27,13 +27,13 @@ namespace System.Runtime.InteropServices
HResult = HResults.COR_E_MARSHALDIRECTIVE;
}
- public MarshalDirectiveException(String message)
+ public MarshalDirectiveException(string message)
: base(message)
{
HResult = HResults.COR_E_MARSHALDIRECTIVE;
}
- public MarshalDirectiveException(String message, Exception inner)
+ public MarshalDirectiveException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_MARSHALDIRECTIVE;
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.Fast.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.Fast.cs
index 8a5bb7539..e3cf0a84e 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.Fast.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.Fast.cs
@@ -2,9 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Buffers;
using System.Runtime.CompilerServices;
-using System.Collections.Generic;
using Internal.Runtime.CompilerServices;
namespace System.Runtime.InteropServices
@@ -15,8 +13,54 @@ namespace System.Runtime.InteropServices
/// </summary>
public static partial class MemoryMarshal
{
+ /// <summary>
+ /// Casts a Span of one primitive type <typeparamref name="T"/> to Span of bytes.
+ /// That type may not contain pointers or references. This is checked at runtime in order to preserve type safety.
+ /// </summary>
+ /// <param name="span">The source slice, of type <typeparamref name="T"/>.</param>
+ /// <exception cref="System.ArgumentException">
+ /// Thrown when <typeparamref name="T"/> contains pointers.
+ /// </exception>
+ /// <exception cref="System.OverflowException">
+ /// Thrown if the Length property of the new Span would exceed int.MaxValue.
+ /// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Span<byte> AsBytes<T>(Span<T> span)
+ where T : struct
+ {
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+
+ return new Span<byte>(
+ ref Unsafe.As<T, byte>(ref GetReference(span)),
+ checked(span.Length * Unsafe.SizeOf<T>()));
+ }
+
+ /// <summary>
+ /// Casts a ReadOnlySpan of one primitive type <typeparamref name="T"/> to ReadOnlySpan of bytes.
+ /// That type may not contain pointers or references. This is checked at runtime in order to preserve type safety.
+ /// </summary>
+ /// <param name="span">The source slice, of type <typeparamref name="T"/>.</param>
+ /// <exception cref="System.ArgumentException">
+ /// Thrown when <typeparamref name="T"/> contains pointers.
+ /// </exception>
+ /// <exception cref="System.OverflowException">
+ /// Thrown if the Length property of the new Span would exceed int.MaxValue.
+ /// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ReadOnlySpan<byte> AsBytes<T>(ReadOnlySpan<T> span)
+ where T : struct
+ {
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+
+ return new ReadOnlySpan<byte>(
+ ref Unsafe.As<T, byte>(ref GetReference(span)),
+ checked(span.Length * Unsafe.SizeOf<T>()));
+ }
+
/// <summary>Creates a <see cref="Memory{T}"/> from a <see cref="ReadOnlyMemory{T}"/>.</summary>
- /// <param name="readOnlyMemory">The <see cref="ReadOnlyMemory{T}"/>.</param>
+ /// <param name="memory">The <see cref="ReadOnlyMemory{T}"/>.</param>
/// <returns>A <see cref="Memory{T}"/> representing the same memory as the <see cref="ReadOnlyMemory{T}"/>, but writable.</returns>
/// <remarks>
/// <see cref="AsMemory{T}(ReadOnlyMemory{T})"/> must be used with extreme caution. <see cref="ReadOnlyMemory{T}"/> is used
@@ -24,33 +68,48 @@ namespace System.Runtime.InteropServices
/// by <see cref="AsMemory{T}(ReadOnlyMemory{T})"/> should not be written to. The method exists to enable variables typed
/// as <see cref="Memory{T}"/> but only used for reading to store a <see cref="ReadOnlyMemory{T}"/>.
/// </remarks>
- public static Memory<T> AsMemory<T>(ReadOnlyMemory<T> readOnlyMemory) =>
- Unsafe.As<ReadOnlyMemory<T>, Memory<T>>(ref readOnlyMemory);
+ public static Memory<T> AsMemory<T>(ReadOnlyMemory<T> memory) =>
+ Unsafe.As<ReadOnlyMemory<T>, Memory<T>>(ref memory);
/// <summary>
/// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to the location where the 0th element
- /// would have been stored. Such a reference can be used for pinning but must never be dereferenced.
+ /// would have been stored. Such a reference may or may not be null. It can be used for pinning but must never be dereferenced.
/// </summary>
public static ref T GetReference<T>(Span<T> span) => ref span._pointer.Value;
/// <summary>
- /// Returns a reference to the 0th element of the ReadOnlySpan. If the Span is empty, returns a reference to the location where the 0th element
- /// would have been stored. Such a reference can be used for pinning but must never be dereferenced.
+ /// Returns a reference to the 0th element of the ReadOnlySpan. If the ReadOnlySpan is empty, returns a reference to the location where the 0th element
+ /// would have been stored. Such a reference may or may not be null. It can be used for pinning but must never be dereferenced.
/// </summary>
public static ref T GetReference<T>(ReadOnlySpan<T> span) => ref span._pointer.Value;
/// <summary>
+ /// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to fake non-null pointer. Such a reference can be used
+ /// for pinning but must never be dereferenced. This is useful for interop with methods that do not accept null pointers for zero-sized buffers.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static unsafe ref T GetNonNullPinnableReference<T>(Span<T> span) => ref (span.Length != 0) ? ref span._pointer.Value : ref Unsafe.AsRef<T>((void*)1);
+
+ /// <summary>
+ /// Returns a reference to the 0th element of the ReadOnlySpan. If the ReadOnlySpan is empty, returns a reference to fake non-null pointer. Such a reference
+ /// can be used for pinning but must never be dereferenced. This is useful for interop with methods that do not accept null pointers for zero-sized buffers.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static unsafe ref T GetNonNullPinnableReference<T>(ReadOnlySpan<T> span) => ref (span.Length != 0) ? ref span._pointer.Value : ref Unsafe.AsRef<T>((void*)1);
+
+ /// <summary>
/// Casts a Span of one primitive type <typeparamref name="TFrom"/> to another primitive type <typeparamref name="TTo"/>.
/// These types may not contain pointers or references. This is checked at runtime in order to preserve type safety.
/// </summary>
/// <remarks>
- /// Supported only for platforms that support misaligned memory access.
+ /// Supported only for platforms that support misaligned memory access or when the memory block is aligned by other means.
/// </remarks>
- /// <param name="source">The source slice, of type <typeparamref name="TFrom"/>.</param>
+ /// <param name="span">The source slice, of type <typeparamref name="TFrom"/>.</param>
/// <exception cref="System.ArgumentException">
/// Thrown when <typeparamref name="TFrom"/> or <typeparamref name="TTo"/> contains pointers.
/// </exception>
- public static Span<TTo> Cast<TFrom, TTo>(Span<TFrom> source)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Span<TTo> Cast<TFrom, TTo>(Span<TFrom> span)
where TFrom : struct
where TTo : struct
{
@@ -63,7 +122,7 @@ namespace System.Runtime.InteropServices
// and checked casts are faster and smaller.
uint fromSize = (uint)Unsafe.SizeOf<TFrom>();
uint toSize = (uint)Unsafe.SizeOf<TTo>();
- uint fromLength = (uint)source.Length;
+ uint fromLength = (uint)span.Length;
int toLength;
if (fromSize == toSize)
{
@@ -89,7 +148,7 @@ namespace System.Runtime.InteropServices
}
return new Span<TTo>(
- ref Unsafe.As<TFrom, TTo>(ref source._pointer.Value),
+ ref Unsafe.As<TFrom, TTo>(ref span._pointer.Value),
toLength);
}
@@ -98,13 +157,14 @@ namespace System.Runtime.InteropServices
/// These types may not contain pointers or references. This is checked at runtime in order to preserve type safety.
/// </summary>
/// <remarks>
- /// Supported only for platforms that support misaligned memory access.
+ /// Supported only for platforms that support misaligned memory access or when the memory block is aligned by other means.
/// </remarks>
- /// <param name="source">The source slice, of type <typeparamref name="TFrom"/>.</param>
+ /// <param name="span">The source slice, of type <typeparamref name="TFrom"/>.</param>
/// <exception cref="System.ArgumentException">
/// Thrown when <typeparamref name="TFrom"/> or <typeparamref name="TTo"/> contains pointers.
/// </exception>
- public static ReadOnlySpan<TTo> Cast<TFrom, TTo>(ReadOnlySpan<TFrom> source)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ReadOnlySpan<TTo> Cast<TFrom, TTo>(ReadOnlySpan<TFrom> span)
where TFrom : struct
where TTo : struct
{
@@ -117,7 +177,7 @@ namespace System.Runtime.InteropServices
// and checked casts are faster and smaller.
uint fromSize = (uint)Unsafe.SizeOf<TFrom>();
uint toSize = (uint)Unsafe.SizeOf<TTo>();
- uint fromLength = (uint)source.Length;
+ uint fromLength = (uint)span.Length;
int toLength;
if (fromSize == toSize)
{
@@ -143,7 +203,7 @@ namespace System.Runtime.InteropServices
}
return new ReadOnlySpan<TTo>(
- ref Unsafe.As<TFrom, TTo>(ref MemoryMarshal.GetReference(source)),
+ ref Unsafe.As<TFrom, TTo>(ref MemoryMarshal.GetReference(span)),
toLength);
}
@@ -154,6 +214,7 @@ namespace System.Runtime.InteropServices
/// </summary>
/// <param name="reference">A reference to data.</param>
/// <param name="length">The number of <typeparamref name="T"/> elements the memory contains.</param>
+ /// <returns>The lifetime of the returned span will not be validated for safety by span-aware languages.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> CreateSpan<T>(ref T reference, int length) => new Span<T>(ref reference, length);
@@ -164,6 +225,7 @@ namespace System.Runtime.InteropServices
/// </summary>
/// <param name="reference">A reference to data.</param>
/// <param name="length">The number of <typeparamref name="T"/> elements the memory contains.</param>
+ /// <returns>The lifetime of the returned span will not be validated for safety by span-aware languages.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ReadOnlySpan<T> CreateReadOnlySpan<T>(ref T reference, int length) => new ReadOnlySpan<T>(ref reference, length);
}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.cs
index 316ce12aa..fcc9c4f41 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.cs
@@ -5,6 +5,9 @@
using System.Buffers;
using System.Runtime.CompilerServices;
using System.Collections.Generic;
+using System.Diagnostics;
+
+using Internal.Runtime.CompilerServices;
namespace System.Runtime.InteropServices
{
@@ -18,72 +21,78 @@ namespace System.Runtime.InteropServices
/// Get an array segment from the underlying memory.
/// If unable to get the array segment, return false with a default array segment.
/// </summary>
- public static bool TryGetArray<T>(ReadOnlyMemory<T> readOnlyMemory, out ArraySegment<T> arraySegment)
+ public static bool TryGetArray<T>(ReadOnlyMemory<T> memory, out ArraySegment<T> segment)
{
- object obj = readOnlyMemory.GetObjectStartLength(out int index, out int length);
+ object obj = memory.GetObjectStartLength(out int index, out int length);
if (index < 0)
{
- if (((OwnedMemory<T>)obj).TryGetArray(out var segment))
+ Debug.Assert(length >= 0);
+ if (((MemoryManager<T>)obj).TryGetArray(out ArraySegment<T> arraySegment))
{
- arraySegment = new ArraySegment<T>(segment.Array, segment.Offset + (index & ReadOnlyMemory<T>.RemoveOwnedFlagBitMask), length);
+ segment = new ArraySegment<T>(arraySegment.Array, arraySegment.Offset + (index & ReadOnlyMemory<T>.RemoveFlagsBitMask), length);
return true;
}
}
else if (obj is T[] arr)
{
- arraySegment = new ArraySegment<T>(arr, index, length);
+ segment = new ArraySegment<T>(arr, index, length & ReadOnlyMemory<T>.RemoveFlagsBitMask);
return true;
}
- if (length == 0)
+ if ((length & ReadOnlyMemory<T>.RemoveFlagsBitMask) == 0)
{
-#if FEATURE_PORTABLE_SPAN
- arraySegment = new ArraySegment<T>(SpanHelpers.PerTypeValues<T>.EmptyArray);
-#else
- arraySegment = ArraySegment<T>.Empty;
-#endif // FEATURE_PORTABLE_SPAN
+ segment = ArraySegment<T>.Empty;
return true;
}
- arraySegment = default;
+ segment = default;
return false;
}
/// <summary>
- /// Gets an <see cref="OwnedMemory{T}"/> from the underlying readOnlyMemory.
- /// If unable to get the <typeparamref name="TOwner"/> type, returns false.
+ /// Gets an <see cref="MemoryManager{T}"/> from the underlying read-only memory.
+ /// If unable to get the <typeparamref name="TManager"/> type, returns false.
/// </summary>
- /// <typeparam name="T">The element type of the <paramref name="readOnlyMemory" />.</typeparam>
- /// <typeparam name="TOwner">The type of <see cref="OwnedMemory{T}"/> to try and retrive.</typeparam>
- /// <param name="readOnlyMemory">The memory to get the owner for.</param>
- /// <param name="ownedMemory">The returned owner of the <see cref="ReadOnlyMemory{T}"/>.</param>
+ /// <typeparam name="T">The element type of the <paramref name="memory" />.</typeparam>
+ /// <typeparam name="TManager">The type of <see cref="MemoryManager{T}"/> to try and retrive.</typeparam>
+ /// <param name="memory">The memory to get the manager for.</param>
+ /// <param name="manager">The returned manager of the <see cref="ReadOnlyMemory{T}"/>.</param>
/// <returns>A <see cref="bool"/> indicating if it was successful.</returns>
- public static bool TryGetOwnedMemory<T, TOwner>(ReadOnlyMemory<T> readOnlyMemory, out TOwner ownedMemory)
- where TOwner : OwnedMemory<T>
+ public static bool TryGetMemoryManager<T, TManager>(ReadOnlyMemory<T> memory, out TManager manager)
+ where TManager : MemoryManager<T>
{
- TOwner owner; // Use register for null comparison rather than byref
- ownedMemory = owner = readOnlyMemory.GetObjectStartLength(out int index, out int length) as TOwner;
- return !ReferenceEquals(owner, null);
+ TManager localManager; // Use register for null comparison rather than byref
+ manager = localManager = memory.GetObjectStartLength(out _, out _) as TManager;
+ return manager != null;
}
/// <summary>
- /// Gets an <see cref="OwnedMemory{T}"/> and <paramref name="index" />, <paramref name="length" /> from the underlying memory.
- /// If unable to get the <typeparamref name="TOwner"/> type, returns false.
+ /// Gets an <see cref="MemoryManager{T}"/> and <paramref name="start" />, <paramref name="length" /> from the underlying read-only memory.
+ /// If unable to get the <typeparamref name="TManager"/> type, returns false.
/// </summary>
- /// <typeparam name="T">The element type of the <paramref name="readOnlyMemory" />.</typeparam>
- /// <typeparam name="TOwner">The type of <see cref="OwnedMemory{T}"/> to try and retrive.</typeparam>
- /// <param name="readOnlyMemory">The memory to get the owner for.</param>
- /// <param name="ownedMemory">The returned owner of the <see cref="ReadOnlyMemory{T}"/>.</param>
- /// <param name="index">The offset from the start of the <paramref name="ownedMemory" /> that the <paramref name="readOnlyMemory" /> represents.</param>
- /// <param name="length">The length of the <paramref name="ownedMemory" /> that the <paramref name="readOnlyMemory" /> represents.</param>
+ /// <typeparam name="T">The element type of the <paramref name="memory" />.</typeparam>
+ /// <typeparam name="TManager">The type of <see cref="MemoryManager{T}"/> to try and retrive.</typeparam>
+ /// <param name="memory">The memory to get the manager for.</param>
+ /// <param name="manager">The returned manager of the <see cref="ReadOnlyMemory{T}"/>.</param>
+ /// <param name="start">The offset from the start of the <paramref name="manager" /> that the <paramref name="memory" /> represents.</param>
+ /// <param name="length">The length of the <paramref name="manager" /> that the <paramref name="memory" /> represents.</param>
/// <returns>A <see cref="bool"/> indicating if it was successful.</returns>
- public static bool TryGetOwnedMemory<T, TOwner>(ReadOnlyMemory<T> readOnlyMemory, out TOwner ownedMemory, out int index, out int length)
- where TOwner : OwnedMemory<T>
+ public static bool TryGetMemoryManager<T, TManager>(ReadOnlyMemory<T> memory, out TManager manager, out int start, out int length)
+ where TManager : MemoryManager<T>
{
- TOwner owner; // Use register for null comparison rather than byref
- ownedMemory = owner = readOnlyMemory.GetObjectStartLength(out index, out length) as TOwner;
- index &= ReadOnlyMemory<T>.RemoveOwnedFlagBitMask;
- return !ReferenceEquals(owner, null);
+ TManager localManager; // Use register for null comparison rather than byref
+ manager = localManager = memory.GetObjectStartLength(out start, out length) as TManager;
+ start &= ReadOnlyMemory<T>.RemoveFlagsBitMask;
+
+ Debug.Assert(length >= 0);
+
+ if (manager == null)
+ {
+ start = default;
+ length = default;
+ return false;
+ }
+ return true;
}
/// <summary>
@@ -100,15 +109,17 @@ namespace System.Runtime.InteropServices
}
/// <summary>Attempts to get the underlying <see cref="string"/> from a <see cref="ReadOnlyMemory{T}"/>.</summary>
- /// <param name="readOnlyMemory">The memory that may be wrapping a <see cref="string"/> object.</param>
+ /// <param name="memory">The memory that may be wrapping a <see cref="string"/> object.</param>
/// <param name="text">The string.</param>
/// <param name="start">The starting location in <paramref name="text"/>.</param>
/// <param name="length">The number of items in <paramref name="text"/>.</param>
/// <returns></returns>
- public static bool TryGetString(ReadOnlyMemory<char> readOnlyMemory, out string text, out int start, out int length)
+ public static bool TryGetString(ReadOnlyMemory<char> memory, out string text, out int start, out int length)
{
- if (readOnlyMemory.GetObjectStartLength(out int offset, out int count) is string s)
+ if (memory.GetObjectStartLength(out int offset, out int count) is string s)
{
+ Debug.Assert(offset >= 0);
+ Debug.Assert(count >= 0);
text = s;
start = offset;
length = count;
@@ -122,5 +133,159 @@ namespace System.Runtime.InteropServices
return false;
}
}
+
+ /// <summary>
+ /// Reads a structure of type T out of a read-only span of bytes.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static T Read<T>(ReadOnlySpan<byte> source)
+ where T : struct
+ {
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ {
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+ }
+ if (Unsafe.SizeOf<T>() > source.Length)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
+ }
+ return Unsafe.ReadUnaligned<T>(ref GetReference(source));
+ }
+
+ /// <summary>
+ /// Reads a structure of type T out of a span of bytes.
+ /// <returns>If the span is too small to contain the type T, return false.</returns>
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool TryRead<T>(ReadOnlySpan<byte> source, out T value)
+ where T : struct
+ {
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ {
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+ }
+ if (Unsafe.SizeOf<T>() > (uint)source.Length)
+ {
+ value = default;
+ return false;
+ }
+ value = Unsafe.ReadUnaligned<T>(ref GetReference(source));
+ return true;
+ }
+
+ /// <summary>
+ /// Writes a structure of type T into a span of bytes.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void Write<T>(Span<byte> destination, ref T value)
+ where T : struct
+ {
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ {
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+ }
+ if ((uint)Unsafe.SizeOf<T>() > (uint)destination.Length)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
+ }
+ Unsafe.WriteUnaligned<T>(ref GetReference(destination), value);
+ }
+
+ /// <summary>
+ /// Writes a structure of type T into a span of bytes.
+ /// <returns>If the span is too small to contain the type T, return false.</returns>
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool TryWrite<T>(Span<byte> destination, ref T value)
+ where T : struct
+ {
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ {
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+ }
+ if (Unsafe.SizeOf<T>() > (uint)destination.Length)
+ {
+ return false;
+ }
+ Unsafe.WriteUnaligned<T>(ref GetReference(destination), value);
+ return true;
+ }
+
+ /// <summary>
+ /// Re-interprets a span of bytes as a reference to structure of type T.
+ /// The type may not contain pointers or references. This is checked at runtime in order to preserve type safety.
+ /// </summary>
+ /// <remarks>
+ /// Supported only for platforms that support misaligned memory access or when the memory block is aligned by other means.
+ /// </remarks>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ref T AsRef<T>(Span<byte> span)
+ where T : struct
+ {
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ {
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+ }
+ if (Unsafe.SizeOf<T>() > (uint)span.Length)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
+ }
+ return ref Unsafe.As<byte, T>(ref GetReference(span));
+ }
+
+ /// <summary>
+ /// Re-interprets a span of bytes as a reference to structure of type T.
+ /// The type may not contain pointers or references. This is checked at runtime in order to preserve type safety.
+ /// </summary>
+ /// <remarks>
+ /// Supported only for platforms that support misaligned memory access or when the memory block is aligned by other means.
+ /// </remarks>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ref readonly T AsRef<T>(ReadOnlySpan<byte> span)
+ where T : struct
+ {
+ if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+ {
+ ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+ }
+ if (Unsafe.SizeOf<T>() > (uint)span.Length)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
+ }
+ return ref Unsafe.As<byte, T>(ref GetReference(span));
+ }
+
+ /// <summary>
+ /// Creates a new memory over the portion of the pre-pinned target array beginning
+ /// at 'start' index and ending at 'end' index (exclusive).
+ /// </summary>
+ /// <param name="array">The pre-pinned target array.</param>
+ /// <param name="start">The index at which to begin the memory.</param>
+ /// <param name="length">The number of items in the memory.</param>
+ /// <remarks>This method should only be called on an array that is already pinned and
+ /// that array should not be unpinned while the returned Memory<typeparamref name="T"/> is still in use.
+ /// Calling this method on an unpinned array could result in memory corruption.</remarks>
+ /// <remarks>Returns default when <paramref name="array"/> is null.</remarks>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception>
+ /// <exception cref="System.ArgumentOutOfRangeException">
+ /// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=Length).
+ /// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Memory<T> CreateFromPinnedArray<T>(T[] array, int start, int length)
+ {
+ if (array == null)
+ {
+ if (start != 0 || length != 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException();
+ return default;
+ }
+ if (default(T) == null && array.GetType() != typeof(T[]))
+ ThrowHelper.ThrowArrayTypeMismatchException();
+ if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start))
+ ThrowHelper.ThrowArgumentOutOfRangeException();
+
+ // Before using _length, check if _length < 0, then 'and' it with RemoveFlagsBitMask
+ return new Memory<T>((object)array, start, length | (1 << 31));
+ }
}
}
diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeCallableAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/NativeCallableAttribute.cs
index 32fc29593..bad4d7f6a 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeCallableAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/NativeCallableAttribute.cs
@@ -2,23 +2,28 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-using System.Runtime.CompilerServices;
-
namespace System.Runtime.InteropServices
{
- //BARTOK expects
+ /// <summary>
+ /// Any method marked with NativeCallableAttribute can be directly called from
+ /// native code. The function token can be loaded to a local variable using LDFTN
+ /// and passed as a callback to native method.
+ /// </summary>
[AttributeUsage(AttributeTargets.Method)]
public sealed class NativeCallableAttribute : Attribute
{
- // Optional. If omitted, then the method is native callable, but no EAT is emitted.
- public string EntryPoint;
-
- // Optional. If omitted a default will be chosen by the compiler.
- public CallingConvention CallingConvention;
-
public NativeCallableAttribute()
{
}
+
+ /// <summary>
+ /// Optional. If omitted, compiler will choose one for you.
+ /// </summary>
+ public CallingConvention CallingConvention;
+
+ /// <summary>
+ /// Optional. If omitted, then the method is native callable, but no EAT is emitted.
+ /// </summary>
+ public string EntryPoint;
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/SafeBuffer.cs b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/SafeBuffer.cs
index 455e41392..661a7edce 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/SafeBuffer.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/InteropServices/SafeBuffer.cs
@@ -77,7 +77,7 @@ namespace System.Runtime.InteropServices
{
// Steal UIntPtr.MaxValue as our uninitialized value.
private static readonly UIntPtr Uninitialized = (UIntPtr.Size == 4) ?
- ((UIntPtr)UInt32.MaxValue) : ((UIntPtr)UInt64.MaxValue);
+ ((UIntPtr)uint.MaxValue) : ((UIntPtr)ulong.MaxValue);
private UIntPtr _numBytes;
@@ -94,7 +94,7 @@ namespace System.Runtime.InteropServices
[CLSCompliant(false)]
public void Initialize(ulong numBytes)
{
- if (IntPtr.Size == 4 && numBytes > UInt32.MaxValue)
+ if (IntPtr.Size == 4 && numBytes > uint.MaxValue)
throw new ArgumentOutOfRangeException(nameof(numBytes), SR.ArgumentOutOfRange_AddressSpace);
if (numBytes >= (ulong)Uninitialized)
@@ -110,7 +110,7 @@ namespace System.Runtime.InteropServices
[CLSCompliant(false)]
public void Initialize(uint numElements, uint sizeOfEachElement)
{
- if (IntPtr.Size == 4 && numElements * sizeOfEachElement > UInt32.MaxValue)
+ if (IntPtr.Size == 4 && numElements * sizeOfEachElement > uint.MaxValue)
throw new ArgumentOutOfRangeException("numBytes", SR.ArgumentOutOfRange_AddressSpace);
if (numElements * sizeOfEachElement >= (ulong)Uninitialized)
@@ -198,7 +198,7 @@ namespace System.Runtime.InteropServices
SpaceCheck(ptr, sizeofT);
// return *(T*) (_ptr + byteOffset);
- T value = default(T);
+ T value = default;
bool mustCallRelease = false;
try
{
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Aes.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Aes.PlatformNotSupported.cs
new file mode 100644
index 000000000..0ad9634d1
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Aes.PlatformNotSupported.cs
@@ -0,0 +1,40 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.Arm.Arm64
+{
+ /// <summary>
+ /// This class provides access to the Arm64 AES Crypto intrinsics
+ ///
+ /// Arm64 CPU indicate support for this feature by setting
+ /// ID_AA64ISAR0_EL1.AES is 1 or better
+ /// </summary>
+ [CLSCompliant(false)]
+ public static class Aes
+ {
+ public static bool IsSupported { get { return false; } }
+ // <summary>
+ /// Performs AES single round decryption
+ /// vaesdq_u8 (uint8x16_t data, uint8x16_t key)
+ ///</summary>
+ public static Vector128<byte> Decrypt(Vector128<byte> value, Vector128<byte> roundKey) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs AES single round encryption
+ /// vaeseq_u8 (uint8x16_t data, uint8x16_t key)
+ ///</summary>
+ public static Vector128<byte> Encrypt(Vector128<byte> value, Vector128<byte> roundKey) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs AES Mix Columns
+ /// vaesmcq_u8 (uint8x16_t data)
+ ///</summary>
+ public static Vector128<byte> MixColumns(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs AES inverse mix columns
+ /// vaesimcq_u8 (uint8x16_t data)
+ ///</summary>
+ public static Vector128<byte> InverseMixColumns(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Aes.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Aes.cs
new file mode 100644
index 000000000..24c9342d9
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Aes.cs
@@ -0,0 +1,40 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.Arm.Arm64
+{
+ /// <summary>
+ /// This class provides access to the Arm64 AES Crypto intrinsics
+ ///
+ /// Arm64 CPU indicate support for this feature by setting
+ /// ID_AA64ISAR0_EL1.AES is 1 or better
+ /// </summary>
+ [CLSCompliant(false)]
+ public static class Aes
+ {
+ public static bool IsSupported { get => IsSupported; }
+ // <summary>
+ /// Performs AES single round decryption
+ /// vaesdq_u8 (uint8x16_t data, uint8x16_t key)
+ ///</summary>
+ public static Vector128<byte> Decrypt(Vector128<byte> value, Vector128<byte> roundKey) => Decrypt(value, roundKey);
+
+ // <summary>
+ /// Performs AES single round encryption
+ /// vaeseq_u8 (uint8x16_t data, uint8x16_t key)
+ ///</summary>
+ public static Vector128<byte> Encrypt(Vector128<byte> value, Vector128<byte> roundKey) => Encrypt(value, roundKey);
+
+ // <summary>
+ /// Performs AES Mix Columns
+ /// vaesmcq_u8 (uint8x16_t data)
+ ///</summary>
+ public static Vector128<byte> MixColumns(Vector128<byte> value) => MixColumns(value);
+
+ // <summary>
+ /// Performs AES inverse mix columns
+ /// vaesimcq_u8 (uint8x16_t data)
+ ///</summary>
+ public static Vector128<byte> InverseMixColumns(Vector128<byte> value) => InverseMixColumns(value);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Base.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Base.PlatformNotSupported.cs
new file mode 100644
index 000000000..0a13828ee
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Base.PlatformNotSupported.cs
@@ -0,0 +1,33 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+
+namespace System.Runtime.Intrinsics.Arm.Arm64
+{
+ /// <summary>
+ /// This class provides access to the Arm64 Base intrinsics
+ ///
+ /// These intrinsics are supported by all Arm64 CPUs
+ /// </summary>
+ [CLSCompliant(false)]
+ public static class Base
+ {
+ public static bool IsSupported { get { return false; }}
+
+ /// <summary>
+ /// Vector LeadingSignCount
+ /// Corresponds to integer forms of ARM64 CLS
+ /// </summary>
+ public static int LeadingSignCount(int value) { throw new PlatformNotSupportedException(); }
+ public static int LeadingSignCount(long value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector LeadingZeroCount
+ /// Corresponds to integer forms of ARM64 CLZ
+ /// </summary>
+ public static int LeadingZeroCount(int value) { throw new PlatformNotSupportedException(); }
+ public static int LeadingZeroCount(uint value) { throw new PlatformNotSupportedException(); }
+ public static int LeadingZeroCount(long value) { throw new PlatformNotSupportedException(); }
+ public static int LeadingZeroCount(ulong value) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Base.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Base.cs
new file mode 100644
index 000000000..fc0a19055
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Base.cs
@@ -0,0 +1,33 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+
+namespace System.Runtime.Intrinsics.Arm.Arm64
+{
+ /// <summary>
+ /// This class provides access to the Arm64 Base intrinsics
+ ///
+ /// These intrinsics are supported by all Arm64 CPUs
+ /// </summary>
+ [CLSCompliant(false)]
+ public static class Base
+ {
+ public static bool IsSupported { get { return false; }}
+
+ /// <summary>
+ /// Vector LeadingSignCount
+ /// Corresponds to integer forms of ARM64 CLS
+ /// </summary>
+ public static int LeadingSignCount(int value) => LeadingSignCount(value);
+ public static int LeadingSignCount(long value) => LeadingSignCount(value);
+
+ /// <summary>
+ /// Vector LeadingZeroCount
+ /// Corresponds to integer forms of ARM64 CLZ
+ /// </summary>
+ public static int LeadingZeroCount(int value) => LeadingZeroCount(value);
+ public static int LeadingZeroCount(uint value) => LeadingZeroCount(value);
+ public static int LeadingZeroCount(long value) => LeadingZeroCount(value);
+ public static int LeadingZeroCount(ulong value) => LeadingZeroCount(value);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha1.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha1.PlatformNotSupported.cs
new file mode 100644
index 000000000..9b6c5aac6
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha1.PlatformNotSupported.cs
@@ -0,0 +1,54 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.Arm.Arm64
+{
+ /// <summary>
+ /// This class provides access to the Arm64 SHA1 Crypto intrinsics
+ ///
+ /// Arm64 CPU indicate support for this feature by setting
+ /// ID_AA64ISAR0_EL1.SHA1 is 1 or better
+ /// </summary>
+ [CLSCompliant(false)]
+ public static class Sha1
+ {
+
+ public static bool IsSupported { get { return false; } }
+
+ // <summary>
+ /// Performs SHA1 hash update choose form.
+ /// vsha1cq_u32 (uint32x4_t hash_abcd, uint32_t hash_e, uint32x4_t wk)
+ ///</summary>
+ public static Vector128<uint> HashChoose(Vector128<uint> hash_abcd, uint hash_e, Vector128<uint>wk) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs SHA1 hash update majority form.
+ /// vsha1mq_u32 (uint32x4_t hash_abcd, uint32_t hash_e, uint32x4_t wk)
+ ///</summary>
+ public static Vector128<uint> HashMajority(Vector128<uint> hash_abcd, uint hash_e, Vector128<uint>wk) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs SHA1 hash update parity form.
+ /// vsha1pq_u32 (uint32x4_t hash_abcd, uint32_t hash_e, uint32x4_t wk)
+ ///</summary>
+ public static Vector128<uint> HashParity(Vector128<uint> hash_abcd, uint hash_e, Vector128<uint>wk) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs SHA1 fixed rotate
+ /// vsha1h_u32 (uint32_t hash_e)
+ ///</summary>
+ public static uint FixedRotate(uint hash_e) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs SHA1 schedule update 0
+ /// vsha1su0q_u32 (uint32x4_t w0_3, uint32x4_t w4_7, uint32x4_t w8_11)
+ ///</summary>
+ public static Vector128<uint> SchedulePart1(Vector128<uint> w0_3, Vector128<uint> w4_7, Vector128<uint> w8_11) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs SHA1 schedule update 1
+ /// vsha1su1q_u32 (uint32x4_t tw0_3, uint32x4_t w12_15)
+ ///</summary>
+ public static Vector128<uint> SchedulePart2(Vector128<uint> tw0_3, Vector128<uint> w12_15) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha1.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha1.cs
new file mode 100644
index 000000000..28cc397ce
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha1.cs
@@ -0,0 +1,53 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.Arm.Arm64
+{
+ /// <summary>
+ /// This class provides access to the Arm64 SHA1 Crypto intrinsics
+ ///
+ /// Arm64 CPU indicate support for this feature by setting
+ /// ID_AA64ISAR0_EL1.SHA1 is 1 or better
+ /// </summary>
+ [CLSCompliant(false)]
+ public static class Sha1
+ {
+ public static bool IsSupported { get => IsSupported; }
+
+ // <summary>
+ /// Performs SHA1 hash update choose form.
+ /// vsha1cq_u32 (uint32x4_t hash_abcd, uint32_t hash_e, uint32x4_t wk)
+ ///</summary>
+ public static Vector128<uint> HashChoose(Vector128<uint> hash_abcd, uint hash_e, Vector128<uint>wk) => HashChoose(hash_abcd, hash_e, wk);
+
+ // <summary>
+ /// Performs SHA1 hash update majority form.
+ /// vsha1mq_u32 (uint32x4_t hash_abcd, uint32_t hash_e, uint32x4_t wk)
+ ///</summary>
+ public static Vector128<uint> HashMajority(Vector128<uint> hash_abcd, uint hash_e, Vector128<uint>wk) => HashMajority(hash_abcd, hash_e, wk);
+
+ // <summary>
+ /// Performs SHA1 hash update parity form.
+ /// vsha1pq_u32 (uint32x4_t hash_abcd, uint32_t hash_e, uint32x4_t wk)
+ ///</summary>
+ public static Vector128<uint> HashParity(Vector128<uint> hash_abcd, uint hash_e, Vector128<uint>wk) => HashParity(hash_abcd, hash_e, wk);
+
+ // <summary>
+ /// Performs SHA1 fixed rotate
+ /// vsha1h_u32 (uint32_t hash_e)
+ ///</summary>
+ public static uint FixedRotate(uint hash_e) => FixedRotate(hash_e);
+
+ // <summary>
+ /// Performs SHA1 schedule update 0
+ /// vsha1su0q_u32 (uint32x4_t w0_3, uint32x4_t w4_7, uint32x4_t w8_11)
+ ///</summary>
+ public static Vector128<uint> SchedulePart1(Vector128<uint> w0_3, Vector128<uint> w4_7, Vector128<uint> w8_11) => SchedulePart1(w0_3, w4_7, w8_11);
+
+ // <summary>
+ /// Performs SHA1 schedule update 1
+ /// vsha1su1q_u32 (uint32x4_t tw0_3, uint32x4_t w12_15)
+ ///</summary>
+ public static Vector128<uint> SchedulePart2(Vector128<uint> tw0_3, Vector128<uint> w12_15) => SchedulePart2(tw0_3, w12_15);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha256.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha256.PlatformNotSupported.cs
new file mode 100644
index 000000000..052a1d236
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha256.PlatformNotSupported.cs
@@ -0,0 +1,41 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.Arm.Arm64
+{
+ /// <summary>
+ /// This class provides access to the Arm64 SHA256 Crypto intrinsics
+ ///
+ /// Arm64 CPU indicate support for this feature by setting
+ /// ID_AA64ISAR0_EL1.SHA2 is 1 or better
+ /// </summary>
+ [CLSCompliant(false)]
+ public static class Sha256
+ {
+ public static bool IsSupported { get { return false; } }
+
+ // <summary>
+ /// Performs SHA256 hash update (part 1).
+ /// vsha256hq_u32 (uint32x4_t hash_abcd, uint32x4_t hash_efgh, uint32x4_t wk)
+ ///</summary>
+ public static Vector128<uint> HashLower(Vector128<uint> hash_abcd, Vector128<uint> hash_efgh, Vector128<uint> wk) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs SHA256 hash update (part 2).
+ /// vsha256h2q_u32 (uint32x4_t hash_efgh, uint32x4_t hash_abcd, uint32x4_t wk)
+ ///</summary>
+ public static Vector128<uint> HashUpper(Vector128<uint> hash_efgh, Vector128<uint> hash_abcd, Vector128<uint> wk) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs SHA256 schedule update 0
+ /// vsha256su0q_u32 (uint32x4_t w0_3, uint32x4_t w4_7)
+ ///</summary>
+ public static Vector128<uint> SchedulePart1(Vector128<uint> w0_3, Vector128<uint> w4_7) { throw new PlatformNotSupportedException(); }
+
+ // <summary>
+ /// Performs SHA256 schedule update 1
+ /// vsha256su1q_u32 (uint32x4_t w0_3, uint32x4_t w8_11, uint32x4_t w12_15)
+ ///</summary>
+ public static Vector128<uint> SchedulePart2(Vector128<uint> w0_3, Vector128<uint> w8_11, Vector128<uint> w12_15) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha256.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha256.cs
new file mode 100644
index 000000000..4e7e51db3
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Sha256.cs
@@ -0,0 +1,41 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.Arm.Arm64
+{
+ /// <summary>
+ /// This class provides access to the Arm64 SHA256 Crypto intrinsics
+ ///
+ /// Arm64 CPU indicate support for this feature by setting
+ /// ID_AA64ISAR0_EL1.SHA2 is 1 or better
+ /// </summary>
+ [CLSCompliant(false)]
+ public static class Sha256
+ {
+ public static bool IsSupported { get => IsSupported; }
+
+ // <summary>
+ /// Performs SHA256 hash update (part 1).
+ /// vsha256hq_u32 (uint32x4_t hash_abcd, uint32x4_t hash_efgh, uint32x4_t wk)
+ ///</summary>
+ public static Vector128<uint> HashLower(Vector128<uint> hash_abcd, Vector128<uint> hash_efgh, Vector128<uint> wk) => HashLower(hash_abcd, hash_efgh, wk);
+
+ // <summary>
+ /// Performs SHA256 hash update (part 2).
+ /// vsha256h2q_u32 (uint32x4_t hash_efgh, uint32x4_t hash_abcd, uint32x4_t wk)
+ ///</summary>
+ public static Vector128<uint> HashUpper(Vector128<uint> hash_efgh, Vector128<uint> hash_abcd, Vector128<uint> wk) => HashUpper(hash_efgh, hash_abcd, wk);
+
+ // <summary>
+ /// Performs SHA256 schedule update 0
+ /// vsha256su0q_u32 (uint32x4_t w0_3, uint32x4_t w4_7)
+ ///</summary>
+ public static Vector128<uint> SchedulePart1(Vector128<uint> w0_3, Vector128<uint> w4_7) => SchedulePart1(w0_3, w4_7);
+
+ // <summary>
+ /// Performs SHA256 schedule update 1
+ /// vsha256su1q_u32 (uint32x4_t tw0_3, uint32x4_t w8_11, uint32x4_t w12_15)
+ ///</summary>
+ public static Vector128<uint> SchedulePart2(Vector128<uint> w0_3, Vector128<uint> w8_11, Vector128<uint> w12_15) => SchedulePart2(w0_3, w8_11, w12_15);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Simd.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Simd.PlatformNotSupported.cs
new file mode 100644
index 000000000..4b377902c
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Simd.PlatformNotSupported.cs
@@ -0,0 +1,344 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+
+namespace System.Runtime.Intrinsics.Arm.Arm64
+{
+ /// <summary>
+ /// This class provides access to the Arm64 AdvSIMD intrinsics
+ ///
+ /// Arm64 CPU indicate support for this feature by setting
+ /// ID_AA64PFR0_EL1.AdvSIMD == 0 or better.
+ /// </summary>
+ [CLSCompliant(false)]
+ public static class Simd
+ {
+ /// <summary>
+ /// IsSupported property indicates whether any method provided
+ /// by this class is supported by the current runtime.
+ /// </summary>
+ public static bool IsSupported { get { return false; }}
+
+ /// <summary>
+ /// Vector abs
+ /// Corresponds to vector forms of ARM64 ABS & FABS
+ /// </summary>
+ public static Vector64<byte> Abs(Vector64<sbyte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<ushort> Abs(Vector64<short> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<uint> Abs(Vector64<int> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<float> Abs(Vector64<float> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<byte> Abs(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<ushort> Abs(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<uint> Abs(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<ulong> Abs(Vector128<long> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<float> Abs(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<double> Abs(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector add
+ /// Corresponds to vector forms of ARM64 ADD & FADD
+ /// </summary>
+ public static Vector64<T> Add<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> Add<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector and
+ /// Corresponds to vector forms of ARM64 AND
+ /// </summary>
+ public static Vector64<T> And<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> And<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector and not
+ /// Corresponds to vector forms of ARM64 BIC
+ /// </summary>
+ public static Vector64<T> AndNot<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> AndNot<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector BitwiseSelect
+ /// For each bit in the vector result[bit] = sel[bit] ? left[bit] : right[bit]
+ /// Corresponds to vector forms of ARM64 BSL (Also BIF & BIT)
+ /// </summary>
+ public static Vector64<T> BitwiseSelect<T>(Vector64<T> sel, Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> BitwiseSelect<T>(Vector128<T> sel, Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector CompareEqual
+ /// For each element result[elem] = (left[elem] == right[elem]) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMEQ & FCMEQ
+ /// </summary>
+ public static Vector64<T> CompareEqual<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> CompareEqual<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector CompareEqualZero
+ /// For each element result[elem] = (left[elem] == 0) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMEQ & FCMEQ
+ /// </summary>
+ public static Vector64<T> CompareEqualZero<T>(Vector64<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> CompareEqualZero<T>(Vector128<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector CompareGreaterThan
+ /// For each element result[elem] = (left[elem] > right[elem]) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGT/CMHI & FCMGT
+ /// </summary>
+ public static Vector64<T> CompareGreaterThan<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> CompareGreaterThan<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector CompareGreaterThanZero
+ /// For each element result[elem] = (left[elem] > 0) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGT & FCMGT
+ /// </summary>
+ public static Vector64<T> CompareGreaterThanZero<T>(Vector64<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> CompareGreaterThanZero<T>(Vector128<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector CompareGreaterThanOrEqual
+ /// For each element result[elem] = (left[elem] >= right[elem]) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGE/CMHS & FCMGE
+ /// </summary>
+ public static Vector64<T> CompareGreaterThanOrEqual<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> CompareGreaterThanOrEqual<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector CompareGreaterThanOrEqualZero
+ /// For each element result[elem] = (left[elem] >= 0) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGE & FCMGE
+ /// </summary>
+ public static Vector64<T> CompareGreaterThanOrEqualZero<T>(Vector64<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> CompareGreaterThanOrEqualZero<T>(Vector128<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector CompareLessThanZero
+ /// For each element result[elem] = (left[elem] < 0) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGT & FCMGT
+ /// </summary>
+ public static Vector64<T> CompareLessThanZero<T>(Vector64<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> CompareLessThanZero<T>(Vector128<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector CompareLessThanOrEqualZero
+ /// For each element result[elem] = (left[elem] < 0) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGT & FCMGT
+ /// </summary>
+ public static Vector64<T> CompareLessThanOrEqualZero<T>(Vector64<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> CompareLessThanOrEqualZero<T>(Vector128<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector CompareTest
+ /// For each element result[elem] = (left[elem] & right[elem]) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMTST
+ /// </summary>
+ public static Vector64<T> CompareTest<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> CompareTest<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// TBD Convert...
+
+ /// <summary>
+ /// Vector Divide
+ /// Corresponds to vector forms of ARM64 FDIV
+ /// </summary>
+ public static Vector64<float> Divide(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<float> Divide(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<double> Divide(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector extract item
+ ///
+ /// result = vector[index]
+ ///
+ /// Note: In order to be inlined, index must be a JIT time const expression which can be used to
+ /// populate the literal immediate field. Use of a non constant will result in generation of a switch table
+ ///
+ /// Corresponds to vector forms of ARM64 MOV
+ /// </summary>
+ public static T Extract<T>(Vector64<T> vector, byte index) where T : struct { throw new PlatformNotSupportedException(); }
+ public static T Extract<T>(Vector128<T> vector, byte index) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector insert item
+ ///
+ /// result = vector;
+ /// result[index] = data;
+ ///
+ /// Note: In order to be inlined, index must be a JIT time const expression which can be used to
+ /// populate the literal immediate field. Use of a non constant will result in generation of a switch table
+ ///
+ /// Corresponds to vector forms of ARM64 INS
+ /// </summary>
+ public static Vector64<T> Insert<T>(Vector64<T> vector, byte index, T data) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> Insert<T>(Vector128<T> vector, byte index, T data) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector LeadingSignCount
+ /// Corresponds to vector forms of ARM64 CLS
+ /// </summary>
+ public static Vector64<sbyte> LeadingSignCount(Vector64<sbyte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<short> LeadingSignCount(Vector64<short> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<int> LeadingSignCount(Vector64<int> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<sbyte> LeadingSignCount(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<short> LeadingSignCount(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<int> LeadingSignCount(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector LeadingZeroCount
+ /// Corresponds to vector forms of ARM64 CLZ
+ /// </summary>
+ public static Vector64<byte> LeadingZeroCount(Vector64<byte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<sbyte> LeadingZeroCount(Vector64<sbyte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<ushort> LeadingZeroCount(Vector64<ushort> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<short> LeadingZeroCount(Vector64<short> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<uint> LeadingZeroCount(Vector64<uint> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<int> LeadingZeroCount(Vector64<int> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<byte> LeadingZeroCount(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<sbyte> LeadingZeroCount(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<ushort> LeadingZeroCount(Vector128<ushort> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<short> LeadingZeroCount(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<uint> LeadingZeroCount(Vector128<uint> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<int> LeadingZeroCount(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector max
+ /// Corresponds to vector forms of ARM64 SMAX, UMAX & FMAX
+ /// </summary>
+ public static Vector64<byte> Max(Vector64<byte> left, Vector64<byte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<sbyte> Max(Vector64<sbyte> left, Vector64<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<ushort> Max(Vector64<ushort> left, Vector64<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<short> Max(Vector64<short> left, Vector64<short> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<uint> Max(Vector64<uint> left, Vector64<uint> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<int> Max(Vector64<int> left, Vector64<int> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<float> Max(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<byte> Max(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<sbyte> Max(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<ushort> Max(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<short> Max(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<uint> Max(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<int> Max(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<float> Max(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<double> Max(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector min
+ /// Corresponds to vector forms of ARM64 SMIN, UMIN & FMIN
+ /// </summary>
+ public static Vector64<byte> Min(Vector64<byte> left, Vector64<byte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<sbyte> Min(Vector64<sbyte> left, Vector64<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<ushort> Min(Vector64<ushort> left, Vector64<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<short> Min(Vector64<short> left, Vector64<short> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<uint> Min(Vector64<uint> left, Vector64<uint> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<int> Min(Vector64<int> left, Vector64<int> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<float> Min(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<byte> Min(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<sbyte> Min(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<ushort> Min(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<short> Min(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<uint> Min(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<int> Min(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<float> Min(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<double> Min(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// TBD MOV, FMOV
+
+ /// <summary>
+ /// Vector multiply
+ ///
+ /// For each element result[elem] = left[elem] * right[elem]
+ ///
+ /// Corresponds to vector forms of ARM64 MUL & FMUL
+ /// </summary>
+ public static Vector64<byte> Multiply(Vector64<byte> left, Vector64<byte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<sbyte> Multiply(Vector64<sbyte> left, Vector64<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<ushort> Multiply(Vector64<ushort> left, Vector64<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<short> Multiply(Vector64<short> left, Vector64<short> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<uint> Multiply(Vector64<uint> left, Vector64<uint> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<int> Multiply(Vector64<int> left, Vector64<int> right) { throw new PlatformNotSupportedException(); }
+ public static Vector64<float> Multiply(Vector64<float> left, Vector64<float> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<byte> Multiply(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<sbyte> Multiply(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<ushort> Multiply(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<short> Multiply(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<uint> Multiply(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<int> Multiply(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<float> Multiply(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ public static Vector128<double> Multiply(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector negate
+ /// Corresponds to vector forms of ARM64 NEG & FNEG
+ /// </summary>
+ public static Vector64<sbyte> Negate(Vector64<sbyte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<short> Negate(Vector64<short> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<int> Negate(Vector64<int> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<float> Negate(Vector64<float> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<sbyte> Negate(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<short> Negate(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<int> Negate(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<long> Negate(Vector128<long> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<float> Negate(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<double> Negate(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector not
+ /// Corresponds to vector forms of ARM64 NOT
+ /// </summary>
+ public static Vector64<T> Not<T>(Vector64<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> Not<T>(Vector128<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector or
+ /// Corresponds to vector forms of ARM64 ORR
+ /// </summary>
+ public static Vector64<T> Or<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> Or<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector or not
+ /// Corresponds to vector forms of ARM64 ORN
+ /// </summary>
+ public static Vector64<T> OrNot<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> OrNot<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector PopCount
+ /// Corresponds to vector forms of ARM64 CNT
+ /// </summary>
+ public static Vector64<byte> PopCount(Vector64<byte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector64<sbyte> PopCount(Vector64<sbyte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<byte> PopCount(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<sbyte> PopCount(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// SetVector* Fill vector elements by replicating element value
+ ///
+ /// Corresponds to vector forms of ARM64 DUP (general), DUP (element 0), FMOV (vector, immediate)
+ /// </summary>
+ public static Vector64<T> SetAllVector64<T>(T value) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> SetAllVector128<T>(T value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector square root
+ /// Corresponds to vector forms of ARM64 FRSQRT
+ /// </summary>
+ public static Vector64<float> Sqrt(Vector64<float> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<float> Sqrt(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ public static Vector128<double> Sqrt(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// Vector subtract
+ /// Corresponds to vector forms of ARM64 SUB & FSUB
+ /// </summary>
+ public static Vector64<T> Subtract<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> Subtract<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+
+ /// <summary>
+ /// Vector exclusive or
+ /// Corresponds to vector forms of ARM64 EOR
+ /// </summary>
+ public static Vector64<T> Xor<T>(Vector64<T> left, Vector64<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ public static Vector128<T> Xor<T>(Vector128<T> left, Vector128<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Simd.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Simd.cs
new file mode 100644
index 000000000..f162483da
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Arm/Arm64/Simd.cs
@@ -0,0 +1,344 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+
+namespace System.Runtime.Intrinsics.Arm.Arm64
+{
+ /// <summary>
+ /// This class provides access to the Arm64 AdvSIMD intrinsics
+ ///
+ /// Arm64 CPU indicate support for this feature by setting
+ /// ID_AA64PFR0_EL1.AdvSIMD == 0 or better.
+ /// </summary>
+ [CLSCompliant(false)]
+ public static class Simd
+ {
+ /// <summary>
+ /// IsSupported property indicates whether any method provided
+ /// by this class is supported by the current runtime.
+ /// </summary>
+ public static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// Vector abs
+ /// Corresponds to vector forms of ARM64 ABS & FABS
+ /// </summary>
+ public static Vector64<byte> Abs(Vector64<sbyte> value) => Abs(value);
+ public static Vector64<ushort> Abs(Vector64<short> value) => Abs(value);
+ public static Vector64<uint> Abs(Vector64<int> value) => Abs(value);
+ public static Vector64<float> Abs(Vector64<float> value) => Abs(value);
+ public static Vector128<byte> Abs(Vector128<sbyte> value) => Abs(value);
+ public static Vector128<ushort> Abs(Vector128<short> value) => Abs(value);
+ public static Vector128<uint> Abs(Vector128<int> value) => Abs(value);
+ public static Vector128<ulong> Abs(Vector128<long> value) => Abs(value);
+ public static Vector128<float> Abs(Vector128<float> value) => Abs(value);
+ public static Vector128<double> Abs(Vector128<double> value) => Abs(value);
+
+ /// <summary>
+ /// Vector add
+ /// Corresponds to vector forms of ARM64 ADD & FADD
+ /// </summary>
+ public static Vector64<T> Add<T>(Vector64<T> left, Vector64<T> right) where T : struct => Add(left, right);
+ public static Vector128<T> Add<T>(Vector128<T> left, Vector128<T> right) where T : struct => Add(left, right);
+
+ /// <summary>
+ /// Vector and
+ /// Corresponds to vector forms of ARM64 AND
+ /// </summary>
+ public static Vector64<T> And<T>(Vector64<T> left, Vector64<T> right) where T : struct => And(left, right);
+ public static Vector128<T> And<T>(Vector128<T> left, Vector128<T> right) where T : struct => And(left, right);
+
+ /// <summary>
+ /// Vector and not
+ /// Corresponds to vector forms of ARM64 BIC
+ /// </summary>
+ public static Vector64<T> AndNot<T>(Vector64<T> left, Vector64<T> right) where T : struct => AndNot(left, right);
+ public static Vector128<T> AndNot<T>(Vector128<T> left, Vector128<T> right) where T : struct => AndNot(left, right);
+
+ /// <summary>
+ /// Vector BitwiseSelect
+ /// For each bit in the vector result[bit] = sel[bit] ? left[bit] : right[bit]
+ /// Corresponds to vector forms of ARM64 BSL (Also BIF & BIT)
+ /// </summary>
+ public static Vector64<T> BitwiseSelect<T>(Vector64<T> sel, Vector64<T> left, Vector64<T> right) where T : struct => BitwiseSelect(sel, left, right);
+ public static Vector128<T> BitwiseSelect<T>(Vector128<T> sel, Vector128<T> left, Vector128<T> right) where T : struct => BitwiseSelect(sel, left, right);
+
+ /// <summary>
+ /// Vector CompareEqual
+ /// For each element result[elem] = (left[elem] == right[elem]) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMEQ & FCMEQ
+ /// </summary>
+ public static Vector64<T> CompareEqual<T>(Vector64<T> left, Vector64<T> right) where T : struct => CompareEqual(left, right);
+ public static Vector128<T> CompareEqual<T>(Vector128<T> left, Vector128<T> right) where T : struct => CompareEqual(left, right);
+
+ /// <summary>
+ /// Vector CompareEqualZero
+ /// For each element result[elem] = (left[elem] == 0) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMEQ & FCMEQ
+ /// </summary>
+ public static Vector64<T> CompareEqualZero<T>(Vector64<T> value) where T : struct => CompareEqualZero(value);
+ public static Vector128<T> CompareEqualZero<T>(Vector128<T> value) where T : struct => CompareEqualZero(value);
+
+ /// <summary>
+ /// Vector CompareGreaterThan
+ /// For each element result[elem] = (left[elem] > right[elem]) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGT/CMHI & FCMGT
+ /// </summary>
+ public static Vector64<T> CompareGreaterThan<T>(Vector64<T> left, Vector64<T> right) where T : struct => CompareGreaterThan(left, right);
+ public static Vector128<T> CompareGreaterThan<T>(Vector128<T> left, Vector128<T> right) where T : struct => CompareGreaterThan(left, right);
+
+ /// <summary>
+ /// Vector CompareGreaterThanZero
+ /// For each element result[elem] = (left[elem] > 0) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGT & FCMGT
+ /// </summary>
+ public static Vector64<T> CompareGreaterThanZero<T>(Vector64<T> value) where T : struct => CompareGreaterThanZero(value);
+ public static Vector128<T> CompareGreaterThanZero<T>(Vector128<T> value) where T : struct => CompareGreaterThanZero(value);
+
+ /// <summary>
+ /// Vector CompareGreaterThanOrEqual
+ /// For each element result[elem] = (left[elem] >= right[elem]) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGE/CMHS & FCMGE
+ /// </summary>
+ public static Vector64<T> CompareGreaterThanOrEqual<T>(Vector64<T> left, Vector64<T> right) where T : struct => CompareGreaterThanOrEqual(left, right);
+ public static Vector128<T> CompareGreaterThanOrEqual<T>(Vector128<T> left, Vector128<T> right) where T : struct => CompareGreaterThanOrEqual(left, right);
+
+ /// <summary>
+ /// Vector CompareGreaterThanOrEqualZero
+ /// For each element result[elem] = (left[elem] >= 0) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGE & FCMGE
+ /// </summary>
+ public static Vector64<T> CompareGreaterThanOrEqualZero<T>(Vector64<T> value) where T : struct => CompareGreaterThanOrEqualZero(value);
+ public static Vector128<T> CompareGreaterThanOrEqualZero<T>(Vector128<T> value) where T : struct => CompareGreaterThanOrEqualZero(value);
+
+ /// <summary>
+ /// Vector CompareLessThanZero
+ /// For each element result[elem] = (left[elem] < 0) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGT & FCMGT
+ /// </summary>
+ public static Vector64<T> CompareLessThanZero<T>(Vector64<T> value) where T : struct => CompareLessThanZero(value);
+ public static Vector128<T> CompareLessThanZero<T>(Vector128<T> value) where T : struct => CompareLessThanZero(value);
+
+ /// <summary>
+ /// Vector CompareLessThanOrEqualZero
+ /// For each element result[elem] = (left[elem] < 0) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMGT & FCMGT
+ /// </summary>
+ public static Vector64<T> CompareLessThanOrEqualZero<T>(Vector64<T> value) where T : struct => CompareLessThanOrEqualZero(value);
+ public static Vector128<T> CompareLessThanOrEqualZero<T>(Vector128<T> value) where T : struct => CompareLessThanOrEqualZero(value);
+
+ /// <summary>
+ /// Vector CompareTest
+ /// For each element result[elem] = (left[elem] & right[elem]) ? ~0 : 0
+ /// Corresponds to vector forms of ARM64 CMTST
+ /// </summary>
+ public static Vector64<T> CompareTest<T>(Vector64<T> left, Vector64<T> right) where T : struct => CompareTest(left, right);
+ public static Vector128<T> CompareTest<T>(Vector128<T> left, Vector128<T> right) where T : struct => CompareTest(left, right);
+
+ /// TBD Convert...
+
+ /// <summary>
+ /// Vector Divide
+ /// Corresponds to vector forms of ARM64 FDIV
+ /// </summary>
+ public static Vector64<float> Divide(Vector64<float> left, Vector64<float> right) => Divide(left, right);
+ public static Vector128<float> Divide(Vector128<float> left, Vector128<float> right) => Divide(left, right);
+ public static Vector128<double> Divide(Vector128<double> left, Vector128<double> right) => Divide(left, right);
+
+ /// <summary>
+ /// Vector extract item
+ ///
+ /// result = vector[index]
+ ///
+ /// Note: In order to be inlined, index must be a JIT time const expression which can be used to
+ /// populate the literal immediate field. Use of a non constant will result in generation of a switch table
+ ///
+ /// Corresponds to vector forms of ARM64 MOV
+ /// </summary>
+ public static T Extract<T>(Vector64<T> vector, byte index) where T : struct => Extract(vector, index);
+ public static T Extract<T>(Vector128<T> vector, byte index) where T : struct => Extract(vector, index);
+
+ /// <summary>
+ /// Vector insert item
+ ///
+ /// result = vector;
+ /// result[index] = data;
+ ///
+ /// Note: In order to be inlined, index must be a JIT time const expression which can be used to
+ /// populate the literal immediate field. Use of a non constant will result in generation of a switch table
+ ///
+ /// Corresponds to vector forms of ARM64 INS
+ /// </summary>
+ public static Vector64<T> Insert<T>(Vector64<T> vector, byte index, T data) where T : struct => Insert(vector, index, data);
+ public static Vector128<T> Insert<T>(Vector128<T> vector, byte index, T data) where T : struct => Insert(vector, index, data);
+
+ /// <summary>
+ /// Vector LeadingSignCount
+ /// Corresponds to vector forms of ARM64 CLS
+ /// </summary>
+ public static Vector64<sbyte> LeadingSignCount(Vector64<sbyte> value) => LeadingSignCount(value);
+ public static Vector64<short> LeadingSignCount(Vector64<short> value) => LeadingSignCount(value);
+ public static Vector64<int> LeadingSignCount(Vector64<int> value) => LeadingSignCount(value);
+ public static Vector128<sbyte> LeadingSignCount(Vector128<sbyte> value) => LeadingSignCount(value);
+ public static Vector128<short> LeadingSignCount(Vector128<short> value) => LeadingSignCount(value);
+ public static Vector128<int> LeadingSignCount(Vector128<int> value) => LeadingSignCount(value);
+
+ /// <summary>
+ /// Vector LeadingZeroCount
+ /// Corresponds to vector forms of ARM64 CLZ
+ /// </summary>
+ public static Vector64<byte> LeadingZeroCount(Vector64<byte> value) => LeadingZeroCount(value);
+ public static Vector64<sbyte> LeadingZeroCount(Vector64<sbyte> value) => LeadingZeroCount(value);
+ public static Vector64<ushort> LeadingZeroCount(Vector64<ushort> value) => LeadingZeroCount(value);
+ public static Vector64<short> LeadingZeroCount(Vector64<short> value) => LeadingZeroCount(value);
+ public static Vector64<uint> LeadingZeroCount(Vector64<uint> value) => LeadingZeroCount(value);
+ public static Vector64<int> LeadingZeroCount(Vector64<int> value) => LeadingZeroCount(value);
+ public static Vector128<byte> LeadingZeroCount(Vector128<byte> value) => LeadingZeroCount(value);
+ public static Vector128<sbyte> LeadingZeroCount(Vector128<sbyte> value) => LeadingZeroCount(value);
+ public static Vector128<ushort> LeadingZeroCount(Vector128<ushort> value) => LeadingZeroCount(value);
+ public static Vector128<short> LeadingZeroCount(Vector128<short> value) => LeadingZeroCount(value);
+ public static Vector128<uint> LeadingZeroCount(Vector128<uint> value) => LeadingZeroCount(value);
+ public static Vector128<int> LeadingZeroCount(Vector128<int> value) => LeadingZeroCount(value);
+
+ /// <summary>
+ /// Vector max
+ /// Corresponds to vector forms of ARM64 SMAX, UMAX & FMAX
+ /// </summary>
+ public static Vector64<byte> Max(Vector64<byte> left, Vector64<byte> right) => Max(left, right);
+ public static Vector64<sbyte> Max(Vector64<sbyte> left, Vector64<sbyte> right) => Max(left, right);
+ public static Vector64<ushort> Max(Vector64<ushort> left, Vector64<ushort> right) => Max(left, right);
+ public static Vector64<short> Max(Vector64<short> left, Vector64<short> right) => Max(left, right);
+ public static Vector64<uint> Max(Vector64<uint> left, Vector64<uint> right) => Max(left, right);
+ public static Vector64<int> Max(Vector64<int> left, Vector64<int> right) => Max(left, right);
+ public static Vector64<float> Max(Vector64<float> left, Vector64<float> right) => Max(left, right);
+ public static Vector128<byte> Max(Vector128<byte> left, Vector128<byte> right) => Max(left, right);
+ public static Vector128<sbyte> Max(Vector128<sbyte> left, Vector128<sbyte> right) => Max(left, right);
+ public static Vector128<ushort> Max(Vector128<ushort> left, Vector128<ushort> right) => Max(left, right);
+ public static Vector128<short> Max(Vector128<short> left, Vector128<short> right) => Max(left, right);
+ public static Vector128<uint> Max(Vector128<uint> left, Vector128<uint> right) => Max(left, right);
+ public static Vector128<int> Max(Vector128<int> left, Vector128<int> right) => Max(left, right);
+ public static Vector128<float> Max(Vector128<float> left, Vector128<float> right) => Max(left, right);
+ public static Vector128<double> Max(Vector128<double> left, Vector128<double> right) => Max(left, right);
+
+ /// <summary>
+ /// Vector min
+ /// Corresponds to vector forms of ARM64 SMIN, UMIN & FMIN
+ /// </summary>
+ public static Vector64<byte> Min(Vector64<byte> left, Vector64<byte> right) => Min(left, right);
+ public static Vector64<sbyte> Min(Vector64<sbyte> left, Vector64<sbyte> right) => Min(left, right);
+ public static Vector64<ushort> Min(Vector64<ushort> left, Vector64<ushort> right) => Min(left, right);
+ public static Vector64<short> Min(Vector64<short> left, Vector64<short> right) => Min(left, right);
+ public static Vector64<uint> Min(Vector64<uint> left, Vector64<uint> right) => Min(left, right);
+ public static Vector64<int> Min(Vector64<int> left, Vector64<int> right) => Min(left, right);
+ public static Vector64<float> Min(Vector64<float> left, Vector64<float> right) => Min(left, right);
+ public static Vector128<byte> Min(Vector128<byte> left, Vector128<byte> right) => Min(left, right);
+ public static Vector128<sbyte> Min(Vector128<sbyte> left, Vector128<sbyte> right) => Min(left, right);
+ public static Vector128<ushort> Min(Vector128<ushort> left, Vector128<ushort> right) => Min(left, right);
+ public static Vector128<short> Min(Vector128<short> left, Vector128<short> right) => Min(left, right);
+ public static Vector128<uint> Min(Vector128<uint> left, Vector128<uint> right) => Min(left, right);
+ public static Vector128<int> Min(Vector128<int> left, Vector128<int> right) => Min(left, right);
+ public static Vector128<float> Min(Vector128<float> left, Vector128<float> right) => Min(left, right);
+ public static Vector128<double> Min(Vector128<double> left, Vector128<double> right) => Min(left, right);
+
+ /// TBD MOV, FMOV
+
+ /// <summary>
+ /// Vector multiply
+ ///
+ /// For each element result[elem] = left[elem] * right[elem]
+ ///
+ /// Corresponds to vector forms of ARM64 MUL & FMUL
+ /// </summary>
+ public static Vector64<byte> Multiply(Vector64<byte> left, Vector64<byte> right) => Multiply(left, right);
+ public static Vector64<sbyte> Multiply(Vector64<sbyte> left, Vector64<sbyte> right) => Multiply(left, right);
+ public static Vector64<ushort> Multiply(Vector64<ushort> left, Vector64<ushort> right) => Multiply(left, right);
+ public static Vector64<short> Multiply(Vector64<short> left, Vector64<short> right) => Multiply(left, right);
+ public static Vector64<uint> Multiply(Vector64<uint> left, Vector64<uint> right) => Multiply(left, right);
+ public static Vector64<int> Multiply(Vector64<int> left, Vector64<int> right) => Multiply(left, right);
+ public static Vector64<float> Multiply(Vector64<float> left, Vector64<float> right) => Multiply(left, right);
+ public static Vector128<byte> Multiply(Vector128<byte> left, Vector128<byte> right) => Multiply(left, right);
+ public static Vector128<sbyte> Multiply(Vector128<sbyte> left, Vector128<sbyte> right) => Multiply(left, right);
+ public static Vector128<ushort> Multiply(Vector128<ushort> left, Vector128<ushort> right) => Multiply(left, right);
+ public static Vector128<short> Multiply(Vector128<short> left, Vector128<short> right) => Multiply(left, right);
+ public static Vector128<uint> Multiply(Vector128<uint> left, Vector128<uint> right) => Multiply(left, right);
+ public static Vector128<int> Multiply(Vector128<int> left, Vector128<int> right) => Multiply(left, right);
+ public static Vector128<float> Multiply(Vector128<float> left, Vector128<float> right) => Multiply(left, right);
+ public static Vector128<double> Multiply(Vector128<double> left, Vector128<double> right) => Multiply(left, right);
+
+ /// <summary>
+ /// Vector negate
+ /// Corresponds to vector forms of ARM64 NEG & FNEG
+ /// </summary>
+ public static Vector64<sbyte> Negate(Vector64<sbyte> value) => Negate(value);
+ public static Vector64<short> Negate(Vector64<short> value) => Negate(value);
+ public static Vector64<int> Negate(Vector64<int> value) => Negate(value);
+ public static Vector64<float> Negate(Vector64<float> value) => Negate(value);
+ public static Vector128<sbyte> Negate(Vector128<sbyte> value) => Negate(value);
+ public static Vector128<short> Negate(Vector128<short> value) => Negate(value);
+ public static Vector128<int> Negate(Vector128<int> value) => Negate(value);
+ public static Vector128<long> Negate(Vector128<long> value) => Negate(value);
+ public static Vector128<float> Negate(Vector128<float> value) => Negate(value);
+ public static Vector128<double> Negate(Vector128<double> value) => Negate(value);
+
+ /// <summary>
+ /// Vector not
+ /// Corresponds to vector forms of ARM64 NOT
+ /// </summary>
+ public static Vector64<T> Not<T>(Vector64<T> value) where T : struct => Not(value);
+ public static Vector128<T> Not<T>(Vector128<T> value) where T : struct => Not(value);
+
+ /// <summary>
+ /// Vector or
+ /// Corresponds to vector forms of ARM64 ORR
+ /// </summary>
+ public static Vector64<T> Or<T>(Vector64<T> left, Vector64<T> right) where T : struct => Or(left, right);
+ public static Vector128<T> Or<T>(Vector128<T> left, Vector128<T> right) where T : struct => Or(left, right);
+
+ /// <summary>
+ /// Vector or not
+ /// Corresponds to vector forms of ARM64 ORN
+ /// </summary>
+ public static Vector64<T> OrNot<T>(Vector64<T> left, Vector64<T> right) where T : struct => OrNot(left, right);
+ public static Vector128<T> OrNot<T>(Vector128<T> left, Vector128<T> right) where T : struct => OrNot(left, right);
+
+ /// <summary>
+ /// Vector PopCount
+ /// Corresponds to vector forms of ARM64 CNT
+ /// </summary>
+ public static Vector64<byte> PopCount(Vector64<byte> value) => PopCount(value);
+ public static Vector64<sbyte> PopCount(Vector64<sbyte> value) => PopCount(value);
+ public static Vector128<byte> PopCount(Vector128<byte> value) => PopCount(value);
+ public static Vector128<sbyte> PopCount(Vector128<sbyte> value) => PopCount(value);
+
+ /// <summary>
+ /// SetVector* Fill vector elements by replicating element value
+ ///
+ /// Corresponds to vector forms of ARM64 DUP (general), DUP (element 0), FMOV (vector, immediate)
+ /// </summary>
+ public static Vector64<T> SetAllVector64<T>(T value) where T : struct => SetAllVector64(value);
+ public static Vector128<T> SetAllVector128<T>(T value) where T : struct => SetAllVector128(value);
+
+ /// <summary>
+ /// Vector square root
+ /// Corresponds to vector forms of ARM64 FRSQRT
+ /// </summary>
+ public static Vector64<float> Sqrt(Vector64<float> value) => Sqrt(value);
+ public static Vector128<float> Sqrt(Vector128<float> value) => Sqrt(value);
+ public static Vector128<double> Sqrt(Vector128<double> value) => Sqrt(value);
+
+ /// <summary>
+ /// Vector subtract
+ /// Corresponds to vector forms of ARM64 SUB & FSUB
+ /// </summary>
+ public static Vector64<T> Subtract<T>(Vector64<T> left, Vector64<T> right) where T : struct => Subtract(left, right);
+ public static Vector128<T> Subtract<T>(Vector128<T> left, Vector128<T> right) where T : struct => Subtract(left, right);
+
+
+ /// <summary>
+ /// Vector exclusive or
+ /// Corresponds to vector forms of ARM64 EOR
+ /// </summary>
+ public static Vector64<T> Xor<T>(Vector64<T> left, Vector64<T> right) where T : struct => Xor(left, right);
+ public static Vector128<T> Xor<T>(Vector128<T> left, Vector128<T> right) where T : struct => Xor(left, right);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128.cs
new file mode 100644
index 000000000..b2e72ddf8
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128.cs
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Internal.Runtime.CompilerServices;
+
+namespace System.Runtime.Intrinsics
+{
+ [Intrinsic]
+ [DebuggerDisplay("{DisplayString,nq}")]
+ [DebuggerTypeProxy(typeof(Vector128DebugView<>))]
+ [StructLayout(LayoutKind.Sequential, Size = 16)]
+ public readonly struct Vector128<T> where T : struct
+ {
+ // These fields exist to ensure the alignment is 8, rather than 1.
+ // This also allows the debug view to work https://github.com/dotnet/coreclr/issues/15694)
+ private readonly ulong _00;
+ private readonly ulong _01;
+
+ private unsafe string DisplayString
+ {
+ get
+ {
+ // The IsPrimitive check ends up working for `bool`, `char`, `IntPtr`, and `UIntPtr`
+ // which are not actually supported by any current architecture. This shouldn't be
+ // an issue however and greatly simplifies the check
+
+ if (typeof(T).IsPrimitive)
+ {
+ var items = new T[16 / Unsafe.SizeOf<T>()];
+ Unsafe.WriteUnaligned(ref Unsafe.As<T, byte>(ref items[0]), this);
+ return $"({string.Join(", ", items)})";
+ }
+ else
+ {
+ return SR.NotSupported_Type;
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128DebugView.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128DebugView.cs
new file mode 100644
index 000000000..ccdc65594
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128DebugView.cs
@@ -0,0 +1,118 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.Runtime.CompilerServices;
+
+namespace System.Runtime.Intrinsics
+{
+ internal readonly struct Vector128DebugView<T> where T : struct
+ {
+ private readonly Vector128<T> _value;
+
+ public Vector128DebugView(Vector128<T> value)
+ {
+ _value = value;
+ }
+
+ public byte[] ByteView
+ {
+ get
+ {
+ var items = new byte[16];
+ Unsafe.WriteUnaligned(ref items[0], _value);
+ return items;
+ }
+ }
+
+ public double[] DoubleView
+ {
+ get
+ {
+ var items = new double[2];
+ Unsafe.WriteUnaligned(ref Unsafe.As<double, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public short[] Int16View
+ {
+ get
+ {
+ var items = new short[8];
+ Unsafe.WriteUnaligned(ref Unsafe.As<short, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public int[] Int32View
+ {
+ get
+ {
+ var items = new int[4];
+ Unsafe.WriteUnaligned(ref Unsafe.As<int, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public long[] Int64View
+ {
+ get
+ {
+ var items = new long[2];
+ Unsafe.WriteUnaligned(ref Unsafe.As<long, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public sbyte[] SByteView
+ {
+ get
+ {
+ var items = new sbyte[16];
+ Unsafe.WriteUnaligned(ref Unsafe.As<sbyte, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public float[] SingleView
+ {
+ get
+ {
+ var items = new float[4];
+ Unsafe.WriteUnaligned(ref Unsafe.As<float, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public ushort[] UInt16View
+ {
+ get
+ {
+ var items = new ushort[8];
+ Unsafe.WriteUnaligned(ref Unsafe.As<ushort, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public uint[] UInt32View
+ {
+ get
+ {
+ var items = new uint[4];
+ Unsafe.WriteUnaligned(ref Unsafe.As<uint, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public ulong[] UInt64View
+ {
+ get
+ {
+ var items = new ulong[2];
+ Unsafe.WriteUnaligned(ref Unsafe.As<ulong, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256.cs
new file mode 100644
index 000000000..48744bb5e
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256.cs
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Internal.Runtime.CompilerServices;
+
+namespace System.Runtime.Intrinsics
+{
+ [Intrinsic]
+ [DebuggerDisplay("{DisplayString,nq}")]
+ [DebuggerTypeProxy(typeof(Vector256DebugView<>))]
+ [StructLayout(LayoutKind.Sequential, Size = 32)]
+ public readonly struct Vector256<T> where T : struct
+ {
+ // These fields exist to ensure the alignment is 8, rather than 1.
+ // This also allows the debug view to work https://github.com/dotnet/coreclr/issues/15694)
+ private readonly ulong _00;
+ private readonly ulong _01;
+ private readonly ulong _02;
+ private readonly ulong _03;
+
+ private unsafe string DisplayString
+ {
+ get
+ {
+ // The IsPrimitive check ends up working for `bool`, `char`, `IntPtr`, and `UIntPtr`
+ // which are not actually supported by any current architecture. This shouldn't be
+ // an issue however and greatly simplifies the check
+
+ if (typeof(T).IsPrimitive)
+ {
+ var items = new T[32 / Unsafe.SizeOf<T>()];
+ Unsafe.WriteUnaligned(ref Unsafe.As<T, byte>(ref items[0]), this);
+ return $"({string.Join(", ", items)})";
+ }
+ else
+ {
+ return SR.NotSupported_Type;
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256DebugView.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256DebugView.cs
new file mode 100644
index 000000000..5131341ad
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256DebugView.cs
@@ -0,0 +1,118 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.Runtime.CompilerServices;
+
+namespace System.Runtime.Intrinsics
+{
+ internal readonly struct Vector256DebugView<T> where T : struct
+ {
+ private readonly Vector256<T> _value;
+
+ public Vector256DebugView(Vector256<T> value)
+ {
+ _value = value;
+ }
+
+ public byte[] ByteView
+ {
+ get
+ {
+ var items = new byte[32];
+ Unsafe.WriteUnaligned(ref items[0], _value);
+ return items;
+ }
+ }
+
+ public double[] DoubleView
+ {
+ get
+ {
+ var items = new double[4];
+ Unsafe.WriteUnaligned(ref Unsafe.As<double, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public short[] Int16View
+ {
+ get
+ {
+ var items = new short[16];
+ Unsafe.WriteUnaligned(ref Unsafe.As<short, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public int[] Int32View
+ {
+ get
+ {
+ var items = new int[8];
+ Unsafe.WriteUnaligned(ref Unsafe.As<int, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public long[] Int64View
+ {
+ get
+ {
+ var items = new long[4];
+ Unsafe.WriteUnaligned(ref Unsafe.As<long, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public sbyte[] SByteView
+ {
+ get
+ {
+ var items = new sbyte[32];
+ Unsafe.WriteUnaligned(ref Unsafe.As<sbyte, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public float[] SingleView
+ {
+ get
+ {
+ var items = new float[8];
+ Unsafe.WriteUnaligned(ref Unsafe.As<float, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public ushort[] UInt16View
+ {
+ get
+ {
+ var items = new ushort[16];
+ Unsafe.WriteUnaligned(ref Unsafe.As<ushort, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public uint[] UInt32View
+ {
+ get
+ {
+ var items = new uint[8];
+ Unsafe.WriteUnaligned(ref Unsafe.As<uint, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public ulong[] UInt64View
+ {
+ get
+ {
+ var items = new ulong[4];
+ Unsafe.WriteUnaligned(ref Unsafe.As<ulong, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64.cs
new file mode 100644
index 000000000..8ce90b9d0
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64.cs
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Internal.Runtime.CompilerServices;
+
+namespace System.Runtime.Intrinsics
+{
+ [Intrinsic]
+ [DebuggerDisplay("{DisplayString,nq}")]
+ [DebuggerTypeProxy(typeof(Vector64DebugView<>))]
+ [StructLayout(LayoutKind.Sequential, Size = 8)]
+ public readonly struct Vector64<T> where T : struct
+ {
+ // These fields exist to ensure the alignment is 8, rather than 1.
+ // This also allows the debug view to work https://github.com/dotnet/coreclr/issues/15694)
+ private readonly ulong _00;
+
+ private unsafe string DisplayString
+ {
+ get
+ {
+ // The IsPrimitive check ends up working for `bool`, `char`, `IntPtr`, and `UIntPtr`
+ // which are not actually supported by any current architecture. This shouldn't be
+ // an issue however and greatly simplifies the check
+
+ if (typeof(T).IsPrimitive)
+ {
+ var items = new T[8 / Unsafe.SizeOf<T>()];
+ Unsafe.WriteUnaligned(ref Unsafe.As<T, byte>(ref items[0]), this);
+ return $"({string.Join(", ", items)})";
+ }
+ else
+ {
+ return SR.NotSupported_Type;
+ }
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64DebugView.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64DebugView.cs
new file mode 100644
index 000000000..878e29949
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64DebugView.cs
@@ -0,0 +1,118 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.Runtime.CompilerServices;
+
+namespace System.Runtime.Intrinsics
+{
+ internal readonly struct Vector64DebugView<T> where T : struct
+ {
+ private readonly Vector64<T> _value;
+
+ public Vector64DebugView(Vector64<T> value)
+ {
+ _value = value;
+ }
+
+ public byte[] ByteView
+ {
+ get
+ {
+ var items = new byte[8];
+ Unsafe.WriteUnaligned(ref items[0], _value);
+ return items;
+ }
+ }
+
+ public double[] DoubleView
+ {
+ get
+ {
+ var items = new double[1];
+ Unsafe.WriteUnaligned(ref Unsafe.As<double, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public short[] Int16View
+ {
+ get
+ {
+ var items = new short[4];
+ Unsafe.WriteUnaligned(ref Unsafe.As<short, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public int[] Int32View
+ {
+ get
+ {
+ var items = new int[2];
+ Unsafe.WriteUnaligned(ref Unsafe.As<int, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public long[] Int64View
+ {
+ get
+ {
+ var items = new long[1];
+ Unsafe.WriteUnaligned(ref Unsafe.As<long, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public sbyte[] SByteView
+ {
+ get
+ {
+ var items = new sbyte[8];
+ Unsafe.WriteUnaligned(ref Unsafe.As<sbyte, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public float[] SingleView
+ {
+ get
+ {
+ var items = new float[2];
+ Unsafe.WriteUnaligned(ref Unsafe.As<float, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public ushort[] UInt16View
+ {
+ get
+ {
+ var items = new ushort[4];
+ Unsafe.WriteUnaligned(ref Unsafe.As<ushort, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public uint[] UInt32View
+ {
+ get
+ {
+ var items = new uint[2];
+ Unsafe.WriteUnaligned(ref Unsafe.As<uint, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+
+ public ulong[] UInt64View
+ {
+ get
+ {
+ var items = new ulong[1];
+ Unsafe.WriteUnaligned(ref Unsafe.As<ulong, byte>(ref items[0]), _value);
+ return items;
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Aes.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Aes.PlatformNotSupported.cs
new file mode 100644
index 000000000..d439defd7
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Aes.PlatformNotSupported.cs
@@ -0,0 +1,58 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel AES hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Aes : Sse2
+ {
+ internal Aes() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// __m128i _mm_aesdec_si128 (__m128i a, __m128i RoundKey)
+ /// AESDEC xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Decrypt(Vector128<byte> value, Vector128<byte> roundKey) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_aesdeclast_si128 (__m128i a, __m128i RoundKey)
+ /// AESDECLAST xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> DecryptLast(Vector128<byte> value, Vector128<byte> roundKey) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_aesenc_si128 (__m128i a, __m128i RoundKey)
+ /// AESENC xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Encrypt(Vector128<byte> value, Vector128<byte> roundKey) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_aesenclast_si128 (__m128i a, __m128i RoundKey)
+ /// AESENCLAST xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> EncryptLast(Vector128<byte> value, Vector128<byte> roundKey) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_aesimc_si128 (__m128i a)
+ /// AESIMC xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> InverseMixColumns(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_aeskeygenassist_si128 (__m128i a, const int imm8)
+ /// AESKEYGENASSIST xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> KeygenAssist(Vector128<byte> value, byte control) { throw new PlatformNotSupportedException(); }
+
+ }
+
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Aes.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Aes.cs
new file mode 100644
index 000000000..412a0c2f1
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Aes.cs
@@ -0,0 +1,58 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel AES hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Aes : Sse2
+ {
+ internal Aes() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// __m128i _mm_aesdec_si128 (__m128i a, __m128i RoundKey)
+ /// AESDEC xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Decrypt(Vector128<byte> value, Vector128<byte> roundKey) => Decrypt(value, roundKey);
+
+ /// <summary>
+ /// __m128i _mm_aesdeclast_si128 (__m128i a, __m128i RoundKey)
+ /// AESDECLAST xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> DecryptLast(Vector128<byte> value, Vector128<byte> roundKey) => DecryptLast(value, roundKey);
+
+ /// <summary>
+ /// __m128i _mm_aesenc_si128 (__m128i a, __m128i RoundKey)
+ /// AESENC xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Encrypt(Vector128<byte> value, Vector128<byte> roundKey) => Encrypt(value, roundKey);
+
+ /// <summary>
+ /// __m128i _mm_aesenclast_si128 (__m128i a, __m128i RoundKey)
+ /// AESENCLAST xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> EncryptLast(Vector128<byte> value, Vector128<byte> roundKey) => EncryptLast(value, roundKey);
+
+ /// <summary>
+ /// __m128i _mm_aesimc_si128 (__m128i a)
+ /// AESIMC xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> InverseMixColumns(Vector128<byte> value) => InverseMixColumns(value);
+
+ /// <summary>
+ /// __m128i _mm_aeskeygenassist_si128 (__m128i a, const int imm8)
+ /// AESKEYGENASSIST xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> KeygenAssist(Vector128<byte> value, byte control) => KeygenAssist(value, control);
+
+ }
+
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx.PlatformNotSupported.cs
new file mode 100644
index 000000000..d6597cfb5
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx.PlatformNotSupported.cs
@@ -0,0 +1,1230 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel AVX hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Avx : Sse42
+ {
+ internal Avx() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// __m256 _mm256_add_ps (__m256 a, __m256 b)
+ /// VADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Add(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_add_pd (__m256d a, __m256d b)
+ /// VADDPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Add(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_addsub_ps (__m256 a, __m256 b)
+ /// VADDSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> AddSubtract(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_addsub_pd (__m256d a, __m256d b)
+ /// VADDSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> AddSubtract(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_and_ps (__m256 a, __m256 b)
+ /// VANDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> And(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_and_pd (__m256d a, __m256d b)
+ /// VANDPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> And(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_andnot_ps (__m256 a, __m256 b)
+ /// VANDNPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> AndNot(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_andnot_pd (__m256d a, __m256d b)
+ /// VANDNPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> AndNot(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_blend_ps (__m256 a, __m256 b, const int imm8)
+ /// VBLENDPS ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<float> Blend(Vector256<float> left, Vector256<float> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_blend_pd (__m256d a, __m256d b, const int imm8)
+ /// VBLENDPD ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<double> Blend(Vector256<double> left, Vector256<double> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_blendv_ps (__m256 a, __m256 b, __m256 mask)
+ /// VBLENDVPS ymm, ymm, ymm/m256, ymm
+ /// </summary>
+ public static Vector256<float> BlendVariable(Vector256<float> left, Vector256<float> right, Vector256<float> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_blendv_pd (__m256d a, __m256d b, __m256d mask)
+ /// VBLENDVPD ymm, ymm, ymm/m256, ymm
+ /// </summary>
+ public static Vector256<double> BlendVariable(Vector256<double> left, Vector256<double> right, Vector256<double> mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_broadcast_ss (float const * mem_addr)
+ /// VBROADCASTSS xmm, m32
+ /// </summary>
+ public static unsafe Vector128<float> BroadcastScalarToVector128(float* source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_broadcast_ss (float const * mem_addr)
+ /// VBROADCASTSS ymm, m32
+ /// </summary>
+ public static unsafe Vector256<float> BroadcastScalarToVector256(float* source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_broadcast_sd (double const * mem_addr)
+ /// VBROADCASTSD ymm, m64
+ /// </summary>
+ public static unsafe Vector256<double> BroadcastScalarToVector256(double* source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_broadcast_ps (__m128 const * mem_addr)
+ /// VBROADCASTF128, ymm, m128
+ /// </summary>
+ public static unsafe Vector256<float> BroadcastVector128ToVector256(float* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_broadcast_pd (__m128d const * mem_addr)
+ /// VBROADCASTF128, ymm, m128
+ /// </summary>
+ public static unsafe Vector256<double> BroadcastVector128ToVector256(double* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_ceil_ps (__m256 a)
+ /// VROUNDPS ymm, ymm/m256, imm8(10)
+ /// </summary>
+ public static Vector256<float> Ceiling(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_ceil_pd (__m256d a)
+ /// VROUNDPD ymm, ymm/m256, imm8(10)
+ /// </summary>
+ public static Vector256<double> Ceiling(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmp_ps (__m128 a, __m128 b, const int imm8)
+ /// VCMPPS xmm, xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<float> Compare(Vector128<float> left, Vector128<float> right, FloatComparisonMode mode) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_cmp_pd (__m128d a, __m128d b, const int imm8)
+ /// VCMPPD xmm, xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<double> Compare(Vector128<double> left, Vector128<double> right, FloatComparisonMode mode) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_cmp_ps (__m256 a, __m256 b, const int imm8)
+ /// VCMPPS ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<float> Compare(Vector256<float> left, Vector256<float> right, FloatComparisonMode mode) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_cmp_pd (__m256d a, __m256d b, const int imm8)
+ /// VCMPPD ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<double> Compare(Vector256<double> left, Vector256<double> right, FloatComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmp_sd (__m128d a, __m128d b, const int imm8)
+ /// VCMPSS xmm, xmm, xmm/m32, imm8
+ /// </summary>
+ public static Vector128<double> CompareScalar(Vector128<double> left, Vector128<double> right, FloatComparisonMode mode) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_cmp_ss (__m128 a, __m128 b, const int imm8)
+ /// VCMPSD xmm, xmm, xmm/m64, imm8
+ /// </summary>
+ public static Vector128<float> CompareScalar(Vector128<float> left, Vector128<float> right, FloatComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float _mm256_cvtss_f32 (__m256 a)
+ /// HELPER: VMOVSS
+ /// </summary>
+ public static float ConvertToSingle(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_cvtpd_epi32 (__m256d a)
+ /// VCVTPD2DQ xmm, ymm/m256
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm256_cvtpd_ps (__m256d a)
+ /// VCVTPD2PS xmm, ymm/m256
+ /// </summary>
+ public static Vector128<float> ConvertToVector128Single(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtps_epi32 (__m256 a)
+ /// VCVTPS2DQ ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> ConvertToVector256Int32(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_cvtepi32_ps (__m256i a)
+ /// VCVTDQ2PS ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> ConvertToVector256Single(Vector256<int> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_cvtps_pd (__m128 a)
+ /// VCVTPS2PD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<double> ConvertToVector256Double(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_cvtepi32_pd (__m128i a)
+ /// VCVTDQ2PD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<double> ConvertToVector256Double(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_cvttpd_epi32 (__m256d a)
+ /// VCVTTPD2DQ xmm, ymm/m256
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32WithTruncation(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvttps_epi32 (__m256 a)
+ /// VCVTTPS2DQ ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> ConvertToVector256Int32WithTruncation(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_div_ps (__m256 a, __m256 b)
+ /// VDIVPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Divide(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_div_pd (__m256d a, __m256d b)
+ /// VDIVPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Divide(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_dp_ps (__m256 a, __m256 b, const int imm8)
+ /// VDPPS ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<float> DotProduct(Vector256<float> left, Vector256<float> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_moveldup_ps (__m256 a)
+ /// VMOVSLDUP ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> DuplicateEvenIndexed(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_movedup_pd (__m256d a)
+ /// VMOVDDUP ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> DuplicateEvenIndexed(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_movehdup_ps (__m256 a)
+ /// VMOVSHDUP ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> DuplicateOddIndexed(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __int8 _mm256_extract_epi8 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static byte Extract(Vector256<byte> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int16 _mm256_extract_epi16 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static ushort Extract(Vector256<ushort> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int32 _mm256_extract_epi32 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static int Extract(Vector256<int> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int32 _mm256_extract_epi32 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static uint Extract(Vector256<uint> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm256_extract_epi64 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static long Extract(Vector256<long> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm256_extract_epi64 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static ulong Extract(Vector256<ulong> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm256_extractf128_ps (__m256 a, const int imm8)
+ /// VEXTRACTF128 xmm/m128, ymm, imm8
+ /// __m128d _mm256_extractf128_pd (__m256d a, const int imm8)
+ /// VEXTRACTF128 xmm/m128, ymm, imm8
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 xmm/m128, ymm, imm8
+ /// </summary>
+ public static Vector128<T> ExtractVector128<T>(Vector256<T> value, byte index) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(byte* address, Vector256<byte> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(sbyte* address, Vector256<sbyte> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(short* address, Vector256<short> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(ushort* address, Vector256<ushort> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(int* address, Vector256<int> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(uint* address, Vector256<uint> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(long* address, Vector256<long> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(ulong* address, Vector256<ulong> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm256_extractf128_ps (__m256 a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(float* address, Vector256<float> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm256_extractf128_pd (__m256d a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(double* address, Vector256<double> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256d _mm256_castpd128_pd256 (__m128d a)
+ /// HELPER - No Codegen
+ /// __m256 _mm256_castps128_ps256 (__m128 a)
+ /// HELPER - No Codegen
+ /// __m256i _mm256_castsi128_si256 (__m128i a)
+ /// HELPER - No Codegen
+ /// </summary>
+ public static Vector256<T> ExtendToVector256<T>(Vector128<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_floor_ps (__m256 a)
+ /// VROUNDPS ymm, ymm/m256, imm8(9)
+ /// </summary>
+ public static Vector256<float> Floor(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_floor_pd (__m256d a)
+ /// VROUNDPS ymm, ymm/m256, imm8(9)
+ /// </summary>
+ public static Vector256<double> Floor(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm256_castpd256_pd128 (__m256d a)
+ /// HELPER - No Codegen
+ /// __m128 _mm256_castps256_ps128 (__m256 a)
+ /// HELPER - No Codegen
+ /// __m128i _mm256_castsi256_si128 (__m256i a)
+ /// HELPER - No Codegen
+ /// </summary>
+ public static Vector128<T> GetLowerHalf<T>(Vector256<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_hadd_ps (__m256 a, __m256 b)
+ /// VHADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> HorizontalAdd(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_hadd_pd (__m256d a, __m256d b)
+ /// VHADDPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> HorizontalAdd(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_hsub_ps (__m256 a, __m256 b)
+ /// VHSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> HorizontalSubtract(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_hsub_pd (__m256d a, __m256d b)
+ /// VHSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> HorizontalSubtract(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_insert_epi8 (__m256i a, __int8 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<sbyte> Insert(Vector256<sbyte> value, sbyte data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insert_epi8 (__m256i a, __int8 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<byte> Insert(Vector256<byte> value, byte data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insert_epi16 (__m256i a, __int16 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<short> Insert(Vector256<short> value, short data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insert_epi16 (__m256i a, __int16 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<ushort> Insert(Vector256<ushort> value, ushort data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insert_epi32 (__m256i a, __int32 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<int> Insert(Vector256<int> value, int data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insert_epi32 (__m256i a, __int32 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<uint> Insert(Vector256<uint> value, uint data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insert_epi64 (__m256i a, __int64 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<long> Insert(Vector256<long> value, long data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insert_epi64 (__m256i a, __int64 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<ulong> Insert(Vector256<ulong> value, ulong data, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_insertf128_ps (__m256 a, __m128 b, int imm8)
+ /// VINSERTF128 ymm, ymm, xmm/m128, imm8
+ /// __m256d _mm256_insertf128_pd (__m256d a, __m128d b, int imm8)
+ /// VINSERTF128 ymm, ymm, xmm/m128, imm8
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, xmm/m128, imm8
+ /// </summary>
+ public static Vector256<T> InsertVector128<T>(Vector256<T> value, Vector128<T> data, byte index) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<sbyte> InsertVector128(Vector256<sbyte> value, sbyte* address, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<byte> InsertVector128(Vector256<byte> value, byte* address, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<short> InsertVector128(Vector256<short> value, short* address, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<ushort> InsertVector128(Vector256<ushort> value, ushort* address, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<int> InsertVector128(Vector256<int> value, int* address, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<uint> InsertVector128(Vector256<uint> value, uint* address, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<long> InsertVector128(Vector256<long> value, long* address, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<ulong> InsertVector128(Vector256<ulong> value, ulong* address, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_insertf128_ps (__m256 a, __m128 b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<float> InsertVector128(Vector256<float> value, float* address, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_insertf128_pd (__m256d a, __m128d b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<double> InsertVector128(Vector256<double> value, double* address, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<sbyte> LoadVector256(sbyte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<byte> LoadVector256(byte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<short> LoadVector256(short* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ushort> LoadVector256(ushort* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<int> LoadVector256(int* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<uint> LoadVector256(uint* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<long> LoadVector256(long* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ulong> LoadVector256(ulong* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_loadu_ps (float const * mem_addr)
+ /// VMOVUPS ymm, ymm/m256
+ /// </summary>
+ public static unsafe Vector256<float> LoadVector256(float* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_loadu_pd (double const * mem_addr)
+ /// VMOVUPD ymm, ymm/m256
+ /// </summary>
+ public static unsafe Vector256<double> LoadVector256(double* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<sbyte> LoadAlignedVector256(sbyte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<byte> LoadAlignedVector256(byte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<short> LoadAlignedVector256(short* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ushort> LoadAlignedVector256(ushort* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<int> LoadAlignedVector256(int* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<uint> LoadAlignedVector256(uint* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<long> LoadAlignedVector256(long* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ulong> LoadAlignedVector256(ulong* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_load_ps (float const * mem_addr)
+ /// VMOVAPS ymm, ymm/m256
+ /// </summary>
+ public static unsafe Vector256<float> LoadAlignedVector256(float* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_load_pd (double const * mem_addr)
+ /// VMOVAPD ymm, ymm/m256
+ /// </summary>
+ public static unsafe Vector256<double> LoadAlignedVector256(double* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<sbyte> LoadDquVector256(sbyte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<byte> LoadDquVector256(byte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<short> LoadDquVector256(short* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ushort> LoadDquVector256(ushort* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<int> LoadDquVector256(int* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<uint> LoadDquVector256(uint* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<long> LoadDquVector256(long* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ulong> LoadDquVector256(ulong* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_maskload_ps (float const * mem_addr, __m128i mask)
+ /// VMASKMOVPS xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<float> MaskLoad(float* address, Vector128<float> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_maskload_pd (double const * mem_addr, __m128i mask)
+ /// VMASKMOVPD xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<double> MaskLoad(double* address, Vector128<double> mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_maskload_ps (float const * mem_addr, __m256i mask)
+ /// VMASKMOVPS ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<float> MaskLoad(float* address, Vector256<float> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_maskload_pd (double const * mem_addr, __m256i mask)
+ /// VMASKMOVPD ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<double> MaskLoad(double* address, Vector256<double> mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_maskstore_ps (float * mem_addr, __m128i mask, __m128 a)
+ /// VMASKMOVPS m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(float* address, Vector128<float> mask, Vector128<float> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_maskstore_pd (double * mem_addr, __m128i mask, __m128d a)
+ /// VMASKMOVPD m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(double* address, Vector128<double> mask, Vector128<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm256_maskstore_ps (float * mem_addr, __m256i mask, __m256 a)
+ /// VMASKMOVPS m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(float* address, Vector256<float> mask, Vector256<float> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_maskstore_pd (double * mem_addr, __m256i mask, __m256d a)
+ /// VMASKMOVPD m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(double* address, Vector256<double> mask, Vector256<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_max_ps (__m256 a, __m256 b)
+ /// VMAXPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Max(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_max_pd (__m256d a, __m256d b)
+ /// VMAXPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Max(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_min_ps (__m256 a, __m256 b)
+ /// VMINPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Min(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_min_pd (__m256d a, __m256d b)
+ /// VMINPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Min(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm256_movemask_ps (__m256 a)
+ /// VMOVMSKPS reg, ymm
+ /// </summary>
+ public static int MoveMask(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm256_movemask_pd (__m256d a)
+ /// VMOVMSKPD reg, ymm
+ /// </summary>
+ public static int MoveMask(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_mul_ps (__m256 a, __m256 b)
+ /// VMULPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Multiply(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_mul_pd (__m256d a, __m256d b)
+ /// VMULPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Multiply(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_or_ps (__m256 a, __m256 b)
+ /// VORPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Or(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_or_pd (__m256d a, __m256d b)
+ /// VORPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Or(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_permute_ps (__m128 a, int imm8)
+ /// VPERMILPS xmm, xmm, imm8
+ /// </summary>
+ public static Vector128<float> Permute(Vector128<float> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_permute_pd (__m128d a, int imm8)
+ /// VPERMILPD xmm, xmm, imm8
+ /// </summary>
+ public static Vector128<double> Permute(Vector128<double> value, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_permute_ps (__m256 a, int imm8)
+ /// VPERMILPS ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<float> Permute(Vector256<float> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_permute_pd (__m256d a, int imm8)
+ /// VPERMILPD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<double> Permute(Vector256<double> value, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_permute2f128_ps (__m256 a, __m256 b, int imm8)
+ /// VPERM2F128 ymm, ymm, ymm/m256, imm8
+ /// __m256d _mm256_permute2f128_pd (__m256d a, __m256d b, int imm8)
+ /// VPERM2F128 ymm, ymm, ymm/m256, imm8
+ /// __m256i _mm256_permute2f128_si256 (__m256i a, __m256i b, int imm8)
+ /// VPERM2F128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<T> Permute2x128<T>(Vector256<T> left, Vector256<T> right, byte control) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_permutevar_ps (__m128 a, __m128i b)
+ /// VPERMILPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> PermuteVar(Vector128<float> left, Vector128<int> control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_permutevar_pd (__m128d a, __m128i b)
+ /// VPERMILPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> PermuteVar(Vector128<double> left, Vector128<long> control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_permutevar_ps (__m256 a, __m256i b)
+ /// VPERMILPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> PermuteVar(Vector256<float> left, Vector256<int> control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_permutevar_pd (__m256d a, __m256i b)
+ /// VPERMILPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> PermuteVar(Vector256<double> left, Vector256<long> control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_rcp_ps (__m256 a)
+ /// VRCPPS ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Reciprocal(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_rsqrt_ps (__m256 a)
+ /// VRSQRTPS ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> ReciprocalSqrt(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_round_ps (__m256 a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)
+ /// VROUNDPS ymm, ymm/m256, imm8(8)
+ /// </summary>
+ public static Vector256<float> RoundToNearestInteger(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_round_ps (__m256 a, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC)
+ /// VROUNDPS ymm, ymm/m256, imm8(9)
+ /// </summary>
+ public static Vector256<float> RoundToNegativeInfinity(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_round_ps (__m256 a, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC)
+ /// VROUNDPS ymm, ymm/m256, imm8(10)
+ /// </summary>
+ public static Vector256<float> RoundToPositiveInfinity(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_round_ps (__m256 a, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC)
+ /// VROUNDPS ymm, ymm/m256, imm8(11)
+ /// </summary>
+ public static Vector256<float> RoundToZero(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_round_ps (__m256 a, _MM_FROUND_CUR_DIRECTION)
+ /// VROUNDPS ymm, ymm/m256, imm8(4)
+ /// </summary>
+ public static Vector256<float> RoundCurrentDirection(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256d _mm256_round_pd (__m256d a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)
+ /// VROUNDPD ymm, ymm/m256, imm8(8)
+ /// </summary>
+ public static Vector256<double> RoundToNearestInteger(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_round_pd (__m256d a, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC)
+ /// VROUNDPD ymm, ymm/m256, imm8(9)
+ /// </summary>
+ public static Vector256<double> RoundToNegativeInfinity(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_round_pd (__m256d a, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC)
+ /// VROUNDPD ymm, ymm/m256, imm8(10)
+ /// </summary>
+ public static Vector256<double> RoundToPositiveInfinity(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_round_pd (__m256d a, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC)
+ /// VROUNDPD ymm, ymm/m256, imm8(11)
+ /// </summary>
+ public static Vector256<double> RoundToZero(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_round_pd (__m256d a, _MM_FROUND_CUR_DIRECTION)
+ /// VROUNDPD ymm, ymm/m256, imm8(4)
+ /// </summary>
+ public static Vector256<double> RoundCurrentDirection(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_set_epi8 (char e31, char e30, char e29, char e28, char e27, char e26, char e25, char e24, char e23, char e22, char e21, char e20, char e19, char e18, char e17, char e16, char e15, char e14, char e13, char e12, char e11, char e10, char e9, char e8, char e7, char e6, char e5, char e4, char e3, char e2, char e1, char e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<sbyte> SetVector256(sbyte e31, sbyte e30, sbyte e29, sbyte e28, sbyte e27, sbyte e26, sbyte e25, sbyte e24, sbyte e23, sbyte e22, sbyte e21, sbyte e20, sbyte e19, sbyte e18, sbyte e17, sbyte e16, sbyte e15, sbyte e14, sbyte e13, sbyte e12, sbyte e11, sbyte e10, sbyte e9, sbyte e8, sbyte e7, sbyte e6, sbyte e5, sbyte e4, sbyte e3, sbyte e2, sbyte e1, sbyte e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_set_epi8 (char e31, char e30, char e29, char e28, char e27, char e26, char e25, char e24, char e23, char e22, char e21, char e20, char e19, char e18, char e17, char e16, char e15, char e14, char e13, char e12, char e11, char e10, char e9, char e8, char e7, char e6, char e5, char e4, char e3, char e2, char e1, char e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<byte> SetVector256(byte e31, byte e30, byte e29, byte e28, byte e27, byte e26, byte e25, byte e24, byte e23, byte e22, byte e21, byte e20, byte e19, byte e18, byte e17, byte e16, byte e15, byte e14, byte e13, byte e12, byte e11, byte e10, byte e9, byte e8, byte e7, byte e6, byte e5, byte e4, byte e3, byte e2, byte e1, byte e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_set_epi16 (short e15, short e14, short e13, short e12, short e11, short e10, short e9, short e8, short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<short> SetVector256(short e15, short e14, short e13, short e12, short e11, short e10, short e9, short e8, short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_set_epi16 (short e15, short e14, short e13, short e12, short e11, short e10, short e9, short e8, short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<ushort> SetVector256(ushort e15, ushort e14, ushort e13, ushort e12, ushort e11, ushort e10, ushort e9, ushort e8, ushort e7, ushort e6, ushort e5, ushort e4, ushort e3, ushort e2, ushort e1, ushort e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_set_epi32 (int e7, int e6, int e5, int e4, int e3, int e2, int e1, int e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<int> SetVector256(int e7, int e6, int e5, int e4, int e3, int e2, int e1, int e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_set_epi32 (int e7, int e6, int e5, int e4, int e3, int e2, int e1, int e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<uint> SetVector256(uint e7, uint e6, uint e5, uint e4, uint e3, uint e2, uint e1, uint e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_set_epi64x (__int64 e3, __int64 e2, __int64 e1, __int64 e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<long> SetVector256(long e3, long e2, long e1, long e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_set_epi64x (__int64 e3, __int64 e2, __int64 e1, __int64 e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<ulong> SetVector256(ulong e3, ulong e2, ulong e1, ulong e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_set_ps (float e7, float e6, float e5, float e4, float e3, float e2, float e1, float e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<float> SetVector256(float e7, float e6, float e5, float e4, float e3, float e2, float e1, float e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_set_pd (double e3, double e2, double e1, double e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<double> SetVector256(double e3, double e2, double e1, double e0) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_set1_epi8 (char a)
+ /// HELPER
+ /// __m256i _mm256_set1_epi16 (short a)
+ /// HELPER
+ /// __m256i _mm256_set1_epi32 (int a)
+ /// HELPER
+ /// __m256i _mm256_set1_epi64x (long long a)
+ /// HELPER
+ /// __m256 _mm256_set1_ps (float a)
+ /// HELPER
+ /// __m256d _mm256_set1_pd (double a)
+ /// HELPER
+ /// </summary>
+ public static Vector256<T> SetAllVector256<T>(T value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_set_m128 (__m128 hi, __m128 lo)
+ /// HELPER
+ /// __m256d _mm256_set_m128d (__m128d hi, __m128d lo)
+ /// HELPER
+ /// __m256i _mm256_set_m128i (__m128i hi, __m128i lo)
+ /// HELPER
+ /// </summary>
+ public static Vector256<T> SetHighLow<T>(Vector128<T> hi, Vector128<T> lo) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_setzero_si256 (void)
+ /// HELPER
+ /// __m256 _mm256_setzero_ps (void)
+ /// HELPER
+ /// __m256d _mm256_setzero_pd (void)
+ /// HELPER
+ /// </summary>
+ public static Vector256<T> SetZeroVector256<T>() where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_shuffle_ps (__m256 a, __m256 b, const int imm8)
+ /// VSHUFPS ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<float> Shuffle(Vector256<float> value, Vector256<float> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_shuffle_pd (__m256d a, __m256d b, const int imm8)
+ /// VSHUFPD ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<double> Shuffle(Vector256<double> value, Vector256<double> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_sqrt_ps (__m256 a)
+ /// VSQRTPS ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Sqrt(Vector256<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_sqrt_pd (__m256d a)
+ /// VSQRTPD ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Sqrt(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_castpd_ps (__m256d a)
+ /// HELPER - No Codegen
+ /// __m256i _mm256_castpd_si256 (__m256d a)
+ /// HELPER - No Codegen
+ /// __m256d _mm256_castps_pd (__m256 a)
+ /// HELPER - No Codegen
+ /// __m256i _mm256_castps_si256 (__m256 a)
+ /// HELPER - No Codegen
+ /// __m256d _mm256_castsi256_pd (__m256i a)
+ /// HELPER - No Codegen
+ /// __m256 _mm256_castsi256_ps (__m256i a)
+ /// HELPER - No Codegen
+ /// </summary>
+ public static Vector256<U> StaticCast<T, U>(Vector256<T> value) where T : struct where U : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(sbyte* address, Vector256<sbyte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(byte* address, Vector256<byte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(short* address, Vector256<short> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(ushort* address, Vector256<ushort> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(int* address, Vector256<int> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(uint* address, Vector256<uint> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(long* address, Vector256<long> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(ulong* address, Vector256<ulong> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_store_ps (float * mem_addr, __m256 a)
+ /// VMOVAPS m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(float* address, Vector256<float> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_store_pd (double * mem_addr, __m256d a)
+ /// VMOVAPD m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(double* address, Vector256<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(sbyte* address, Vector256<sbyte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(byte* address, Vector256<byte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(short* address, Vector256<short> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(ushort* address, Vector256<ushort> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(int* address, Vector256<int> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(uint* address, Vector256<uint> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(long* address, Vector256<long> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(ulong* address, Vector256<ulong> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_stream_ps (float * mem_addr, __m256 a)
+ /// MOVNTPS m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(float* address, Vector256<float> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_stream_pd (double * mem_addr, __m256d a)
+ /// MOVNTPD m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(double* address, Vector256<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(sbyte* address, Vector256<sbyte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(byte* address, Vector256<byte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(short* address, Vector256<short> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(ushort* address, Vector256<ushort> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(int* address, Vector256<int> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(uint* address, Vector256<uint> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(long* address, Vector256<long> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(ulong* address, Vector256<ulong> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_storeu_ps (float * mem_addr, __m256 a)
+ /// MOVUPS m256, ymm
+ /// </summary>
+ public static unsafe void Store(float* address, Vector256<float> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_storeu_pd (double * mem_addr, __m256d a)
+ /// MOVUPD m256, ymm
+ /// </summary>
+ public static unsafe void Store(double* address, Vector256<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_sub_ps (__m256 a, __m256 b)
+ /// VSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Subtract(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_sub_pd (__m256d a, __m256d b)
+ /// VSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Subtract(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_testc_ps (__m128 a, __m128 b)
+ /// VTESTPS xmm, xmm/m128
+ /// </summary>
+ public static bool TestC(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_testc_pd (__m128d a, __m128d b)
+ /// VTESTPD xmm, xmm/m128
+ /// </summary>
+ public static bool TestC(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm256_testc_si256 (__m256i a, __m256i b)
+ /// VPTEST ymm, ymm/m256
+ /// int _mm256_testc_ps (__m256 a, __m256 b)
+ /// VTESTPS ymm, ymm/m256
+ /// int _mm256_testc_pd (__m256d a, __m256d b)
+ /// VTESTPS ymm, ymm/m256
+ /// </summary>
+ public static bool TestC<T>(Vector256<T> left, Vector256<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_testnzc_ps (__m128 a, __m128 b)
+ /// VTESTPS xmm, xmm/m128
+ /// </summary>
+ public static bool TestNotZAndNotC(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_testnzc_pd (__m128d a, __m128d b)
+ /// VTESTPD xmm, xmm/m128
+ /// </summary>
+ public static bool TestNotZAndNotC(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm256_testnzc_si256 (__m256i a, __m256i b)
+ /// VPTEST ymm, ymm/m256
+ /// int _mm256_testnzc_ps (__m256 a, __m256 b)
+ /// VTESTPS ymm, ymm/m256
+ /// int _mm256_testnzc_pd (__m256d a, __m256d b)
+ /// VTESTPD ymm, ymm/m256
+ /// </summary>
+ public static bool TestNotZAndNotC<T>(Vector256<T> left, Vector256<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_testz_ps (__m128 a, __m128 b)
+ /// VTESTPS xmm, xmm/m128
+ /// </summary>
+ public static bool TestZ(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_testz_pd (__m128d a, __m128d b)
+ /// VTESTPD xmm, xmm/m128
+ /// </summary>
+ public static bool TestZ(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm256_testz_si256 (__m256i a, __m256i b)
+ /// VPTEST ymm, ymm/m256
+ /// int _mm256_testz_ps (__m256 a, __m256 b)
+ /// VTESTPS ymm, ymm/m256
+ /// int _mm256_testz_pd (__m256d a, __m256d b)
+ /// VTESTPD ymm, ymm/m256
+ /// </summary>
+ public static bool TestZ<T>(Vector256<T> left, Vector256<T> right) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_unpackhi_ps (__m256 a, __m256 b)
+ /// VUNPCKHPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> UnpackHigh(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_unpackhi_pd (__m256d a, __m256d b)
+ /// VUNPCKHPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> UnpackHigh(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_unpacklo_ps (__m256 a, __m256 b)
+ /// VUNPCKLPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> UnpackLow(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_unpacklo_pd (__m256d a, __m256d b)
+ /// VUNPCKLPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> UnpackLow(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256 _mm256_xor_ps (__m256 a, __m256 b)
+ /// VXORPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Xor(Vector256<float> left, Vector256<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_xor_pd (__m256d a, __m256d b)
+ /// VXORPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Xor(Vector256<double> left, Vector256<double> right) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx.cs
new file mode 100644
index 000000000..3cb6849a6
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx.cs
@@ -0,0 +1,1412 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+using Internal.Runtime.CompilerServices;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel AVX hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Avx : Sse42
+ {
+ internal Avx() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// __m256 _mm256_add_ps (__m256 a, __m256 b)
+ /// VADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Add(Vector256<float> left, Vector256<float> right) => Add(left, right);
+ /// <summary>
+ /// __m256d _mm256_add_pd (__m256d a, __m256d b)
+ /// VADDPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Add(Vector256<double> left, Vector256<double> right) => Add(left, right);
+
+ /// <summary>
+ /// __m256 _mm256_addsub_ps (__m256 a, __m256 b)
+ /// VADDSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> AddSubtract(Vector256<float> left, Vector256<float> right) => AddSubtract(left, right);
+ /// <summary>
+ /// __m256d _mm256_addsub_pd (__m256d a, __m256d b)
+ /// VADDSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> AddSubtract(Vector256<double> left, Vector256<double> right) => AddSubtract(left, right);
+
+ /// <summary>
+ /// __m256 _mm256_and_ps (__m256 a, __m256 b)
+ /// VANDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> And(Vector256<float> left, Vector256<float> right) => And(left, right);
+ /// <summary>
+ /// __m256d _mm256_and_pd (__m256d a, __m256d b)
+ /// VANDPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> And(Vector256<double> left, Vector256<double> right) => And(left, right);
+
+ /// <summary>
+ /// __m256 _mm256_andnot_ps (__m256 a, __m256 b)
+ /// VANDNPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> AndNot(Vector256<float> left, Vector256<float> right) => AndNot(left, right);
+ /// <summary>
+ /// __m256d _mm256_andnot_pd (__m256d a, __m256d b)
+ /// VANDNPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> AndNot(Vector256<double> left, Vector256<double> right) => AndNot(left, right);
+
+ /// <summary>
+ /// __m256 _mm256_blend_ps (__m256 a, __m256 b, const int imm8)
+ /// VBLENDPS ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<float> Blend(Vector256<float> left, Vector256<float> right, byte control) => Blend(left, right, control);
+ /// <summary>
+ /// __m256d _mm256_blend_pd (__m256d a, __m256d b, const int imm8)
+ /// VBLENDPD ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<double> Blend(Vector256<double> left, Vector256<double> right, byte control) => Blend(left, right, control);
+
+ /// <summary>
+ /// __m256 _mm256_blendv_ps (__m256 a, __m256 b, __m256 mask)
+ /// VBLENDVPS ymm, ymm, ymm/m256, ymm
+ /// </summary>
+ public static Vector256<float> BlendVariable(Vector256<float> left, Vector256<float> right, Vector256<float> mask) => BlendVariable(left, right, mask);
+ /// <summary>
+ /// __m256d _mm256_blendv_pd (__m256d a, __m256d b, __m256d mask)
+ /// VBLENDVPD ymm, ymm, ymm/m256, ymm
+ /// </summary>
+ public static Vector256<double> BlendVariable(Vector256<double> left, Vector256<double> right, Vector256<double> mask) => BlendVariable(left, right, mask);
+
+ /// <summary>
+ /// __m128 _mm_broadcast_ss (float const * mem_addr)
+ /// VBROADCASTSS xmm, m32
+ /// </summary>
+ public static unsafe Vector128<float> BroadcastScalarToVector128(float* source) => BroadcastScalarToVector128(source);
+
+ /// <summary>
+ /// __m256 _mm256_broadcast_ss (float const * mem_addr)
+ /// VBROADCASTSS ymm, m32
+ /// </summary>
+ public static unsafe Vector256<float> BroadcastScalarToVector256(float* source) => BroadcastScalarToVector256(source);
+ /// <summary>
+ /// __m256d _mm256_broadcast_sd (double const * mem_addr)
+ /// VBROADCASTSD ymm, m64
+ /// </summary>
+ public static unsafe Vector256<double> BroadcastScalarToVector256(double* source) => BroadcastScalarToVector256(source);
+
+ /// <summary>
+ /// __m256 _mm256_broadcast_ps (__m128 const * mem_addr)
+ /// VBROADCASTF128, ymm, m128
+ /// </summary>
+ public static unsafe Vector256<float> BroadcastVector128ToVector256(float* address) => BroadcastVector128ToVector256(address);
+ /// <summary>
+ /// __m256d _mm256_broadcast_pd (__m128d const * mem_addr)
+ /// VBROADCASTF128, ymm, m128
+ /// </summary>
+ public static unsafe Vector256<double> BroadcastVector128ToVector256(double* address) => BroadcastVector128ToVector256(address);
+
+ /// <summary>
+ /// __m256 _mm256_ceil_ps (__m256 a)
+ /// VROUNDPS ymm, ymm/m256, imm8(10)
+ /// </summary>
+ public static Vector256<float> Ceiling(Vector256<float> value) => Ceiling(value);
+ /// <summary>
+ /// __m256d _mm256_ceil_pd (__m256d a)
+ /// VROUNDPD ymm, ymm/m256, imm8(10)
+ /// </summary>
+ public static Vector256<double> Ceiling(Vector256<double> value) => Ceiling(value);
+
+ /// <summary>
+ /// __m128 _mm_cmp_ps (__m128 a, __m128 b, const int imm8)
+ /// VCMPPS xmm, xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<float> Compare(Vector128<float> left, Vector128<float> right, FloatComparisonMode mode) => Compare(left, right, mode);
+ /// <summary>
+ /// __m128d _mm_cmp_pd (__m128d a, __m128d b, const int imm8)
+ /// VCMPPD xmm, xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<double> Compare(Vector128<double> left, Vector128<double> right, FloatComparisonMode mode) => Compare(left, right, mode);
+ /// <summary>
+ /// __m256 _mm256_cmp_ps (__m256 a, __m256 b, const int imm8)
+ /// VCMPPS ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<float> Compare(Vector256<float> left, Vector256<float> right, FloatComparisonMode mode) => Compare(left, right, mode);
+ /// <summary>
+ /// __m256d _mm256_cmp_pd (__m256d a, __m256d b, const int imm8)
+ /// VCMPPD ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<double> Compare(Vector256<double> left, Vector256<double> right, FloatComparisonMode mode) => Compare(left, right, mode);
+
+ /// <summary>
+ /// __m128d _mm_cmp_sd (__m128d a, __m128d b, const int imm8)
+ /// VCMPSS xmm, xmm, xmm/m32, imm8
+ /// </summary>
+ public static Vector128<double> CompareScalar(Vector128<double> left, Vector128<double> right, FloatComparisonMode mode) => CompareScalar(left, right, mode);
+ /// <summary>
+ /// __m128 _mm_cmp_ss (__m128 a, __m128 b, const int imm8)
+ /// VCMPSD xmm, xmm, xmm/m64, imm8
+ /// </summary>
+ public static Vector128<float> CompareScalar(Vector128<float> left, Vector128<float> right, FloatComparisonMode mode) => CompareScalar(left, right, mode);
+
+ /// <summary>
+ /// float _mm256_cvtss_f32 (__m256 a)
+ /// HELPER: VMOVSS
+ /// </summary>
+ public static float ConvertToSingle(Vector256<float> value) => ConvertToSingle(value);
+
+ /// <summary>
+ /// __m128i _mm256_cvtpd_epi32 (__m256d a)
+ /// VCVTPD2DQ xmm, ymm/m256
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector256<double> value) => ConvertToVector128Int32(value);
+ /// <summary>
+ /// __m128 _mm256_cvtpd_ps (__m256d a)
+ /// VCVTPD2PS xmm, ymm/m256
+ /// </summary>
+ public static Vector128<float> ConvertToVector128Single(Vector256<double> value) => ConvertToVector128Single(value);
+ /// <summary>
+ /// __m256i _mm256_cvtps_epi32 (__m256 a)
+ /// VCVTPS2DQ ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> ConvertToVector256Int32(Vector256<float> value) => ConvertToVector256Int32(value);
+ /// <summary>
+ /// __m256 _mm256_cvtepi32_ps (__m256i a)
+ /// VCVTDQ2PS ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> ConvertToVector256Single(Vector256<int> value) => ConvertToVector256Single(value);
+ /// <summary>
+ /// __m256d _mm256_cvtps_pd (__m128 a)
+ /// VCVTPS2PD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<double> ConvertToVector256Double(Vector128<float> value) => ConvertToVector256Double(value);
+ /// <summary>
+ /// __m256d _mm256_cvtepi32_pd (__m128i a)
+ /// VCVTDQ2PD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<double> ConvertToVector256Double(Vector128<int> value) => ConvertToVector256Double(value);
+
+ /// <summary>
+ /// __m128i _mm256_cvttpd_epi32 (__m256d a)
+ /// VCVTTPD2DQ xmm, ymm/m256
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32WithTruncation(Vector256<double> value) => ConvertToVector128Int32WithTruncation(value);
+ /// <summary>
+ /// __m256i _mm256_cvttps_epi32 (__m256 a)
+ /// VCVTTPS2DQ ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> ConvertToVector256Int32WithTruncation(Vector256<float> value) => ConvertToVector256Int32WithTruncation(value);
+
+ /// <summary>
+ /// __m256 _mm256_div_ps (__m256 a, __m256 b)
+ /// VDIVPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Divide(Vector256<float> left, Vector256<float> right) => Divide(left, right);
+ /// <summary>
+ /// __m256d _mm256_div_pd (__m256d a, __m256d b)
+ /// VDIVPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Divide(Vector256<double> left, Vector256<double> right) => Divide(left, right);
+
+ /// <summary>
+ /// __m256 _mm256_dp_ps (__m256 a, __m256 b, const int imm8)
+ /// VDPPS ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<float> DotProduct(Vector256<float> left, Vector256<float> right, byte control) => DotProduct(left, right, control);
+
+ /// <summary>
+ /// __m256 _mm256_moveldup_ps (__m256 a)
+ /// VMOVSLDUP ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> DuplicateEvenIndexed(Vector256<float> value) => DuplicateEvenIndexed(value);
+ /// <summary>
+ /// __m256d _mm256_movedup_pd (__m256d a)
+ /// VMOVDDUP ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> DuplicateEvenIndexed(Vector256<double> value) => DuplicateEvenIndexed(value);
+
+ /// <summary>
+ /// __m256 _mm256_movehdup_ps (__m256 a)
+ /// VMOVSHDUP ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> DuplicateOddIndexed(Vector256<float> value) => DuplicateOddIndexed(value);
+
+ /// <summary>
+ /// __int8 _mm256_extract_epi8 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static byte Extract(Vector256<byte> value, byte index)
+ {
+ if (!IsSupported)
+ {
+ throw new PlatformNotSupportedException();
+ }
+ return Unsafe.Add<byte>(ref Unsafe.As<Vector256<byte>, byte>(ref value), index & 0x1F);
+ }
+
+
+ /// <summary>
+ /// __int16 _mm256_extract_epi16 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static ushort Extract(Vector256<ushort> value, byte index)
+ {
+ if (!IsSupported)
+ {
+ throw new PlatformNotSupportedException();
+ }
+ return Unsafe.Add<ushort>(ref Unsafe.As<Vector256<ushort>, ushort>(ref value), index & 0xF);
+ }
+
+ /// <summary>
+ /// __int32 _mm256_extract_epi32 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static int Extract(Vector256<int> value, byte index)
+ {
+ if (!IsSupported)
+ {
+ throw new PlatformNotSupportedException();
+ }
+ return Unsafe.Add<int>(ref Unsafe.As<Vector256<int>, int>(ref value), index & 0x7);
+ }
+
+ /// <summary>
+ /// __int32 _mm256_extract_epi32 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static uint Extract(Vector256<uint> value, byte index)
+ {
+ if (!IsSupported)
+ {
+ throw new PlatformNotSupportedException();
+ }
+ return Unsafe.Add<uint>(ref Unsafe.As<Vector256<uint>, uint>(ref value), index & 0x7);
+ }
+
+ /// <summary>
+ /// __int64 _mm256_extract_epi64 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static long Extract(Vector256<long> value, byte index)
+ {
+ if (!IsSupported || (IntPtr.Size != 8))
+ {
+ throw new PlatformNotSupportedException();
+ }
+ return Unsafe.Add<long>(ref Unsafe.As<Vector256<long>, long>(ref value), index & 0x3);
+ }
+
+ /// <summary>
+ /// __int64 _mm256_extract_epi64 (__m256i a, const int index)
+ /// HELPER
+ /// </summary>
+ public static ulong Extract(Vector256<ulong> value, byte index)
+ {
+ if (!IsSupported || (IntPtr.Size != 8))
+ {
+ throw new PlatformNotSupportedException();
+ }
+ return Unsafe.Add<ulong>(ref Unsafe.As<Vector256<ulong>, ulong>(ref value), index & 0x3);
+ }
+
+ /// <summary>
+ /// __m128 _mm256_extractf128_ps (__m256 a, const int imm8)
+ /// VEXTRACTF128 xmm/m128, ymm, imm8
+ /// __m128d _mm256_extractf128_pd (__m256d a, const int imm8)
+ /// VEXTRACTF128 xmm/m128, ymm, imm8
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 xmm/m128, ymm, imm8
+ /// </summary>
+ public static Vector128<T> ExtractVector128<T>(Vector256<T> value, byte index) where T : struct
+ {
+ return ExtractVector128<T>(value, index);
+ }
+
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(byte* address, Vector256<byte> value, byte index) => ExtractVector128(address, value, index);
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(sbyte* address, Vector256<sbyte> value, byte index) => ExtractVector128(address, value, index);
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(short* address, Vector256<short> value, byte index) => ExtractVector128(address, value, index);
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(ushort* address, Vector256<ushort> value, byte index) => ExtractVector128(address, value, index);
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(int* address, Vector256<int> value, byte index) => ExtractVector128(address, value, index);
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(uint* address, Vector256<uint> value, byte index) => ExtractVector128(address, value, index);
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(long* address, Vector256<long> value, byte index) => ExtractVector128(address, value, index);
+ /// <summary>
+ /// __m128i _mm256_extractf128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(ulong* address, Vector256<ulong> value, byte index) => ExtractVector128(address, value, index);
+ /// <summary>
+ /// __m128 _mm256_extractf128_ps (__m256 a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(float* address, Vector256<float> value, byte index) => ExtractVector128(address, value, index);
+ /// <summary>
+ /// __m128d _mm256_extractf128_pd (__m256d a, const int imm8)
+ /// VEXTRACTF128 m128, ymm, imm8
+ /// </summary>
+ public static unsafe void ExtractVector128(double* address, Vector256<double> value, byte index) => ExtractVector128(address, value, index);
+
+ /// <summary>
+ /// __m256d _mm256_castpd128_pd256 (__m128d a)
+ /// HELPER - No Codegen
+ /// __m256 _mm256_castps128_ps256 (__m128 a)
+ /// HELPER - No Codegen
+ /// __m256i _mm256_castsi128_si256 (__m128i a)
+ /// HELPER - No Codegen
+ /// </summary>
+ public static Vector256<T> ExtendToVector256<T>(Vector128<T> value) where T : struct
+ {
+ return ExtendToVector256<T>(value);
+ }
+
+ /// <summary>
+ /// __m256 _mm256_floor_ps (__m256 a)
+ /// VROUNDPS ymm, ymm/m256, imm8(9)
+ /// </summary>
+ public static Vector256<float> Floor(Vector256<float> value) => Floor(value);
+ /// <summary>
+ /// __m256d _mm256_floor_pd (__m256d a)
+ /// VROUNDPS ymm, ymm/m256, imm8(9)
+ /// </summary>
+ public static Vector256<double> Floor(Vector256<double> value) => Floor(value);
+
+ /// <summary>
+ /// __m128d _mm256_castpd256_pd128 (__m256d a)
+ /// HELPER - No Codegen
+ /// __m128 _mm256_castps256_ps128 (__m256 a)
+ /// HELPER - No Codegen
+ /// __m128i _mm256_castsi256_si128 (__m256i a)
+ /// HELPER - No Codegen
+ /// </summary>
+ public static Vector128<T> GetLowerHalf<T>(Vector256<T> value) where T : struct
+ {
+ return GetLowerHalf<T>(value);
+ }
+
+ /// <summary>
+ /// __m256 _mm256_hadd_ps (__m256 a, __m256 b)
+ /// VHADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> HorizontalAdd(Vector256<float> left, Vector256<float> right) => HorizontalAdd(left, right);
+ /// <summary>
+ /// __m256d _mm256_hadd_pd (__m256d a, __m256d b)
+ /// VHADDPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> HorizontalAdd(Vector256<double> left, Vector256<double> right) => HorizontalAdd(left, right);
+
+ /// <summary>
+ /// __m256 _mm256_hsub_ps (__m256 a, __m256 b)
+ /// VHSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> HorizontalSubtract(Vector256<float> left, Vector256<float> right) => HorizontalSubtract(left, right);
+ /// <summary>
+ /// __m256d _mm256_hsub_pd (__m256d a, __m256d b)
+ /// VHSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> HorizontalSubtract(Vector256<double> left, Vector256<double> right) => HorizontalSubtract(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_insert_epi8 (__m256i a, __int8 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<sbyte> Insert(Vector256<sbyte> value, sbyte data, byte index)
+ {
+ unsafe
+ {
+ index &= 0x1F;
+ sbyte* buffer = stackalloc sbyte[32];
+ Store(buffer, value);
+ buffer[index] = data;
+ return LoadVector256(buffer);
+ }
+ }
+
+ /// <summary>
+ /// __m256i _mm256_insert_epi8 (__m256i a, __int8 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<byte> Insert(Vector256<byte> value, byte data, byte index)
+ {
+ unsafe
+ {
+ index &= 0x1F;
+ byte* buffer = stackalloc byte[32];
+ Store(buffer, value);
+ buffer[index] = data;
+ return LoadVector256(buffer);
+ }
+ }
+
+ /// <summary>
+ /// __m256i _mm256_insert_epi16 (__m256i a, __int16 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<short> Insert(Vector256<short> value, short data, byte index)
+ {
+ unsafe
+ {
+ index &= 0xF;
+ short* buffer = stackalloc short[16];
+ Store(buffer, value);
+ buffer[index] = data;
+ return LoadVector256(buffer);
+ }
+ }
+
+ /// <summary>
+ /// __m256i _mm256_insert_epi16 (__m256i a, __int16 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<ushort> Insert(Vector256<ushort> value, ushort data, byte index)
+ {
+ unsafe
+ {
+ index &= 0xF;
+ ushort* buffer = stackalloc ushort[16];
+ Store(buffer, value);
+ buffer[index] = data;
+ return LoadVector256(buffer);
+ }
+ }
+
+ /// <summary>
+ /// __m256i _mm256_insert_epi32 (__m256i a, __int32 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<int> Insert(Vector256<int> value, int data, byte index)
+ {
+ unsafe
+ {
+ index &= 0x7;
+ int* buffer = stackalloc int[8];
+ Store(buffer, value);
+ buffer[index] = data;
+ return LoadVector256(buffer);
+ }
+ }
+
+ /// <summary>
+ /// __m256i _mm256_insert_epi32 (__m256i a, __int32 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<uint> Insert(Vector256<uint> value, uint data, byte index)
+ {
+ unsafe
+ {
+ index &= 0x7;
+ uint* buffer = stackalloc uint[8];
+ Store(buffer, value);
+ buffer[index] = data;
+ return LoadVector256(buffer);
+ }
+ }
+
+ /// <summary>
+ /// __m256i _mm256_insert_epi64 (__m256i a, __int64 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<long> Insert(Vector256<long> value, long data, byte index)
+ {
+ if (IntPtr.Size != 8)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ unsafe
+ {
+ index &= 0x3;
+ long* buffer = stackalloc long[4];
+ Store(buffer, value);
+ buffer[index] = data;
+ return LoadVector256(buffer);
+ }
+ }
+
+ /// <summary>
+ /// __m256i _mm256_insert_epi64 (__m256i a, __int64 i, const int index)
+ /// HELPER
+ /// </summary>
+ public static Vector256<ulong> Insert(Vector256<ulong> value, ulong data, byte index)
+ {
+ if (IntPtr.Size != 8)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ unsafe
+ {
+ index &= 0x3;
+ ulong* buffer = stackalloc ulong[4];
+ Store(buffer, value);
+ buffer[index] = data;
+ return LoadVector256(buffer);
+ }
+ }
+
+ /// <summary>
+ /// __m256 _mm256_insertf128_ps (__m256 a, __m128 b, int imm8)
+ /// VINSERTF128 ymm, ymm, xmm/m128, imm8
+ /// __m256d _mm256_insertf128_pd (__m256d a, __m128d b, int imm8)
+ /// VINSERTF128 ymm, ymm, xmm/m128, imm8
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, xmm/m128, imm8
+ /// </summary>
+ public static Vector256<T> InsertVector128<T>(Vector256<T> value, Vector128<T> data, byte index) where T : struct
+ {
+ return InsertVector128<T>(value, data, index);
+ }
+
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<sbyte> InsertVector128(Vector256<sbyte> value, sbyte* address, byte index) => InsertVector128(value, address, index);
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<byte> InsertVector128(Vector256<byte> value, byte* address, byte index) => InsertVector128(value, address, index);
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<short> InsertVector128(Vector256<short> value, short* address, byte index) => InsertVector128(value, address, index);
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<ushort> InsertVector128(Vector256<ushort> value, ushort* address, byte index) => InsertVector128(value, address, index);
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<int> InsertVector128(Vector256<int> value, int* address, byte index) => InsertVector128(value, address, index);
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<uint> InsertVector128(Vector256<uint> value, uint* address, byte index) => InsertVector128(value, address, index);
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<long> InsertVector128(Vector256<long> value, long* address, byte index) => InsertVector128(value, address, index);
+ /// <summary>
+ /// __m256i _mm256_insertf128_si256 (__m256i a, __m128i b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<ulong> InsertVector128(Vector256<ulong> value, ulong* address, byte index) => InsertVector128(value, address, index);
+ /// <summary>
+ /// __m256 _mm256_insertf128_ps (__m256 a, __m128 b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<float> InsertVector128(Vector256<float> value, float* address, byte index) => InsertVector128(value, address, index);
+ /// <summary>
+ /// __m256d _mm256_insertf128_pd (__m256d a, __m128d b, int imm8)
+ /// VINSERTF128 ymm, ymm, m128, imm8
+ /// </summary>
+ public static unsafe Vector256<double> InsertVector128(Vector256<double> value, double* address, byte index) => InsertVector128(value, address, index);
+
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<sbyte> LoadVector256(sbyte* address) => LoadVector256(address);
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<byte> LoadVector256(byte* address) => LoadVector256(address);
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<short> LoadVector256(short* address) => LoadVector256(address);
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ushort> LoadVector256(ushort* address) => LoadVector256(address);
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<int> LoadVector256(int* address) => LoadVector256(address);
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<uint> LoadVector256(uint* address) => LoadVector256(address);
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<long> LoadVector256(long* address) => LoadVector256(address);
+ /// <summary>
+ /// __m256i _mm256_loadu_si256 (__m256i const * mem_addr)
+ /// VMOVDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ulong> LoadVector256(ulong* address) => LoadVector256(address);
+ /// <summary>
+ /// __m256 _mm256_loadu_ps (float const * mem_addr)
+ /// VMOVUPS ymm, ymm/m256
+ /// </summary>
+ public static unsafe Vector256<float> LoadVector256(float* address) => LoadVector256(address);
+ /// <summary>
+ /// __m256d _mm256_loadu_pd (double const * mem_addr)
+ /// VMOVUPD ymm, ymm/m256
+ /// </summary>
+ public static unsafe Vector256<double> LoadVector256(double* address) => LoadVector256(address);
+
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<sbyte> LoadAlignedVector256(sbyte* address) => LoadAlignedVector256(address);
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<byte> LoadAlignedVector256(byte* address) => LoadAlignedVector256(address);
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<short> LoadAlignedVector256(short* address) => LoadAlignedVector256(address);
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ushort> LoadAlignedVector256(ushort* address) => LoadAlignedVector256(address);
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<int> LoadAlignedVector256(int* address) => LoadAlignedVector256(address);
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<uint> LoadAlignedVector256(uint* address) => LoadAlignedVector256(address);
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<long> LoadAlignedVector256(long* address) => LoadAlignedVector256(address);
+ /// <summary>
+ /// __m256i _mm256_load_si256 (__m256i const * mem_addr)
+ /// VMOVDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ulong> LoadAlignedVector256(ulong* address) => LoadAlignedVector256(address);
+ /// <summary>
+ /// __m256 _mm256_load_ps (float const * mem_addr)
+ /// VMOVAPS ymm, ymm/m256
+ /// </summary>
+ public static unsafe Vector256<float> LoadAlignedVector256(float* address) => LoadAlignedVector256(address);
+ /// <summary>
+ /// __m256d _mm256_load_pd (double const * mem_addr)
+ /// VMOVAPD ymm, ymm/m256
+ /// </summary>
+ public static unsafe Vector256<double> LoadAlignedVector256(double* address) => LoadAlignedVector256(address);
+
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<sbyte> LoadDquVector256(sbyte* address) => LoadDquVector256(address);
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<byte> LoadDquVector256(byte* address) => LoadDquVector256(address);
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<short> LoadDquVector256(short* address) => LoadDquVector256(address);
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ushort> LoadDquVector256(ushort* address) => LoadDquVector256(address);
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<int> LoadDquVector256(int* address) => LoadDquVector256(address);
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<uint> LoadDquVector256(uint* address) => LoadDquVector256(address);
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<long> LoadDquVector256(long* address) => LoadDquVector256(address);
+ /// <summary>
+ /// __m256i _mm256_lddqu_si256 (__m256i const * mem_addr)
+ /// VLDDQU ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ulong> LoadDquVector256(ulong* address) => LoadDquVector256(address);
+
+ /// <summary>
+ /// __m128 _mm_maskload_ps (float const * mem_addr, __m128i mask)
+ /// VMASKMOVPS xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<float> MaskLoad(float* address, Vector128<float> mask) => MaskLoad(address, mask);
+ /// <summary>
+ /// __m128d _mm_maskload_pd (double const * mem_addr, __m128i mask)
+ /// VMASKMOVPD xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<double> MaskLoad(double* address, Vector128<double> mask) => MaskLoad(address, mask);
+
+ /// <summary>
+ /// __m256 _mm256_maskload_ps (float const * mem_addr, __m256i mask)
+ /// VMASKMOVPS ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<float> MaskLoad(float* address, Vector256<float> mask) => MaskLoad(address, mask);
+ /// <summary>
+ /// __m256d _mm256_maskload_pd (double const * mem_addr, __m256i mask)
+ /// VMASKMOVPD ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<double> MaskLoad(double* address, Vector256<double> mask) => MaskLoad(address, mask);
+
+ /// <summary>
+ /// void _mm_maskstore_ps (float * mem_addr, __m128i mask, __m128 a)
+ /// VMASKMOVPS m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(float* address, Vector128<float> mask, Vector128<float> source) => MaskStore(address, mask, source);
+ /// <summary>
+ /// void _mm_maskstore_pd (double * mem_addr, __m128i mask, __m128d a)
+ /// VMASKMOVPD m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(double* address, Vector128<double> mask, Vector128<double> source) => MaskStore(address, mask, source);
+
+ /// <summary>
+ /// void _mm256_maskstore_ps (float * mem_addr, __m256i mask, __m256 a)
+ /// VMASKMOVPS m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(float* address, Vector256<float> mask, Vector256<float> source) => MaskStore(address, mask, source);
+ /// <summary>
+ /// void _mm256_maskstore_pd (double * mem_addr, __m256i mask, __m256d a)
+ /// VMASKMOVPD m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(double* address, Vector256<double> mask, Vector256<double> source) => MaskStore(address, mask, source);
+
+ /// <summary>
+ /// __m256 _mm256_max_ps (__m256 a, __m256 b)
+ /// VMAXPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Max(Vector256<float> left, Vector256<float> right) => Max(left, right);
+ /// <summary>
+ /// __m256d _mm256_max_pd (__m256d a, __m256d b)
+ /// VMAXPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Max(Vector256<double> left, Vector256<double> right) => Max(left, right);
+
+ /// <summary>
+ /// __m256 _mm256_min_ps (__m256 a, __m256 b)
+ /// VMINPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Min(Vector256<float> left, Vector256<float> right) => Min(left, right);
+ /// <summary>
+ /// __m256d _mm256_min_pd (__m256d a, __m256d b)
+ /// VMINPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Min(Vector256<double> left, Vector256<double> right) => Min(left, right);
+
+ /// <summary>
+ /// int _mm256_movemask_ps (__m256 a)
+ /// VMOVMSKPS reg, ymm
+ /// </summary>
+ public static int MoveMask(Vector256<float> value) => MoveMask(value);
+ /// <summary>
+ /// int _mm256_movemask_pd (__m256d a)
+ /// VMOVMSKPD reg, ymm
+ /// </summary>
+ public static int MoveMask(Vector256<double> value) => MoveMask(value);
+
+ /// <summary>
+ /// __m256 _mm256_mul_ps (__m256 a, __m256 b)
+ /// VMULPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Multiply(Vector256<float> left, Vector256<float> right) => Multiply(left, right);
+ /// <summary>
+ /// __m256d _mm256_mul_pd (__m256d a, __m256d b)
+ /// VMULPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Multiply(Vector256<double> left, Vector256<double> right) => Multiply(left, right);
+
+ /// <summary>
+ /// __m256 _mm256_or_ps (__m256 a, __m256 b)
+ /// VORPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Or(Vector256<float> left, Vector256<float> right) => Or(left, right);
+ /// <summary>
+ /// __m256d _mm256_or_pd (__m256d a, __m256d b)
+ /// VORPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Or(Vector256<double> left, Vector256<double> right) => Or(left, right);
+
+ /// <summary>
+ /// __m128 _mm_permute_ps (__m128 a, int imm8)
+ /// VPERMILPS xmm, xmm, imm8
+ /// </summary>
+ public static Vector128<float> Permute(Vector128<float> value, byte control) => Permute(value, control);
+ /// <summary>
+ /// __m128d _mm_permute_pd (__m128d a, int imm8)
+ /// VPERMILPD xmm, xmm, imm8
+ /// </summary>
+ public static Vector128<double> Permute(Vector128<double> value, byte control) => Permute(value, control);
+
+ /// <summary>
+ /// __m256 _mm256_permute_ps (__m256 a, int imm8)
+ /// VPERMILPS ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<float> Permute(Vector256<float> value, byte control) => Permute(value, control);
+ /// <summary>
+ /// __m256d _mm256_permute_pd (__m256d a, int imm8)
+ /// VPERMILPD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<double> Permute(Vector256<double> value, byte control) => Permute(value, control);
+
+ /// <summary>
+ /// __m256 _mm256_permute2f128_ps (__m256 a, __m256 b, int imm8)
+ /// VPERM2F128 ymm, ymm, ymm/m256, imm8
+ /// __m256d _mm256_permute2f128_pd (__m256d a, __m256d b, int imm8)
+ /// VPERM2F128 ymm, ymm, ymm/m256, imm8
+ /// __m256i _mm256_permute2f128_si256 (__m256i a, __m256i b, int imm8)
+ /// VPERM2F128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<T> Permute2x128<T>(Vector256<T> left, Vector256<T> right, byte control) where T : struct
+ {
+ return Permute2x128<T>(left, right, control);
+ }
+
+ /// <summary>
+ /// __m128 _mm_permutevar_ps (__m128 a, __m128i b)
+ /// VPERMILPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> PermuteVar(Vector128<float> left, Vector128<int> control) => PermuteVar(left, control);
+ /// <summary>
+ /// __m128d _mm_permutevar_pd (__m128d a, __m128i b)
+ /// VPERMILPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> PermuteVar(Vector128<double> left, Vector128<long> control) => PermuteVar(left, control);
+ /// <summary>
+ /// __m256 _mm256_permutevar_ps (__m256 a, __m256i b)
+ /// VPERMILPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> PermuteVar(Vector256<float> left, Vector256<int> control) => PermuteVar(left, control);
+ /// <summary>
+ /// __m256d _mm256_permutevar_pd (__m256d a, __m256i b)
+ /// VPERMILPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> PermuteVar(Vector256<double> left, Vector256<long> control) => PermuteVar(left, control);
+
+ /// <summary>
+ /// __m256 _mm256_rcp_ps (__m256 a)
+ /// VRCPPS ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Reciprocal(Vector256<float> value) => Reciprocal(value);
+
+ /// <summary>
+ /// __m256 _mm256_rsqrt_ps (__m256 a)
+ /// VRSQRTPS ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> ReciprocalSqrt(Vector256<float> value) => ReciprocalSqrt(value);
+
+ /// <summary>
+ /// __m256 _mm256_round_ps (__m256 a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)
+ /// VROUNDPS ymm, ymm/m256, imm8(8)
+ /// </summary>
+ public static Vector256<float> RoundToNearestInteger(Vector256<float> value) => RoundToNearestInteger(value);
+ /// <summary>
+ /// __m256 _mm256_round_ps (__m256 a, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC)
+ /// VROUNDPS ymm, ymm/m256, imm8(9)
+ /// </summary>
+ public static Vector256<float> RoundToNegativeInfinity(Vector256<float> value) => RoundToNegativeInfinity(value);
+ /// <summary>
+ /// __m256 _mm256_round_ps (__m256 a, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC)
+ /// VROUNDPS ymm, ymm/m256, imm8(10)
+ /// </summary>
+ public static Vector256<float> RoundToPositiveInfinity(Vector256<float> value) => RoundToPositiveInfinity(value);
+ /// <summary>
+ /// __m256 _mm256_round_ps (__m256 a, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC)
+ /// VROUNDPS ymm, ymm/m256, imm8(11)
+ /// </summary>
+ public static Vector256<float> RoundToZero(Vector256<float> value) => RoundToZero(value);
+ /// <summary>
+ /// __m256 _mm256_round_ps (__m256 a, _MM_FROUND_CUR_DIRECTION)
+ /// VROUNDPS ymm, ymm/m256, imm8(4)
+ /// </summary>
+ public static Vector256<float> RoundCurrentDirection(Vector256<float> value) => RoundCurrentDirection(value);
+
+ /// <summary>
+ /// __m256d _mm256_round_pd (__m256d a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)
+ /// VROUNDPD ymm, ymm/m256, imm8(8)
+ /// </summary>
+ public static Vector256<double> RoundToNearestInteger(Vector256<double> value) => RoundToNearestInteger(value);
+ /// <summary>
+ /// __m256d _mm256_round_pd (__m256d a, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC)
+ /// VROUNDPD ymm, ymm/m256, imm8(9)
+ /// </summary>
+ public static Vector256<double> RoundToNegativeInfinity(Vector256<double> value) => RoundToNegativeInfinity(value);
+ /// <summary>
+ /// __m256d _mm256_round_pd (__m256d a, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC)
+ /// VROUNDPD ymm, ymm/m256, imm8(10)
+ /// </summary>
+ public static Vector256<double> RoundToPositiveInfinity(Vector256<double> value) => RoundToPositiveInfinity(value);
+ /// <summary>
+ /// __m256d _mm256_round_pd (__m256d a, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC)
+ /// VROUNDPD ymm, ymm/m256, imm8(11)
+ /// </summary>
+ public static Vector256<double> RoundToZero(Vector256<double> value) => RoundToZero(value);
+ /// <summary>
+ /// __m256d _mm256_round_pd (__m256d a, _MM_FROUND_CUR_DIRECTION)
+ /// VROUNDPD ymm, ymm/m256, imm8(4)
+ /// </summary>
+ public static Vector256<double> RoundCurrentDirection(Vector256<double> value) => RoundCurrentDirection(value);
+
+ /// <summary>
+ /// __m256i _mm256_set_epi8 (char e31, char e30, char e29, char e28, char e27, char e26, char e25, char e24, char e23, char e22, char e21, char e20, char e19, char e18, char e17, char e16, char e15, char e14, char e13, char e12, char e11, char e10, char e9, char e8, char e7, char e6, char e5, char e4, char e3, char e2, char e1, char e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<sbyte> SetVector256(sbyte e31, sbyte e30, sbyte e29, sbyte e28, sbyte e27, sbyte e26, sbyte e25, sbyte e24, sbyte e23, sbyte e22, sbyte e21, sbyte e20, sbyte e19, sbyte e18, sbyte e17, sbyte e16, sbyte e15, sbyte e14, sbyte e13, sbyte e12, sbyte e11, sbyte e10, sbyte e9, sbyte e8, sbyte e7, sbyte e6, sbyte e5, sbyte e4, sbyte e3, sbyte e2, sbyte e1, sbyte e0) => SetVector256(e31, e30, e29, e28, e27, e26, e25, e24, e23, e22, e21, e20, e19, e18, e17, e16, e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0);
+ /// <summary>
+ /// __m256i _mm256_set_epi8 (char e31, char e30, char e29, char e28, char e27, char e26, char e25, char e24, char e23, char e22, char e21, char e20, char e19, char e18, char e17, char e16, char e15, char e14, char e13, char e12, char e11, char e10, char e9, char e8, char e7, char e6, char e5, char e4, char e3, char e2, char e1, char e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<byte> SetVector256(byte e31, byte e30, byte e29, byte e28, byte e27, byte e26, byte e25, byte e24, byte e23, byte e22, byte e21, byte e20, byte e19, byte e18, byte e17, byte e16, byte e15, byte e14, byte e13, byte e12, byte e11, byte e10, byte e9, byte e8, byte e7, byte e6, byte e5, byte e4, byte e3, byte e2, byte e1, byte e0) => SetVector256(e31, e30, e29, e28, e27, e26, e25, e24, e23, e22, e21, e20, e19, e18, e17, e16, e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0);
+ /// <summary>
+ /// __m256i _mm256_set_epi16 (short e15, short e14, short e13, short e12, short e11, short e10, short e9, short e8, short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<short> SetVector256(short e15, short e14, short e13, short e12, short e11, short e10, short e9, short e8, short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0) => SetVector256(e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0);
+ /// <summary>
+ /// __m256i _mm256_set_epi16 (short e15, short e14, short e13, short e12, short e11, short e10, short e9, short e8, short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<ushort> SetVector256(ushort e15, ushort e14, ushort e13, ushort e12, ushort e11, ushort e10, ushort e9, ushort e8, ushort e7, ushort e6, ushort e5, ushort e4, ushort e3, ushort e2, ushort e1, ushort e0) => SetVector256(e15, e14, e13, e12, e11, e10, e9, e8, e7, e6, e5, e4, e3, e2, e1, e0);
+ /// <summary>
+ /// __m256i _mm256_set_epi32 (int e7, int e6, int e5, int e4, int e3, int e2, int e1, int e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<int> SetVector256(int e7, int e6, int e5, int e4, int e3, int e2, int e1, int e0) => SetVector256(e7, e6, e5, e4, e3, e2, e1, e0);
+ /// <summary>
+ /// __m256i _mm256_set_epi32 (int e7, int e6, int e5, int e4, int e3, int e2, int e1, int e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<uint> SetVector256(uint e7, uint e6, uint e5, uint e4, uint e3, uint e2, uint e1, uint e0) => SetVector256(e7, e6, e5, e4, e3, e2, e1, e0);
+ /// <summary>
+ /// __m256i _mm256_set_epi64x (__int64 e3, __int64 e2, __int64 e1, __int64 e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<long> SetVector256(long e3, long e2, long e1, long e0) => SetVector256(e3, e2, e1, e0);
+ /// <summary>
+ /// __m256i _mm256_set_epi64x (__int64 e3, __int64 e2, __int64 e1, __int64 e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<ulong> SetVector256(ulong e3, ulong e2, ulong e1, ulong e0) => SetVector256(e3, e2, e1, e0);
+ /// <summary>
+ /// __m256 _mm256_set_ps (float e7, float e6, float e5, float e4, float e3, float e2, float e1, float e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<float> SetVector256(float e7, float e6, float e5, float e4, float e3, float e2, float e1, float e0) => SetVector256(e7, e6, e5, e4, e3, e2, e1, e0);
+ /// <summary>
+ /// __m256d _mm256_set_pd (double e3, double e2, double e1, double e0)
+ /// HELPER
+ /// </summary>
+ public static Vector256<double> SetVector256(double e3, double e2, double e1, double e0) => SetVector256(e3, e2, e1, e0);
+
+ /// <summary>
+ /// __m256i _mm256_set1_epi8 (char a)
+ /// HELPER
+ /// __m256i _mm256_set1_epi16 (short a)
+ /// HELPER
+ /// __m256i _mm256_set1_epi32 (int a)
+ /// HELPER
+ /// __m256i _mm256_set1_epi64x (long long a)
+ /// HELPER
+ /// __m256 _mm256_set1_ps (float a)
+ /// HELPER
+ /// __m256d _mm256_set1_pd (double a)
+ /// HELPER
+ /// </summary>
+ public static Vector256<T> SetAllVector256<T>(T value) where T : struct
+ {
+ return SetAllVector256<T>(value);
+ }
+
+ /// <summary>
+ /// __m256 _mm256_set_m128 (__m128 hi, __m128 lo)
+ /// HELPER
+ /// __m256d _mm256_set_m128d (__m128d hi, __m128d lo)
+ /// HELPER
+ /// __m256i _mm256_set_m128i (__m128i hi, __m128i lo)
+ /// HELPER
+ /// </summary>
+ public static Vector256<T> SetHighLow<T>(Vector128<T> hi, Vector128<T> lo) where T : struct
+ {
+ return SetHighLow<T>(hi, lo);
+ }
+
+ /// <summary>
+ /// __m256i _mm256_setzero_si256 (void)
+ /// HELPER
+ /// __m256 _mm256_setzero_ps (void)
+ /// HELPER
+ /// __m256d _mm256_setzero_pd (void)
+ /// HELPER
+ /// </summary>
+ public static Vector256<T> SetZeroVector256<T>() where T : struct
+ {
+ return SetZeroVector256<T>();
+ }
+
+ /// <summary>
+ /// __m256 _mm256_shuffle_ps (__m256 a, __m256 b, const int imm8)
+ /// VSHUFPS ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<float> Shuffle(Vector256<float> value, Vector256<float> right, byte control) => Shuffle(value, right, control);
+ /// <summary>
+ /// __m256d _mm256_shuffle_pd (__m256d a, __m256d b, const int imm8)
+ /// VSHUFPD ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<double> Shuffle(Vector256<double> value, Vector256<double> right, byte control) => Shuffle(value, right, control);
+
+ /// <summary>
+ /// __m256 _mm256_sqrt_ps (__m256 a)
+ /// VSQRTPS ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Sqrt(Vector256<float> value) => Sqrt(value);
+ /// <summary>
+ /// __m256d _mm256_sqrt_pd (__m256d a)
+ /// VSQRTPD ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Sqrt(Vector256<double> value) => Sqrt(value);
+
+ /// <summary>
+ /// __m256 _mm256_castpd_ps (__m256d a)
+ /// HELPER - No Codegen
+ /// __m256i _mm256_castpd_si256 (__m256d a)
+ /// HELPER - No Codegen
+ /// __m256d _mm256_castps_pd (__m256 a)
+ /// HELPER - No Codegen
+ /// __m256i _mm256_castps_si256 (__m256 a)
+ /// HELPER - No Codegen
+ /// __m256d _mm256_castsi256_pd (__m256i a)
+ /// HELPER - No Codegen
+ /// __m256 _mm256_castsi256_ps (__m256i a)
+ /// HELPER - No Codegen
+ /// </summary>
+ public static Vector256<U> StaticCast<T, U>(Vector256<T> value) where T : struct where U : struct
+ {
+ return StaticCast<T, U>(value);
+ }
+
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(sbyte* address, Vector256<sbyte> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(byte* address, Vector256<byte> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(short* address, Vector256<short> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(ushort* address, Vector256<ushort> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(int* address, Vector256<int> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(uint* address, Vector256<uint> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(long* address, Vector256<long> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm256_store_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQA m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(ulong* address, Vector256<ulong> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm256_store_ps (float * mem_addr, __m256 a)
+ /// VMOVAPS m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(float* address, Vector256<float> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm256_store_pd (double * mem_addr, __m256d a)
+ /// VMOVAPD m256, ymm
+ /// </summary>
+ public static unsafe void StoreAligned(double* address, Vector256<double> source) => StoreAligned(address, source);
+
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(sbyte* address, Vector256<sbyte> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(byte* address, Vector256<byte> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(short* address, Vector256<short> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(ushort* address, Vector256<ushort> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(int* address, Vector256<int> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(uint* address, Vector256<uint> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(long* address, Vector256<long> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm256_stream_si256 (__m256i * mem_addr, __m256i a)
+ /// VMOVNTDQ m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(ulong* address, Vector256<ulong> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm256_stream_ps (float * mem_addr, __m256 a)
+ /// MOVNTPS m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(float* address, Vector256<float> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm256_stream_pd (double * mem_addr, __m256d a)
+ /// MOVNTPD m256, ymm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(double* address, Vector256<double> source) => StoreAlignedNonTemporal(address, source);
+
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(sbyte* address, Vector256<sbyte> source) => Store(address, source);
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(byte* address, Vector256<byte> source) => Store(address, source);
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(short* address, Vector256<short> source) => Store(address, source);
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(ushort* address, Vector256<ushort> source) => Store(address, source);
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(int* address, Vector256<int> source) => Store(address, source);
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(uint* address, Vector256<uint> source) => Store(address, source);
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(long* address, Vector256<long> source) => Store(address, source);
+ /// <summary>
+ /// void _mm256_storeu_si256 (__m256i * mem_addr, __m256i a)
+ /// MOVDQU m256, ymm
+ /// </summary>
+ public static unsafe void Store(ulong* address, Vector256<ulong> source) => Store(address, source);
+ /// <summary>
+ /// void _mm256_storeu_ps (float * mem_addr, __m256 a)
+ /// MOVUPS m256, ymm
+ /// </summary>
+ public static unsafe void Store(float* address, Vector256<float> source) => Store(address, source);
+ /// <summary>
+ /// void _mm256_storeu_pd (double * mem_addr, __m256d a)
+ /// MOVUPD m256, ymm
+ /// </summary>
+ public static unsafe void Store(double* address, Vector256<double> source) => Store(address, source);
+
+ /// <summary>
+ /// __m256 _mm256_sub_ps (__m256 a, __m256 b)
+ /// VSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Subtract(Vector256<float> left, Vector256<float> right) => Subtract(left, right);
+ /// <summary>
+ /// __m256d _mm256_sub_pd (__m256d a, __m256d b)
+ /// VSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Subtract(Vector256<double> left, Vector256<double> right) => Subtract(left, right);
+
+ /// <summary>
+ /// int _mm_testc_ps (__m128 a, __m128 b)
+ /// VTESTPS xmm, xmm/m128
+ /// </summary>
+ public static bool TestC(Vector128<float> left, Vector128<float> right) => TestC(left, right);
+ /// <summary>
+ /// int _mm_testc_pd (__m128d a, __m128d b)
+ /// VTESTPD xmm, xmm/m128
+ /// </summary>
+ public static bool TestC(Vector128<double> left, Vector128<double> right) => TestC(left, right);
+
+ /// <summary>
+ /// int _mm256_testc_si256 (__m256i a, __m256i b)
+ /// VPTEST ymm, ymm/m256
+ /// int _mm256_testc_ps (__m256 a, __m256 b)
+ /// VTESTPS ymm, ymm/m256
+ /// int _mm256_testc_pd (__m256d a, __m256d b)
+ /// VTESTPS ymm, ymm/m256
+ /// </summary>
+ public static bool TestC<T>(Vector256<T> left, Vector256<T> right) where T : struct
+ {
+ return TestC<T>(left, right);
+ }
+
+ /// <summary>
+ /// int _mm_testnzc_ps (__m128 a, __m128 b)
+ /// VTESTPS xmm, xmm/m128
+ /// </summary>
+ public static bool TestNotZAndNotC(Vector128<float> left, Vector128<float> right) => TestNotZAndNotC(left, right);
+ /// <summary>
+ /// int _mm_testnzc_pd (__m128d a, __m128d b)
+ /// VTESTPD xmm, xmm/m128
+ /// </summary>
+ public static bool TestNotZAndNotC(Vector128<double> left, Vector128<double> right) => TestNotZAndNotC(left, right);
+
+ /// <summary>
+ /// int _mm256_testnzc_si256 (__m256i a, __m256i b)
+ /// VPTEST ymm, ymm/m256
+ /// int _mm256_testnzc_ps (__m256 a, __m256 b)
+ /// VTESTPS ymm, ymm/m256
+ /// int _mm256_testnzc_pd (__m256d a, __m256d b)
+ /// VTESTPD ymm, ymm/m256
+ /// </summary>
+ public static bool TestNotZAndNotC<T>(Vector256<T> left, Vector256<T> right) where T : struct
+ {
+ return TestNotZAndNotC<T>(left, right);
+ }
+
+ /// <summary>
+ /// int _mm_testz_ps (__m128 a, __m128 b)
+ /// VTESTPS xmm, xmm/m128
+ /// </summary>
+ public static bool TestZ(Vector128<float> left, Vector128<float> right) => TestZ(left, right);
+ /// <summary>
+ /// int _mm_testz_pd (__m128d a, __m128d b)
+ /// VTESTPD xmm, xmm/m128
+ /// </summary>
+ public static bool TestZ(Vector128<double> left, Vector128<double> right) => TestZ(left, right);
+
+ /// <summary>
+ /// int _mm256_testz_si256 (__m256i a, __m256i b)
+ /// VPTEST ymm, ymm/m256
+ /// int _mm256_testz_ps (__m256 a, __m256 b)
+ /// VTESTPS ymm, ymm/m256
+ /// int _mm256_testz_pd (__m256d a, __m256d b)
+ /// VTESTPD ymm, ymm/m256
+ /// </summary>
+ public static bool TestZ<T>(Vector256<T> left, Vector256<T> right) where T : struct
+ {
+ return TestZ<T>(left, right);
+ }
+
+ /// <summary>
+ /// __m256 _mm256_unpackhi_ps (__m256 a, __m256 b)
+ /// VUNPCKHPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> UnpackHigh(Vector256<float> left, Vector256<float> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m256d _mm256_unpackhi_pd (__m256d a, __m256d b)
+ /// VUNPCKHPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> UnpackHigh(Vector256<double> left, Vector256<double> right) => UnpackHigh(left, right);
+
+ /// <summary>
+ /// __m256 _mm256_unpacklo_ps (__m256 a, __m256 b)
+ /// VUNPCKLPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> UnpackLow(Vector256<float> left, Vector256<float> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m256d _mm256_unpacklo_pd (__m256d a, __m256d b)
+ /// VUNPCKLPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> UnpackLow(Vector256<double> left, Vector256<double> right) => UnpackLow(left, right);
+
+ /// <summary>
+ /// __m256 _mm256_xor_ps (__m256 a, __m256 b)
+ /// VXORPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> Xor(Vector256<float> left, Vector256<float> right) => Xor(left, right);
+ /// <summary>
+ /// __m256d _mm256_xor_pd (__m256d a, __m256d b)
+ /// VXORPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> Xor(Vector256<double> left, Vector256<double> right) => Xor(left, right);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs
new file mode 100644
index 000000000..79c30d37a
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.PlatformNotSupported.cs
@@ -0,0 +1,1915 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel AVX2 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Avx2 : Avx
+ {
+ internal Avx2() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// __m256i _mm256_abs_epi8 (__m256i a)
+ /// VPABSB ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Abs(Vector256<sbyte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_abs_epi16 (__m256i a)
+ /// VPABSW ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Abs(Vector256<short> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_abs_epi32 (__m256i a)
+ /// VPABSD ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Abs(Vector256<int> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_add_epi8 (__m256i a, __m256i b)
+ /// VPADDB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Add(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_add_epi8 (__m256i a, __m256i b)
+ /// VPADDB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Add(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_add_epi16 (__m256i a, __m256i b)
+ /// VPADDW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Add(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_add_epi16 (__m256i a, __m256i b)
+ /// VPADDW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Add(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_add_epi32 (__m256i a, __m256i b)
+ /// VPADDD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Add(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_add_epi32 (__m256i a, __m256i b)
+ /// VPADDD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Add(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_add_epi64 (__m256i a, __m256i b)
+ /// VPADDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> Add(Vector256<long> left, Vector256<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_add_epi64 (__m256i a, __m256i b)
+ /// VPADDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> Add(Vector256<ulong> left, Vector256<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_adds_epi8 (__m256i a, __m256i b)
+ /// VPADDSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> AddSaturate(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_adds_epu8 (__m256i a, __m256i b)
+ /// VPADDUSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> AddSaturate(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_adds_epi16 (__m256i a, __m256i b)
+ /// VPADDSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> AddSaturate(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_adds_epu16 (__m256i a, __m256i b)
+ /// VPADDUSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> AddSaturate(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_alignr_epi8 (__m256i a, __m256i b, const int count)
+ /// VPALIGNR ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<sbyte> AlignRight(Vector256<sbyte> left, Vector256<sbyte> right, byte mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> And(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> And(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> And(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> And(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> And(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> And(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> And(Vector256<long> left, Vector256<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> And(Vector256<ulong> left, Vector256<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> AndNot(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> AndNot(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> AndNot(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> AndNot(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> AndNot(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> AndNot(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> AndNot(Vector256<long> left, Vector256<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> AndNot(Vector256<ulong> left, Vector256<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_avg_epu8 (__m256i a, __m256i b)
+ /// VPAVGB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Average(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_avg_epu16 (__m256i a, __m256i b)
+ /// VPAVGW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Average(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_blend_epi32 (__m128i a, __m128i b, const int imm8)
+ /// VPBLENDD xmm, xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<int> Blend(Vector128<int> left, Vector128<int> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_blend_epi32 (__m128i a, __m128i b, const int imm8)
+ /// VPBLENDD xmm, xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<uint> Blend(Vector128<uint> left, Vector128<uint> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_blend_epi16 (__m256i a, __m256i b, const int imm8)
+ /// VPBLENDW ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<short> Blend(Vector256<short> left, Vector256<short> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_blend_epi16 (__m256i a, __m256i b, const int imm8)
+ /// VPBLENDW ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ushort> Blend(Vector256<ushort> left, Vector256<ushort> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_blend_epi32 (__m256i a, __m256i b, const int imm8)
+ /// VPBLENDD ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<int> Blend(Vector256<int> left, Vector256<int> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_blend_epi32 (__m256i a, __m256i b, const int imm8)
+ /// VPBLENDD ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<uint> Blend(Vector256<uint> left, Vector256<uint> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_blendv_epi8 (__m256i a, __m256i b, __m256i mask)
+ /// PBLENDVB ymm, ymm, ymm/m256, ymm
+ /// </summary>
+ public static Vector256<sbyte> BlendVariable(Vector256<sbyte> left, Vector256<sbyte> right, Vector256<sbyte> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_blendv_epi8 (__m256i a, __m256i b, __m256i mask)
+ /// PBLENDVB ymm, ymm, ymm/m256, ymm
+ /// </summary>
+ public static Vector256<byte> BlendVariable(Vector256<byte> left, Vector256<byte> right, Vector256<byte> mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_broadcastb_epi8 (__m128i a)
+ /// VPBROADCASTB xmm, xmm
+ /// __m128i _mm_broadcastw_epi16 (__m128i a)
+ /// VPBROADCASTW xmm, xmm
+ /// __m128i _mm_broadcastd_epi32 (__m128i a)
+ /// VPBROADCASTD xmm, xmm
+ /// __m128i _mm_broadcastq_epi64 (__m128i a)
+ /// VPBROADCASTQ xmm, xmm
+ /// __m128 _mm_broadcastss_ps (__m128 a)
+ /// VBROADCASTSS xmm, xmm
+ /// __m128d _mm_broadcastsd_pd (__m128d a)
+ /// VMOVDDUP xmm, xmm
+ /// </summary>
+ public static Vector128<T> BroadcastScalarToVector128<T>(Vector128<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_broadcastb_epi8 (__m128i a)
+ /// VPBROADCASTB ymm, xmm
+ /// __m256i _mm256_broadcastw_epi16 (__m128i a)
+ /// VPBROADCASTW ymm, xmm
+ /// __m256i _mm256_broadcastd_epi32 (__m128i a)
+ /// VPBROADCASTD ymm, xmm
+ /// __m256i _mm256_broadcastq_epi64 (__m128i a)
+ /// VPBROADCASTQ ymm, xmm
+ /// __m256 _mm256_broadcastss_ps (__m128 a)
+ /// VBROADCASTSS ymm, xmm
+ /// __m256d _mm256_broadcastsd_pd (__m128d a)
+ /// VBROADCASTSD ymm, xmm
+ /// </summary>
+ public static Vector256<T> BroadcastScalarToVector256<T>(Vector128<T> value) where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m8
+ /// </summary>
+ public static unsafe Vector256<sbyte> BroadcastVector128ToVector256(sbyte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m8
+ /// </summary>
+ public static unsafe Vector256<byte> BroadcastVector128ToVector256(byte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m16
+ /// </summary>
+ public static unsafe Vector256<short> BroadcastVector128ToVector256(short* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m16
+ /// </summary>
+ public static unsafe Vector256<ushort> BroadcastVector128ToVector256(ushort* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m32
+ /// </summary>
+ public static unsafe Vector256<int> BroadcastVector128ToVector256(int* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m32
+ /// </summary>
+ public static unsafe Vector256<uint> BroadcastVector128ToVector256(uint* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m64
+ /// </summary>
+ public static unsafe Vector256<long> BroadcastVector128ToVector256(long* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m64
+ /// </summary>
+ public static unsafe Vector256<ulong> BroadcastVector128ToVector256(ulong* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi8 (__m256i a, __m256i b)
+ /// VPCMPEQB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> CompareEqual(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi8 (__m256i a, __m256i b)
+ /// VPCMPEQB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> CompareEqual(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi16 (__m256i a, __m256i b)
+ /// VPCMPEQW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> CompareEqual(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi16 (__m256i a, __m256i b)
+ /// VPCMPEQW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> CompareEqual(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi32 (__m256i a, __m256i b)
+ /// VPCMPEQD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> CompareEqual(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi32 (__m256i a, __m256i b)
+ /// VPCMPEQD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> CompareEqual(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi64 (__m256i a, __m256i b)
+ /// VPCMPEQQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> CompareEqual(Vector256<long> left, Vector256<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi64 (__m256i a, __m256i b)
+ /// VPCMPEQQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> CompareEqual(Vector256<ulong> left, Vector256<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_cmpgt_epi8 (__m256i a, __m256i b)
+ /// VPCMPGTB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> CompareGreaterThan(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cmpgt_epi16 (__m256i a, __m256i b)
+ /// VPCMPGTW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> CompareGreaterThan(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cmpgt_epi32 (__m256i a, __m256i b)
+ /// VPCMPGTD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> CompareGreaterThan(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cmpgt_epi64 (__m256i a, __m256i b)
+ /// VPCMPGTQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> CompareGreaterThan(Vector256<long> left, Vector256<long> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// double _mm256_cvtsd_f64 (__m256d a)
+ /// HELPER: MOVSD
+ /// </summary>
+ public static double ConvertToDouble(Vector256<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm256_cvtsi256_si32 (__m256i a)
+ /// MOVD reg/m32, xmm
+ /// </summary>
+ public static int ConvertToInt32(Vector256<int> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm256_cvtsi256_si32 (__m256i a)
+ /// MOVD reg/m32, xmm
+ /// </summary>
+ public static uint ConvertToUInt32(Vector256<uint> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_cvtepi8_epi16 (__m128i a)
+ /// VPMOVSXBW ymm, xmm/m128
+ /// </summary>
+ public static Vector256<short> ConvertToVector256Int16(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepu8_epi16 (__m128i a)
+ /// VPMOVZXBW ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ushort> ConvertToVector256UInt16(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepi8_epi32 (__m128i a)
+ /// VPMOVSXBD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<int> ConvertToVector256Int32(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepi16_epi32 (__m128i a)
+ /// VPMOVSXWD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<int> ConvertToVector256Int32(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepu8_epi32 (__m128i a)
+ /// VPMOVZXBD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<uint> ConvertToVector256UInt32(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepu16_epi32 (__m128i a)
+ /// VPMOVZXWD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<uint> ConvertToVector256UInt32(Vector128<ushort> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepi8_epi64 (__m128i a)
+ /// VPMOVSXBQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<long> ConvertToVector256Int64(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepi16_epi64 (__m128i a)
+ /// VPMOVSXWQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<long> ConvertToVector256Int64(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepi32_epi64 (__m128i a)
+ /// VPMOVSXDQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<long> ConvertToVector256Int64(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepu8_epi64 (__m128i a)
+ /// VPMOVZXBQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ulong> ConvertToVector256UInt64(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepu16_epi64 (__m128i a)
+ /// VPMOVZXWQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ulong> ConvertToVector256UInt64(Vector128<ushort> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_cvtepu32_epi64 (__m128i a)
+ /// VPMOVZXDQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ulong> ConvertToVector256UInt64(Vector128<uint> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<sbyte> ExtractVector128(Vector256<sbyte> value, byte index) { throw new PlatformNotSupportedException(); }
+ // <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(sbyte* address, Vector256<sbyte> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<byte> ExtractVector128(Vector256<byte> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(byte* address, Vector256<byte> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<short> ExtractVector128(Vector256<short> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(short* address, Vector256<short> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<ushort> ExtractVector128(Vector256<ushort> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(ushort* address, Vector256<ushort> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<int> ExtractVector128(Vector256<int> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(int* address, Vector256<int> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<uint> ExtractVector128(Vector256<uint> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(uint* address, Vector256<uint> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<long> ExtractVector128(Vector256<long> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(long* address, Vector256<long> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<ulong> ExtractVector128(Vector256<ulong> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(ulong* address, Vector256<ulong> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_i32gather_epi32 (int const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherVector128(int* baseAddress, Vector128<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_i32gather_epi32 (int const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherVector128(uint* baseAddress, Vector128<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_i32gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDQ xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<long> GatherVector128(long* baseAddress, Vector128<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_i32gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDQ xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<ulong> GatherVector128(ulong* baseAddress, Vector128<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_i32gather_ps (float const* base_addr, __m128i vindex, const int scale)
+ /// VGATHERDPS xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherVector128(float* baseAddress, Vector128<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_i32gather_pd (double const* base_addr, __m128i vindex, const int scale)
+ /// VGATHERDPD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<double> GatherVector128(double* baseAddress, Vector128<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_i64gather_epi32 (int const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERQD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherVector128(int* baseAddress, Vector128<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_i64gather_epi32 (int const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERQD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherVector128(uint* baseAddress, Vector128<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_i64gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERQQ xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<long> GatherVector128(long* baseAddress, Vector128<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_i64gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERQQ xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<ulong> GatherVector128(ulong* baseAddress, Vector128<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_i64gather_ps (float const* base_addr, __m128i vindex, const int scale)
+ /// VGATHERQPS xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherVector128(float* baseAddress, Vector128<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_i64gather_pd (double const* base_addr, __m128i vindex, const int scale)
+ /// VGATHERQPD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<double> GatherVector128(double* baseAddress, Vector128<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_i32gather_epi32 (int const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERDD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<int> GatherVector256(int* baseAddress, Vector256<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_i32gather_epi32 (int const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERDD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<uint> GatherVector256(uint* baseAddress, Vector256<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_i32gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<long> GatherVector256(long* baseAddress, Vector128<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_i32gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<ulong> GatherVector256(ulong* baseAddress, Vector128<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_i32gather_ps (float const* base_addr, __m256i vindex, const int scale)
+ /// VGATHERDPS ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<float> GatherVector256(float* baseAddress, Vector256<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_i32gather_pd (double const* base_addr, __m128i vindex, const int scale)
+ /// VGATHERDPD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<double> GatherVector256(double* baseAddress, Vector128<int> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_i64gather_epi32 (int const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERQD xmm, vm64y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherVector128(int* baseAddress, Vector256<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_i64gather_epi32 (int const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERQD xmm, vm64y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherVector128(uint* baseAddress, Vector256<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_i64gather_epi64 (__int64 const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERQQ ymm, vm64y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<long> GatherVector256(long* baseAddress, Vector256<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_i64gather_epi64 (__int64 const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERQQ ymm, vm64y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<ulong> GatherVector256(ulong* baseAddress, Vector256<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm256_i64gather_ps (float const* base_addr, __m256i vindex, const int scale)
+ /// VGATHERQPS xmm, vm64y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherVector128(float* baseAddress, Vector256<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_i64gather_pd (double const* base_addr, __m256i vindex, const int scale)
+ /// VGATHERQPD ymm, vm64y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<double> GatherVector256(double* baseAddress, Vector256<long> index, byte scale) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_mask_i32gather_epi32 (__m128i src, int const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERDD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherMaskVector128(Vector128<int> source, int* baseAddress, Vector128<int> index, Vector128<int> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_mask_i32gather_epi32 (__m128i src, int const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERDD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherMaskVector128(Vector128<uint> source, uint* baseAddress, Vector128<int> index, Vector128<uint> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_mask_i32gather_epi64 (__m128i src, __int64 const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERDQ xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<long> GatherMaskVector128(Vector128<long> source, long* baseAddress, Vector128<int> index, Vector128<long> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_mask_i32gather_epi64 (__m128i src, __int64 const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERDQ xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<ulong> GatherMaskVector128(Vector128<ulong> source, ulong* baseAddress, Vector128<int> index, Vector128<ulong> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_mask_i32gather_ps (__m128 src, float const* base_addr, __m128i vindex, __m128 mask, const int scale)
+ /// VGATHERDPS xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherMaskVector128(Vector128<float> source, float* baseAddress, Vector128<int> index, Vector128<float> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_mask_i32gather_pd (__m128d src, double const* base_addr, __m128i vindex, __m128d mask, const int scale)
+ /// VGATHERDPD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<double> GatherMaskVector128(Vector128<double> source, double* baseAddress, Vector128<int> index, Vector128<double> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_mask_i64gather_epi32 (__m128i src, int const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERQD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherMaskVector128(Vector128<int> source, int* baseAddress, Vector128<long> index, Vector128<int> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_mask_i64gather_epi32 (__m128i src, int const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERQD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherMaskVector128(Vector128<uint> source, uint* baseAddress, Vector128<long> index, Vector128<uint> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_mask_i64gather_epi64 (__m128i src, __int64 const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERQQ xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<long> GatherMaskVector128(Vector128<long> source, long* baseAddress, Vector128<long> index, Vector128<long> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_mask_i64gather_epi64 (__m128i src, __int64 const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERQQ xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<ulong> GatherMaskVector128(Vector128<ulong> source, ulong* baseAddress, Vector128<long> index, Vector128<ulong> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_mask_i64gather_ps (__m128 src, float const* base_addr, __m128i vindex, __m128 mask, const int scale)
+ /// VGATHERQPS xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherMaskVector128(Vector128<float> source, float* baseAddress, Vector128<long> index, Vector128<float> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_mask_i64gather_pd (__m128d src, double const* base_addr, __m128i vindex, __m128d mask, const int scale)
+ /// VGATHERQPD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<double> GatherMaskVector128(Vector128<double> source, double* baseAddress, Vector128<long> index, Vector128<double> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_mask_i32gather_epi32 (__m256i src, int const* base_addr, __m256i vindex, __m256i mask, const int scale)
+ /// VPGATHERDD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<int> GatherMaskVector256(Vector256<int> source, int* baseAddress, Vector256<int> index, Vector256<int> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_mask_i32gather_epi32 (__m256i src, int const* base_addr, __m256i vindex, __m256i mask, const int scale)
+ /// VPGATHERDD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<uint> GatherMaskVector256(Vector256<uint> source, uint* baseAddress, Vector256<int> index, Vector256<uint> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_mask_i32gather_epi64 (__m256i src, __int64 const* base_addr, __m128i vindex, __m256i mask, const int scale)
+ /// VPGATHERDQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<long> GatherMaskVector256(Vector256<long> source, long* baseAddress, Vector128<int> index, Vector256<long> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_mask_i32gather_epi64 (__m256i src, __int64 const* base_addr, __m128i vindex, __m256i mask, const int scale)
+ /// VPGATHERDQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<ulong> GatherMaskVector256(Vector256<ulong> source, ulong* baseAddress, Vector128<int> index, Vector256<ulong> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_mask_i32gather_ps (__m256 src, float const* base_addr, __m256i vindex, __m256 mask, const int scale)
+ /// VPGATHERDPS ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<float> GatherMaskVector256(Vector256<float> source, float* baseAddress, Vector256<int> index, Vector256<float> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_mask_i32gather_pd (__m256d src, double const* base_addr, __m128i vindex, __m256d mask, const int scale)
+ /// VPGATHERDPD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<double> GatherMaskVector256(Vector256<double> source, double* baseAddress, Vector128<int> index, Vector256<double> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_mask_i64gather_epi32 (__m128i src, int const* base_addr, __m256i vindex, __m128i mask, const int scale)
+ /// VPGATHERQD xmm, vm32y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherMaskVector128(Vector128<int> source, int* baseAddress, Vector256<long> index, Vector128<int> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm256_mask_i64gather_epi32 (__m128i src, int const* base_addr, __m256i vindex, __m128i mask, const int scale)
+ /// VPGATHERQD xmm, vm32y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherMaskVector128(Vector128<uint> source, uint* baseAddress, Vector256<long> index, Vector128<uint> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_mask_i64gather_epi64 (__m256i src, __int64 const* base_addr, __m256i vindex, __m256i mask, const int scale)
+ /// VPGATHERQQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<long> GatherMaskVector256(Vector256<long> source, long* baseAddress, Vector256<long> index, Vector256<long> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_mask_i64gather_epi64 (__m256i src, __int64 const* base_addr, __m256i vindex, __m256i mask, const int scale)
+ /// VPGATHERQQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<ulong> GatherMaskVector256(Vector256<ulong> source, ulong* baseAddress, Vector256<long> index, Vector256<ulong> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm256_mask_i64gather_ps (__m128 src, float const* base_addr, __m256i vindex, __m128 mask, const int scale)
+ /// VGATHERQPS xmm, vm32y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherMaskVector128(Vector128<float> source, float* baseAddress, Vector256<long> index, Vector128<float> mask, byte scale) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_mask_i64gather_pd (__m256d src, double const* base_addr, __m256i vindex, __m256d mask, const int scale)
+ /// VGATHERQPD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<double> GatherMaskVector256(Vector256<double> source, double* baseAddress, Vector256<long> index, Vector256<double> mask, byte scale) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_hadd_epi16 (__m256i a, __m256i b)
+ /// VPHADDW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> HorizontalAdd(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_hadd_epi32 (__m256i a, __m256i b)
+ /// VPHADDD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> HorizontalAdd(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_hadds_epi16 (__m256i a, __m256i b)
+ /// VPHADDSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> HorizontalAddSaturate(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_hsub_epi16 (__m256i a, __m256i b)
+ /// VPHSUBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> HorizontalSubtract(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_hsub_epi32 (__m256i a, __m256i b)
+ /// VPHSUBD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> HorizontalSubtract(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_hsubs_epi16 (__m256i a, __m256i b)
+ /// VPHSUBSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> HorizontalSubtractSaturate(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<sbyte> InsertVector128(Vector256<sbyte> value, Vector128<sbyte> data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xm128, imm8
+ /// </summary>
+ public new static unsafe Vector256<sbyte> InsertVector128(Vector256<sbyte> value, sbyte* address, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<byte> InsertVector128(Vector256<byte> value, Vector128<byte> data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<byte> InsertVector128(Vector256<byte> value, byte* address, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<short> InsertVector128(Vector256<short> value, Vector128<short> data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<short> InsertVector128(Vector256<short> value, short* address, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<ushort> InsertVector128(Vector256<ushort> value, Vector128<ushort> data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<ushort> InsertVector128(Vector256<ushort> value, ushort* address, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<int> InsertVector128(Vector256<int> value, Vector128<int> data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<int> InsertVector128(Vector256<int> value, int* address, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<uint> InsertVector128(Vector256<uint> value, Vector128<uint> data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<uint> InsertVector128(Vector256<uint> value, uint* address, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<long> InsertVector128(Vector256<long> value, Vector128<long> data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<long> InsertVector128(Vector256<long> value, long* address, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<ulong> InsertVector128(Vector256<ulong> value, Vector128<ulong> data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<ulong> InsertVector128(Vector256<ulong> value, ulong* address, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<sbyte> LoadAlignedVector256NonTemporal(sbyte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<byte> LoadAlignedVector256NonTemporal(byte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<short> LoadAlignedVector256NonTemporal(short* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ushort> LoadAlignedVector256NonTemporal(ushort* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<int> LoadAlignedVector256NonTemporal(int* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<uint> LoadAlignedVector256NonTemporal(uint* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<long> LoadAlignedVector256NonTemporal(long* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ulong> LoadAlignedVector256NonTemporal(ulong* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_maskload_epi32 (int const* mem_addr, __m128i mask)
+ /// VPMASKMOVD xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<int> MaskLoad(int* address, Vector128<int> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_maskload_epi32 (int const* mem_addr, __m128i mask)
+ /// VPMASKMOVD xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<uint> MaskLoad(uint* address, Vector128<uint> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_maskload_epi64 (__int64 const* mem_addr, __m128i mask)
+ /// VPMASKMOVQ xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<long> MaskLoad(long* address, Vector128<long> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_maskload_epi64 (__int64 const* mem_addr, __m128i mask)
+ /// VPMASKMOVQ xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ulong> MaskLoad(ulong* address, Vector128<ulong> mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_maskload_epi32 (int const* mem_addr, __m256i mask)
+ /// VPMASKMOVD ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<int> MaskLoad(int* address, Vector256<int> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_maskload_epi32 (int const* mem_addr, __m256i mask)
+ /// VPMASKMOVD ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<uint> MaskLoad(uint* address, Vector256<uint> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_maskload_epi64 (__int64 const* mem_addr, __m256i mask)
+ /// VPMASKMOVQ ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<long> MaskLoad(long* address, Vector256<long> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_maskload_epi64 (__int64 const* mem_addr, __m256i mask)
+ /// VPMASKMOVQ ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ulong> MaskLoad(ulong* address, Vector256<ulong> mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_maskstore_epi32 (int* mem_addr, __m128i mask, __m128i a)
+ /// VPMASKMOVD m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(int* address, Vector128<int> mask, Vector128<int> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_maskstore_epi32 (int* mem_addr, __m128i mask, __m128i a)
+ /// VPMASKMOVD m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(uint* address, Vector128<uint> mask, Vector128<uint> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_maskstore_epi64 (__int64* mem_addr, __m128i mask, __m128i a)
+ /// VPMASKMOVQ m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(long* address, Vector128<long> mask, Vector128<long> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_maskstore_epi64 (__int64* mem_addr, __m128i mask, __m128i a)
+ /// VPMASKMOVQ m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(ulong* address, Vector128<ulong> mask, Vector128<ulong> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm256_maskstore_epi32 (int* mem_addr, __m256i mask, __m256i a)
+ /// VPMASKMOVD m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(int* address, Vector256<int> mask, Vector256<int> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_maskstore_epi32 (int* mem_addr, __m256i mask, __m256i a)
+ /// VPMASKMOVD m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(uint* address, Vector256<uint> mask, Vector256<uint> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_maskstore_epi64 (__int64* mem_addr, __m256i mask, __m256i a)
+ /// VPMASKMOVQ m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(long* address, Vector256<long> mask, Vector256<long> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm256_maskstore_epi64 (__int64* mem_addr, __m256i mask, __m256i a)
+ /// VPMASKMOVQ m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(ulong* address, Vector256<ulong> mask, Vector256<ulong> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_madd_epi16 (__m256i a, __m256i b)
+ /// VPMADDWD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> MultiplyAddAdjacent(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_maddubs_epi16 (__m256i a, __m256i b)
+ /// VPMADDUBSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> MultiplyAddAdjacent(Vector256<byte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_max_epi8 (__m256i a, __m256i b)
+ /// VPMAXSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Max(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_max_epu8 (__m256i a, __m256i b)
+ /// VPMAXUB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Max(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_max_epi16 (__m256i a, __m256i b)
+ /// VPMAXSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Max(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_max_epu16 (__m256i a, __m256i b)
+ /// VPMAXUW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Max(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_max_epi32 (__m256i a, __m256i b)
+ /// VPMAXSD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Max(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_max_epu32 (__m256i a, __m256i b)
+ /// VPMAXUD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Max(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_min_epi8 (__m256i a, __m256i b)
+ /// VPMINSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Min(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_min_epu8 (__m256i a, __m256i b)
+ /// VPMINUB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Min(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_min_epi16 (__m256i a, __m256i b)
+ /// VPMINSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Min(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_min_epu16 (__m256i a, __m256i b)
+ /// VPMINUW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Min(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_min_epi32 (__m256i a, __m256i b)
+ /// VPMINSD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Min(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_min_epu32 (__m256i a, __m256i b)
+ /// VPMINUD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Min(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm256_movemask_epi8 (__m256i a)
+ /// VPMOVMSKB reg, ymm
+ /// </summary>
+ public static int MoveMask(Vector256<sbyte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm256_movemask_epi8 (__m256i a)
+ /// VPMOVMSKB reg, ymm
+ /// </summary>
+ public static int MoveMask(Vector256<byte> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_mpsadbw_epu8 (__m256i a, __m256i b, const int imm8)
+ /// VMPSADBW ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ushort> MultipleSumAbsoluteDifferences(Vector256<byte> left, Vector256<byte> right, byte mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_mul_epi32 (__m256i a, __m256i b)
+ /// VPMULDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> Multiply(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_mul_epu32 (__m256i a, __m256i b)
+ /// VPMULUDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> Multiply(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_mulhi_epi16 (__m256i a, __m256i b)
+ /// VPMULHW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> MultiplyHigh(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_mulhi_epu16 (__m256i a, __m256i b)
+ /// VPMULHUW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> MultiplyHigh(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_mulhrs_epi16 (__m256i a, __m256i b)
+ /// VPMULHRSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> MultiplyHighRoundScale(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_mullo_epi16 (__m256i a, __m256i b)
+ /// VPMULLW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> MultiplyLow(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_mullo_epi32 (__m256i a, __m256i b)
+ /// VPMULLD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> MultiplyLow(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Or(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Or(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Or(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Or(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Or(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Or(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> Or(Vector256<long> left, Vector256<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> Or(Vector256<ulong> left, Vector256<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_packs_epi16 (__m256i a, __m256i b)
+ /// VPACKSSWB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> PackSignedSaturate(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_packs_epi32 (__m256i a, __m256i b)
+ /// VPACKSSDW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> PackSignedSaturate(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_packus_epi16 (__m256i a, __m256i b)
+ /// VPACKUSWB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> PackUnsignedSaturate(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_packus_epi32 (__m256i a, __m256i b)
+ /// VPACKUSDW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> PackUnsignedSaturate(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<sbyte> Permute2x128(Vector256<sbyte> left, Vector256<sbyte> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<byte> Permute2x128(Vector256<byte> left, Vector256<byte> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<short> Permute2x128(Vector256<short> left, Vector256<short> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ushort> Permute2x128(Vector256<ushort> left, Vector256<ushort> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<int> Permute2x128(Vector256<int> left, Vector256<int> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<uint> Permute2x128(Vector256<uint> left, Vector256<uint> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<long> Permute2x128(Vector256<long> left, Vector256<long> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ulong> Permute2x128(Vector256<ulong> left, Vector256<ulong> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_permute4x64_epi64 (__m256i a, const int imm8)
+ /// VPERMQ ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<long> Permute4x64(Vector256<long> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_permute4x64_epi64 (__m256i a, const int imm8)
+ /// VPERMQ ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ulong> Permute4x64(Vector256<ulong> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_permute4x64_pd (__m256d a, const int imm8)
+ /// VPERMPD ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<double> Permute4x64(Vector256<double> value, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_permutevar8x32_epi32 (__m256i a, __m256i idx)
+ /// VPERMD ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<int> PermuteVar8x32(Vector256<int> left, Vector256<int> control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_permutevar8x32_epi32 (__m256i a, __m256i idx)
+ /// VPERMD ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<uint> PermuteVar8x32(Vector256<uint> left, Vector256<uint> control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_permutevar8x32_ps (__m256 a, __m256i idx)
+ /// VPERMPS ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<float> PermuteVar8x32(Vector256<float> left, Vector256<int> control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_sll_epi16 (__m256i a, __m128i count)
+ /// VPSLLW ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<short> ShiftLeftLogical(Vector256<short> value, Vector128<short> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sll_epi16 (__m256i a, __m128i count)
+ /// VPSLLW ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ushort> ShiftLeftLogical(Vector256<ushort> value, Vector128<ushort> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sll_epi32 (__m256i a, __m128i count)
+ /// VPSLLD ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<int> ShiftLeftLogical(Vector256<int> value, Vector128<int> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sll_epi32 (__m256i a, __m128i count)
+ /// VPSLLD ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<uint> ShiftLeftLogical(Vector256<uint> value, Vector128<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sll_epi64 (__m256i a, __m128i count)
+ /// VPSLLQ ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<long> ShiftLeftLogical(Vector256<long> value, Vector128<long> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sll_epi64 (__m256i a, __m128i count)
+ /// VPSLLQ ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ulong> ShiftLeftLogical(Vector256<ulong> value, Vector128<ulong> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_slli_epi16 (__m256i a, int imm8)
+ /// VPSLLW ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<short> ShiftLeftLogical(Vector256<short> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_slli_epi16 (__m256i a, int imm8)
+ /// VPSLLW ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ushort> ShiftLeftLogical(Vector256<ushort> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_slli_epi32 (__m256i a, int imm8)
+ /// VPSLLD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<int> ShiftLeftLogical(Vector256<int> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_slli_epi32 (__m256i a, int imm8)
+ /// VPSLLD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<uint> ShiftLeftLogical(Vector256<uint> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_slli_epi64 (__m256i a, int imm8)
+ /// VPSLLQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<long> ShiftLeftLogical(Vector256<long> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_slli_epi64 (__m256i a, int imm8)
+ /// VPSLLQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ulong> ShiftLeftLogical(Vector256<ulong> value, byte count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<sbyte> ShiftLeftLogical128BitLane(Vector256<sbyte> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<byte> ShiftLeftLogical128BitLane(Vector256<byte> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<short> ShiftLeftLogical128BitLane(Vector256<short> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ushort> ShiftLeftLogical128BitLane(Vector256<ushort> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<int> ShiftLeftLogical128BitLane(Vector256<int> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<uint> ShiftLeftLogical128BitLane(Vector256<uint> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<long> ShiftLeftLogical128BitLane(Vector256<long> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ulong> ShiftLeftLogical128BitLane(Vector256<ulong> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_sllv_epi32 (__m256i a, __m256i count)
+ /// VPSLLVD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> ShiftLeftLogicalVariable(Vector256<int> value, Vector256<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sllv_epi32 (__m256i a, __m256i count)
+ /// VPSLLVD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> ShiftLeftLogicalVariable(Vector256<uint> value, Vector256<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sllv_epi64 (__m256i a, __m256i count)
+ /// VPSLLVQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> ShiftLeftLogicalVariable(Vector256<long> value, Vector256<ulong> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sllv_epi64 (__m256i a, __m256i count)
+ /// VPSLLVQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> ShiftLeftLogicalVariable(Vector256<ulong> value, Vector256<ulong> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_sllv_epi32 (__m128i a, __m128i count)
+ /// VPSLLVD xmm, ymm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftLeftLogicalVariable(Vector128<int> value, Vector128<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sllv_epi32 (__m128i a, __m128i count)
+ /// VPSLLVD xmm, ymm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> ShiftLeftLogicalVariable(Vector128<uint> value, Vector128<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sllv_epi64 (__m128i a, __m128i count)
+ /// VPSLLVQ xmm, ymm, xmm/m128
+ /// </summary>
+ public static Vector128<long> ShiftLeftLogicalVariable(Vector128<long> value, Vector128<ulong> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sllv_epi64 (__m128i a, __m128i count)
+ /// VPSLLVQ xmm, ymm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> ShiftLeftLogicalVariable(Vector128<ulong> value, Vector128<ulong> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// _mm256_sra_epi16 (__m256i a, __m128i count)
+ /// VPSRAW ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<short> ShiftRightArithmetic(Vector256<short> value, Vector128<short> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// _mm256_sra_epi32 (__m256i a, __m128i count)
+ /// VPSRAD ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<int> ShiftRightArithmetic(Vector256<int> value, Vector128<int> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_srai_epi16 (__m256i a, int imm8)
+ /// VPSRAW ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<short> ShiftRightArithmetic(Vector256<short> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srai_epi32 (__m256i a, int imm8)
+ /// VPSRAD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<int> ShiftRightArithmetic(Vector256<int> value, byte count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_srav_epi32 (__m256i a, __m256i count)
+ /// VPSRAVD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> ShiftRightArithmeticVariable(Vector256<int> value, Vector256<uint> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_srav_epi32 (__m128i a, __m128i count)
+ /// VPSRAVD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftRightArithmeticVariable(Vector128<int> value, Vector128<uint> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_srl_epi16 (__m256i a, __m128i count)
+ /// VPSRLW ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<short> ShiftRightLogical(Vector256<short> value, Vector128<short> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srl_epi16 (__m256i a, __m128i count)
+ /// VPSRLW ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ushort> ShiftRightLogical(Vector256<ushort> value, Vector128<ushort> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srl_epi32 (__m256i a, __m128i count)
+ /// VPSRLD ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<int> ShiftRightLogical(Vector256<int> value, Vector128<int> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srl_epi32 (__m256i a, __m128i count)
+ /// VPSRLD ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<uint> ShiftRightLogical(Vector256<uint> value, Vector128<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srl_epi64 (__m256i a, __m128i count)
+ /// VPSRLQ ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<long> ShiftRightLogical(Vector256<long> value, Vector128<long> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srl_epi64 (__m256i a, __m128i count)
+ /// VPSRLQ ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ulong> ShiftRightLogical(Vector256<ulong> value, Vector128<ulong> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_srli_epi16 (__m256i a, int imm8)
+ /// VPSRLW ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<short> ShiftRightLogical(Vector256<short> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srli_epi16 (__m256i a, int imm8)
+ /// VPSRLW ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ushort> ShiftRightLogical(Vector256<ushort> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srli_epi32 (__m256i a, int imm8)
+ /// VPSRLD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<int> ShiftRightLogical(Vector256<int> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srli_epi32 (__m256i a, int imm8)
+ /// VPSRLD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<uint> ShiftRightLogical(Vector256<uint> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srli_epi64 (__m256i a, int imm8)
+ /// VPSRLQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<long> ShiftRightLogical(Vector256<long> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srli_epi64 (__m256i a, int imm8)
+ /// VPSRLQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ulong> ShiftRightLogical(Vector256<ulong> value, byte count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<sbyte> ShiftRightLogical128BitLane(Vector256<sbyte> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<byte> ShiftRightLogical128BitLane(Vector256<byte> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<short> ShiftRightLogical128BitLane(Vector256<short> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ushort> ShiftRightLogical128BitLane(Vector256<ushort> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<int> ShiftRightLogical128BitLane(Vector256<int> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<uint> ShiftRightLogical128BitLane(Vector256<uint> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<long> ShiftRightLogical128BitLane(Vector256<long> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ulong> ShiftRightLogical128BitLane(Vector256<ulong> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_srlv_epi32 (__m256i a, __m256i count)
+ /// VPSRLVD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> ShiftRightLogicalVariable(Vector256<int> value, Vector256<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srlv_epi32 (__m256i a, __m256i count)
+ /// VPSRLVD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> ShiftRightLogicalVariable(Vector256<uint> value, Vector256<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srlv_epi64 (__m256i a, __m256i count)
+ /// VPSRLVQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> ShiftRightLogicalVariable(Vector256<long> value, Vector256<ulong> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_srlv_epi64 (__m256i a, __m256i count)
+ /// VPSRLVQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> ShiftRightLogicalVariable(Vector256<ulong> value, Vector256<ulong> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_srlv_epi32 (__m128i a, __m128i count)
+ /// VPSRLVD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftRightLogicalVariable(Vector128<int> value, Vector128<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srlv_epi32 (__m128i a, __m128i count)
+ /// VPSRLVD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> ShiftRightLogicalVariable(Vector128<uint> value, Vector128<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srlv_epi64 (__m128i a, __m128i count)
+ /// VPSRLVQ xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> ShiftRightLogicalVariable(Vector128<long> value, Vector128<ulong> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srlv_epi64 (__m128i a, __m128i count)
+ /// VPSRLVQ xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> ShiftRightLogicalVariable(Vector128<ulong> value, Vector128<ulong> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_shuffle_epi8 (__m256i a, __m256i b)
+ /// VPSHUFB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Shuffle(Vector256<sbyte> value, Vector256<sbyte> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_shuffle_epi8 (__m256i a, __m256i b)
+ /// VPSHUFB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Shuffle(Vector256<byte> value, Vector256<byte> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_shuffle_epi32 (__m256i a, const int imm8)
+ /// VPSHUFD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Shuffle(Vector256<int> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_shuffle_epi32 (__m256i a, const int imm8)
+ /// VPSHUFD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Shuffle(Vector256<uint> value, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_shufflehi_epi16 (__m256i a, const int imm8)
+ /// VPSHUFHW ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<short> ShuffleHigh(Vector256<short> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_shufflehi_epi16 (__m256i a, const int imm8)
+ /// VPSHUFHW ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ushort> ShuffleHigh(Vector256<ushort> value, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_shufflelo_epi16 (__m256i a, const int imm8)
+ /// VPSHUFLW ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<short> ShuffleLow(Vector256<short> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_shufflelo_epi16 (__m256i a, const int imm8)
+ /// VPSHUFLW ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ushort> ShuffleLow(Vector256<ushort> value, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_sign_epi8 (__m256i a, __m256i b)
+ /// VPSIGNB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Sign(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sign_epi16 (__m256i a, __m256i b)
+ /// VPSIGNW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Sign(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sign_epi32 (__m256i a, __m256i b)
+ /// VPSIGND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Sign(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_sub_epi8 (__m256i a, __m256i b)
+ /// VPSUBB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Subtract(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sub_epi8 (__m256i a, __m256i b)
+ /// VPSUBB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Subtract(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sub_epi16 (__m256i a, __m256i b)
+ /// VPSUBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Subtract(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sub_epi16 (__m256i a, __m256i b)
+ /// VPSUBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Subtract(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sub_epi32 (__m256i a, __m256i b)
+ /// VPSUBD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Subtract(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sub_epi32 (__m256i a, __m256i b)
+ /// VPSUBD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Subtract(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sub_epi64 (__m256i a, __m256i b)
+ /// VPSUBQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> Subtract(Vector256<long> left, Vector256<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_sub_epi64 (__m256i a, __m256i b)
+ /// VPSUBQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> Subtract(Vector256<ulong> left, Vector256<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_subs_epi8 (__m256i a, __m256i b)
+ /// VPSUBSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> SubtractSaturate(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_subs_epi16 (__m256i a, __m256i b)
+ /// VPSUBSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> SubtractSaturate(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_subs_epu8 (__m256i a, __m256i b)
+ /// VPSUBUSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> SubtractSaturate(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_subs_epu16 (__m256i a, __m256i b)
+ /// VPSUBUSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> SubtractSaturate(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_sad_epu8 (__m256i a, __m256i b)
+ /// VPSADBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> SumAbsoluteDifferences(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi8 (__m256i a, __m256i b)
+ /// VPUNPCKHBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> UnpackHigh(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi8 (__m256i a, __m256i b)
+ /// VPUNPCKHBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> UnpackHigh(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi16 (__m256i a, __m256i b)
+ /// VPUNPCKHWD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> UnpackHigh(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi16 (__m256i a, __m256i b)
+ /// VPUNPCKHWD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> UnpackHigh(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi32 (__m256i a, __m256i b)
+ /// VPUNPCKHDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> UnpackHigh(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi32 (__m256i a, __m256i b)
+ /// VPUNPCKHDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> UnpackHigh(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi64 (__m256i a, __m256i b)
+ /// VPUNPCKHQDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> UnpackHigh(Vector256<long> left, Vector256<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi64 (__m256i a, __m256i b)
+ /// VPUNPCKHQDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> UnpackHigh(Vector256<ulong> left, Vector256<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi8 (__m256i a, __m256i b)
+ /// VPUNPCKLBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> UnpackLow(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi8 (__m256i a, __m256i b)
+ /// VPUNPCKLBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> UnpackLow(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi16 (__m256i a, __m256i b)
+ /// VPUNPCKLWD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> UnpackLow(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi16 (__m256i a, __m256i b)
+ /// VPUNPCKLWD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> UnpackLow(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi32 (__m256i a, __m256i b)
+ /// VPUNPCKLDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> UnpackLow(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi32 (__m256i a, __m256i b)
+ /// VPUNPCKLDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> UnpackLow(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi64 (__m256i a, __m256i b)
+ /// VPUNPCKLQDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> UnpackLow(Vector256<long> left, Vector256<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi64 (__m256i a, __m256i b)
+ /// VPUNPCKLQDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> UnpackLow(Vector256<ulong> left, Vector256<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Xor(Vector256<sbyte> left, Vector256<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Xor(Vector256<byte> left, Vector256<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Xor(Vector256<short> left, Vector256<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Xor(Vector256<ushort> left, Vector256<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Xor(Vector256<int> left, Vector256<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Xor(Vector256<uint> left, Vector256<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> Xor(Vector256<long> left, Vector256<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> Xor(Vector256<ulong> left, Vector256<ulong> right) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.cs
new file mode 100644
index 000000000..90c5b315b
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Avx2.cs
@@ -0,0 +1,2641 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel AVX2 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Avx2 : Avx
+ {
+ internal Avx2() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// __m256i _mm256_abs_epi8 (__m256i a)
+ /// VPABSB ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Abs(Vector256<sbyte> value) => Abs(value);
+ /// <summary>
+ /// __m256i _mm256_abs_epi16 (__m256i a)
+ /// VPABSW ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Abs(Vector256<short> value) => Abs(value);
+ /// <summary>
+ /// __m256i _mm256_abs_epi32 (__m256i a)
+ /// VPABSD ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Abs(Vector256<int> value) => Abs(value);
+
+ /// <summary>
+ /// __m256i _mm256_add_epi8 (__m256i a, __m256i b)
+ /// VPADDB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Add(Vector256<sbyte> left, Vector256<sbyte> right) => Add(left, right);
+ /// <summary>
+ /// __m256i _mm256_add_epi8 (__m256i a, __m256i b)
+ /// VPADDB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Add(Vector256<byte> left, Vector256<byte> right) => Add(left, right);
+ /// <summary>
+ /// __m256i _mm256_add_epi16 (__m256i a, __m256i b)
+ /// VPADDW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Add(Vector256<short> left, Vector256<short> right) => Add(left, right);
+ /// <summary>
+ /// __m256i _mm256_add_epi16 (__m256i a, __m256i b)
+ /// VPADDW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Add(Vector256<ushort> left, Vector256<ushort> right) => Add(left, right);
+ /// <summary>
+ /// __m256i _mm256_add_epi32 (__m256i a, __m256i b)
+ /// VPADDD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Add(Vector256<int> left, Vector256<int> right) => Add(left, right);
+ /// <summary>
+ /// __m256i _mm256_add_epi32 (__m256i a, __m256i b)
+ /// VPADDD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Add(Vector256<uint> left, Vector256<uint> right) => Add(left, right);
+ /// <summary>
+ /// __m256i _mm256_add_epi64 (__m256i a, __m256i b)
+ /// VPADDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> Add(Vector256<long> left, Vector256<long> right) => Add(left, right);
+ /// <summary>
+ /// __m256i _mm256_add_epi64 (__m256i a, __m256i b)
+ /// VPADDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> Add(Vector256<ulong> left, Vector256<ulong> right) => Add(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_adds_epi8 (__m256i a, __m256i b)
+ /// VPADDSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> AddSaturate(Vector256<sbyte> left, Vector256<sbyte> right) => AddSaturate(left, right);
+ /// <summary>
+ /// __m256i _mm256_adds_epu8 (__m256i a, __m256i b)
+ /// VPADDUSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> AddSaturate(Vector256<byte> left, Vector256<byte> right) => AddSaturate(left, right);
+ /// <summary>
+ /// __m256i _mm256_adds_epi16 (__m256i a, __m256i b)
+ /// VPADDSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> AddSaturate(Vector256<short> left, Vector256<short> right) => AddSaturate(left, right);
+ /// <summary>
+ /// __m256i _mm256_adds_epu16 (__m256i a, __m256i b)
+ /// VPADDUSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> AddSaturate(Vector256<ushort> left, Vector256<ushort> right) => AddSaturate(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_alignr_epi8 (__m256i a, __m256i b, const int count)
+ /// VPALIGNR ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<sbyte> AlignRight(Vector256<sbyte> left, Vector256<sbyte> right, byte mask) => AlignRight(left, right, mask);
+
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> And(Vector256<sbyte> left, Vector256<sbyte> right) => And(left, right);
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> And(Vector256<byte> left, Vector256<byte> right) => And(left, right);
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> And(Vector256<short> left, Vector256<short> right) => And(left, right);
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> And(Vector256<ushort> left, Vector256<ushort> right) => And(left, right);
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> And(Vector256<int> left, Vector256<int> right) => And(left, right);
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> And(Vector256<uint> left, Vector256<uint> right) => And(left, right);
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> And(Vector256<long> left, Vector256<long> right) => And(left, right);
+ /// <summary>
+ /// __m256i _mm256_and_si256 (__m256i a, __m256i b)
+ /// VPAND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> And(Vector256<ulong> left, Vector256<ulong> right) => And(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> AndNot(Vector256<sbyte> left, Vector256<sbyte> right) => AndNot(left, right);
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> AndNot(Vector256<byte> left, Vector256<byte> right) => AndNot(left, right);
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> AndNot(Vector256<short> left, Vector256<short> right) => AndNot(left, right);
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> AndNot(Vector256<ushort> left, Vector256<ushort> right) => AndNot(left, right);
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> AndNot(Vector256<int> left, Vector256<int> right) => AndNot(left, right);
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> AndNot(Vector256<uint> left, Vector256<uint> right) => AndNot(left, right);
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> AndNot(Vector256<long> left, Vector256<long> right) => AndNot(left, right);
+ /// <summary>
+ /// __m256i _mm256_andnot_si256 (__m256i a, __m256i b)
+ /// VPANDN ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> AndNot(Vector256<ulong> left, Vector256<ulong> right) => AndNot(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_avg_epu8 (__m256i a, __m256i b)
+ /// VPAVGB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Average(Vector256<byte> left, Vector256<byte> right) => Average(left, right);
+ /// <summary>
+ /// __m256i _mm256_avg_epu16 (__m256i a, __m256i b)
+ /// VPAVGW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Average(Vector256<ushort> left, Vector256<ushort> right) => Average(left, right);
+
+ /// <summary>
+ /// __m128i _mm_blend_epi32 (__m128i a, __m128i b, const int imm8)
+ /// VPBLENDD xmm, xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<int> Blend(Vector128<int> left, Vector128<int> right, byte control) => Blend(left, right, control);
+ /// <summary>
+ /// __m128i _mm_blend_epi32 (__m128i a, __m128i b, const int imm8)
+ /// VPBLENDD xmm, xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<uint> Blend(Vector128<uint> left, Vector128<uint> right, byte control) => Blend(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_blend_epi16 (__m256i a, __m256i b, const int imm8)
+ /// VPBLENDW ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<short> Blend(Vector256<short> left, Vector256<short> right, byte control) => Blend(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_blend_epi16 (__m256i a, __m256i b, const int imm8)
+ /// VPBLENDW ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ushort> Blend(Vector256<ushort> left, Vector256<ushort> right, byte control) => Blend(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_blend_epi32 (__m256i a, __m256i b, const int imm8)
+ /// VPBLENDD ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<int> Blend(Vector256<int> left, Vector256<int> right, byte control) => Blend(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_blend_epi32 (__m256i a, __m256i b, const int imm8)
+ /// VPBLENDD ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<uint> Blend(Vector256<uint> left, Vector256<uint> right, byte control) => Blend(left, right, control);
+
+ /// <summary>
+ /// __m256i _mm256_blendv_epi8 (__m256i a, __m256i b, __m256i mask)
+ /// PBLENDVB ymm, ymm, ymm/m256, ymm
+ /// </summary>
+ public static Vector256<sbyte> BlendVariable(Vector256<sbyte> left, Vector256<sbyte> right, Vector256<sbyte> mask) => BlendVariable(left, right, mask);
+ /// <summary>
+ /// __m256i _mm256_blendv_epi8 (__m256i a, __m256i b, __m256i mask)
+ /// PBLENDVB ymm, ymm, ymm/m256, ymm
+ /// </summary>
+ public static Vector256<byte> BlendVariable(Vector256<byte> left, Vector256<byte> right, Vector256<byte> mask) => BlendVariable(left, right, mask);
+
+ /// <summary>
+ /// __m128i _mm_broadcastb_epi8 (__m128i a)
+ /// VPBROADCASTB xmm, xmm
+ /// __m128i _mm_broadcastw_epi16 (__m128i a)
+ /// VPBROADCASTW xmm, xmm
+ /// __m128i _mm_broadcastd_epi32 (__m128i a)
+ /// VPBROADCASTD xmm, xmm
+ /// __m128i _mm_broadcastq_epi64 (__m128i a)
+ /// VPBROADCASTQ xmm, xmm
+ /// __m128 _mm_broadcastss_ps (__m128 a)
+ /// VBROADCASTSS xmm, xmm
+ /// __m128d _mm_broadcastsd_pd (__m128d a)
+ /// VMOVDDUP xmm, xmm
+ /// </summary>
+ public static Vector128<T> BroadcastScalarToVector128<T>(Vector128<T> value) where T : struct
+ {
+ return BroadcastScalarToVector128<T>(value);
+ }
+
+ /// <summary>
+ /// __m256i _mm256_broadcastb_epi8 (__m128i a)
+ /// VPBROADCASTB ymm, xmm
+ /// __m256i _mm256_broadcastw_epi16 (__m128i a)
+ /// VPBROADCASTW ymm, xmm
+ /// __m256i _mm256_broadcastd_epi32 (__m128i a)
+ /// VPBROADCASTD ymm, xmm
+ /// __m256i _mm256_broadcastq_epi64 (__m128i a)
+ /// VPBROADCASTQ ymm, xmm
+ /// __m256 _mm256_broadcastss_ps (__m128 a)
+ /// VBROADCASTSS ymm, xmm
+ /// __m256d _mm256_broadcastsd_pd (__m128d a)
+ /// VBROADCASTSD ymm, xmm
+ /// </summary>
+ public static Vector256<T> BroadcastScalarToVector256<T>(Vector128<T> value) where T : struct
+ {
+ return BroadcastScalarToVector256<T>(value);
+ }
+
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m8
+ /// </summary>
+ public static unsafe Vector256<sbyte> BroadcastVector128ToVector256(sbyte* address) => BroadcastVector128ToVector256(address);
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m8
+ /// </summary>
+ public static unsafe Vector256<byte> BroadcastVector128ToVector256(byte* address) => BroadcastVector128ToVector256(address);
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m16
+ /// </summary>
+ public static unsafe Vector256<short> BroadcastVector128ToVector256(short* address) => BroadcastVector128ToVector256(address);
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m16
+ /// </summary>
+ public static unsafe Vector256<ushort> BroadcastVector128ToVector256(ushort* address) => BroadcastVector128ToVector256(address);
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m32
+ /// </summary>
+ public static unsafe Vector256<int> BroadcastVector128ToVector256(int* address) => BroadcastVector128ToVector256(address);
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m32
+ /// </summary>
+ public static unsafe Vector256<uint> BroadcastVector128ToVector256(uint* address) => BroadcastVector128ToVector256(address);
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m64
+ /// </summary>
+ public static unsafe Vector256<long> BroadcastVector128ToVector256(long* address) => BroadcastVector128ToVector256(address);
+ /// <summary>
+ /// __m256i _mm256_broadcastsi128_si256 (__m128i a)
+ /// VBROADCASTI128 xmm, m64
+ /// </summary>
+ public static unsafe Vector256<ulong> BroadcastVector128ToVector256(ulong* address) => BroadcastVector128ToVector256(address);
+
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi8 (__m256i a, __m256i b)
+ /// VPCMPEQB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> CompareEqual(Vector256<sbyte> left, Vector256<sbyte> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi8 (__m256i a, __m256i b)
+ /// VPCMPEQB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> CompareEqual(Vector256<byte> left, Vector256<byte> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi16 (__m256i a, __m256i b)
+ /// VPCMPEQW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> CompareEqual(Vector256<short> left, Vector256<short> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi16 (__m256i a, __m256i b)
+ /// VPCMPEQW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> CompareEqual(Vector256<ushort> left, Vector256<ushort> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi32 (__m256i a, __m256i b)
+ /// VPCMPEQD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> CompareEqual(Vector256<int> left, Vector256<int> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi32 (__m256i a, __m256i b)
+ /// VPCMPEQD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> CompareEqual(Vector256<uint> left, Vector256<uint> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi64 (__m256i a, __m256i b)
+ /// VPCMPEQQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> CompareEqual(Vector256<long> left, Vector256<long> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m256i _mm256_cmpeq_epi64 (__m256i a, __m256i b)
+ /// VPCMPEQQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> CompareEqual(Vector256<ulong> left, Vector256<ulong> right) => CompareEqual(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_cmpgt_epi8 (__m256i a, __m256i b)
+ /// VPCMPGTB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> CompareGreaterThan(Vector256<sbyte> left, Vector256<sbyte> right) => CompareGreaterThan(left, right);
+ /// <summary>
+ /// __m256i _mm256_cmpgt_epi16 (__m256i a, __m256i b)
+ /// VPCMPGTW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> CompareGreaterThan(Vector256<short> left, Vector256<short> right) => CompareGreaterThan(left, right);
+ /// <summary>
+ /// __m256i _mm256_cmpgt_epi32 (__m256i a, __m256i b)
+ /// VPCMPGTD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> CompareGreaterThan(Vector256<int> left, Vector256<int> right) => CompareGreaterThan(left, right);
+ /// <summary>
+ /// __m256i _mm256_cmpgt_epi64 (__m256i a, __m256i b)
+ /// VPCMPGTQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> CompareGreaterThan(Vector256<long> left, Vector256<long> right) => CompareGreaterThan(left, right);
+
+ /// <summary>
+ /// double _mm256_cvtsd_f64 (__m256d a)
+ /// HELPER: MOVSD
+ /// </summary>
+ public static double ConvertToDouble(Vector256<double> value) => ConvertToDouble(value);
+ /// <summary>
+ /// int _mm256_cvtsi256_si32 (__m256i a)
+ /// MOVD reg/m32, xmm
+ /// </summary>
+ public static int ConvertToInt32(Vector256<int> value) => ConvertToInt32(value);
+ /// <summary>
+ /// int _mm256_cvtsi256_si32 (__m256i a)
+ /// MOVD reg/m32, xmm
+ /// </summary>
+ public static uint ConvertToUInt32(Vector256<uint> value) => ConvertToUInt32(value);
+
+ /// <summary>
+ /// __m256i _mm256_cvtepi8_epi16 (__m128i a)
+ /// VPMOVSXBW ymm, xmm/m128
+ /// </summary>
+ public static Vector256<short> ConvertToVector256Int16(Vector128<sbyte> value) => ConvertToVector256Int16(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepu8_epi16 (__m128i a)
+ /// VPMOVZXBW ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ushort> ConvertToVector256UInt16(Vector128<byte> value) => ConvertToVector256UInt16(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepi8_epi32 (__m128i a)
+ /// VPMOVSXBD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<int> ConvertToVector256Int32(Vector128<sbyte> value) => ConvertToVector256Int32(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepi16_epi32 (__m128i a)
+ /// VPMOVSXWD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<int> ConvertToVector256Int32(Vector128<short> value) => ConvertToVector256Int32(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepu8_epi32 (__m128i a)
+ /// VPMOVZXBD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<uint> ConvertToVector256UInt32(Vector128<byte> value) => ConvertToVector256UInt32(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepu16_epi32 (__m128i a)
+ /// VPMOVZXWD ymm, xmm/m128
+ /// </summary>
+ public static Vector256<uint> ConvertToVector256UInt32(Vector128<ushort> value) => ConvertToVector256UInt32(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepi8_epi64 (__m128i a)
+ /// VPMOVSXBQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<long> ConvertToVector256Int64(Vector128<sbyte> value) => ConvertToVector256Int64(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepi16_epi64 (__m128i a)
+ /// VPMOVSXWQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<long> ConvertToVector256Int64(Vector128<short> value) => ConvertToVector256Int64(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepi32_epi64 (__m128i a)
+ /// VPMOVSXDQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<long> ConvertToVector256Int64(Vector128<int> value) => ConvertToVector256Int64(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepu8_epi64 (__m128i a)
+ /// VPMOVZXBQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ulong> ConvertToVector256UInt64(Vector128<byte> value) => ConvertToVector256UInt64(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepu16_epi64 (__m128i a)
+ /// VPMOVZXWQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ulong> ConvertToVector256UInt64(Vector128<ushort> value) => ConvertToVector256UInt64(value);
+ /// <summary>
+ /// __m256i _mm256_cvtepu32_epi64 (__m128i a)
+ /// VPMOVZXDQ ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ulong> ConvertToVector256UInt64(Vector128<uint> value) => ConvertToVector256UInt64(value);
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<sbyte> ExtractVector128(Vector256<sbyte> value, byte index) => ExtractVector128(value, index);
+ // <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(sbyte* address, Vector256<sbyte> value, byte index) => ExtractVector128(address, value, index);
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<byte> ExtractVector128(Vector256<byte> value, byte index) => ExtractVector128(value, index);
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(byte* address, Vector256<byte> value, byte index) => ExtractVector128(address, value, index);
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<short> ExtractVector128(Vector256<short> value, byte index) => ExtractVector128(value, index);
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(short* address, Vector256<short> value, byte index) => ExtractVector128(address, value, index);
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<ushort> ExtractVector128(Vector256<ushort> value, byte index) => ExtractVector128(value, index);
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(ushort* address, Vector256<ushort> value, byte index) => ExtractVector128(address, value, index);
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<int> ExtractVector128(Vector256<int> value, byte index) => ExtractVector128(value, index);
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(int* address, Vector256<int> value, byte index) => ExtractVector128(address, value, index);
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<uint> ExtractVector128(Vector256<uint> value, byte index) => ExtractVector128(value, index);
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(uint* address, Vector256<uint> value, byte index) => ExtractVector128(address, value, index);
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<long> ExtractVector128(Vector256<long> value, byte index) => ExtractVector128(value, index);
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(long* address, Vector256<long> value, byte index) => ExtractVector128(address, value, index);
+
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 xmm, ymm, imm8
+ /// </summary>
+ public static Vector128<ulong> ExtractVector128(Vector256<ulong> value, byte index) => ExtractVector128(value, index);
+ /// <summary>
+ /// __m128i _mm256_extracti128_si256 (__m256i a, const int imm8)
+ /// VEXTRACTI128 m128, ymm, imm8
+ /// </summary>
+ public new static unsafe void ExtractVector128(ulong* address, Vector256<ulong> value, byte index) => ExtractVector128(address, value, index);
+
+ /// <summary>
+ /// __m128i _mm_i32gather_epi32 (int const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherVector128(int* baseAddress, Vector128<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_i32gather_epi32 (int const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherVector128(uint* baseAddress, Vector128<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_i32gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDQ xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<long> GatherVector128(long* baseAddress, Vector128<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_i32gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDQ xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<ulong> GatherVector128(ulong* baseAddress, Vector128<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128 _mm_i32gather_ps (float const* base_addr, __m128i vindex, const int scale)
+ /// VGATHERDPS xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherVector128(float* baseAddress, Vector128<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128d _mm_i32gather_pd (double const* base_addr, __m128i vindex, const int scale)
+ /// VGATHERDPD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<double> GatherVector128(double* baseAddress, Vector128<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_i64gather_epi32 (int const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERQD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherVector128(int* baseAddress, Vector128<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_i64gather_epi32 (int const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERQD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherVector128(uint* baseAddress, Vector128<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_i64gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERQQ xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<long> GatherVector128(long* baseAddress, Vector128<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_i64gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERQQ xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<ulong> GatherVector128(ulong* baseAddress, Vector128<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128 _mm_i64gather_ps (float const* base_addr, __m128i vindex, const int scale)
+ /// VGATHERQPS xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherVector128(float* baseAddress, Vector128<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128d _mm_i64gather_pd (double const* base_addr, __m128i vindex, const int scale)
+ /// VGATHERQPD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<double> GatherVector128(double* baseAddress, Vector128<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_i32gather_epi32 (int const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERDD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<int> GatherVector256(int* baseAddress, Vector256<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector256(baseAddress, index, 1);
+ case 2:
+ return GatherVector256(baseAddress, index, 2);
+ case 4:
+ return GatherVector256(baseAddress, index, 4);
+ case 8:
+ return GatherVector256(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_i32gather_epi32 (int const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERDD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<uint> GatherVector256(uint* baseAddress, Vector256<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector256(baseAddress, index, 1);
+ case 2:
+ return GatherVector256(baseAddress, index, 2);
+ case 4:
+ return GatherVector256(baseAddress, index, 4);
+ case 8:
+ return GatherVector256(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_i32gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<long> GatherVector256(long* baseAddress, Vector128<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector256(baseAddress, index, 1);
+ case 2:
+ return GatherVector256(baseAddress, index, 2);
+ case 4:
+ return GatherVector256(baseAddress, index, 4);
+ case 8:
+ return GatherVector256(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_i32gather_epi64 (__int64 const* base_addr, __m128i vindex, const int scale)
+ /// VPGATHERDQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<ulong> GatherVector256(ulong* baseAddress, Vector128<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector256(baseAddress, index, 1);
+ case 2:
+ return GatherVector256(baseAddress, index, 2);
+ case 4:
+ return GatherVector256(baseAddress, index, 4);
+ case 8:
+ return GatherVector256(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256 _mm256_i32gather_ps (float const* base_addr, __m256i vindex, const int scale)
+ /// VGATHERDPS ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<float> GatherVector256(float* baseAddress, Vector256<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector256(baseAddress, index, 1);
+ case 2:
+ return GatherVector256(baseAddress, index, 2);
+ case 4:
+ return GatherVector256(baseAddress, index, 4);
+ case 8:
+ return GatherVector256(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256d _mm256_i32gather_pd (double const* base_addr, __m128i vindex, const int scale)
+ /// VGATHERDPD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<double> GatherVector256(double* baseAddress, Vector128<int> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector256(baseAddress, index, 1);
+ case 2:
+ return GatherVector256(baseAddress, index, 2);
+ case 4:
+ return GatherVector256(baseAddress, index, 4);
+ case 8:
+ return GatherVector256(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm256_i64gather_epi32 (int const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERQD xmm, vm64y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherVector128(int* baseAddress, Vector256<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm256_i64gather_epi32 (int const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERQD xmm, vm64y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherVector128(uint* baseAddress, Vector256<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_i64gather_epi64 (__int64 const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERQQ ymm, vm64y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<long> GatherVector256(long* baseAddress, Vector256<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector256(baseAddress, index, 1);
+ case 2:
+ return GatherVector256(baseAddress, index, 2);
+ case 4:
+ return GatherVector256(baseAddress, index, 4);
+ case 8:
+ return GatherVector256(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_i64gather_epi64 (__int64 const* base_addr, __m256i vindex, const int scale)
+ /// VPGATHERQQ ymm, vm64y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<ulong> GatherVector256(ulong* baseAddress, Vector256<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector256(baseAddress, index, 1);
+ case 2:
+ return GatherVector256(baseAddress, index, 2);
+ case 4:
+ return GatherVector256(baseAddress, index, 4);
+ case 8:
+ return GatherVector256(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128 _mm256_i64gather_ps (float const* base_addr, __m256i vindex, const int scale)
+ /// VGATHERQPS xmm, vm64y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherVector128(float* baseAddress, Vector256<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector128(baseAddress, index, 1);
+ case 2:
+ return GatherVector128(baseAddress, index, 2);
+ case 4:
+ return GatherVector128(baseAddress, index, 4);
+ case 8:
+ return GatherVector128(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256d _mm256_i64gather_pd (double const* base_addr, __m256i vindex, const int scale)
+ /// VGATHERQPD ymm, vm64y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<double> GatherVector256(double* baseAddress, Vector256<long> index, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherVector256(baseAddress, index, 1);
+ case 2:
+ return GatherVector256(baseAddress, index, 2);
+ case 4:
+ return GatherVector256(baseAddress, index, 4);
+ case 8:
+ return GatherVector256(baseAddress, index, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+
+ /// <summary>
+ /// __m128i _mm_mask_i32gather_epi32 (__m128i src, int const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERDD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherMaskVector128(Vector128<int> source, int* baseAddress, Vector128<int> index, Vector128<int> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_mask_i32gather_epi32 (__m128i src, int const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERDD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherMaskVector128(Vector128<uint> source, uint* baseAddress, Vector128<int> index, Vector128<uint> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_mask_i32gather_epi64 (__m128i src, __int64 const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERDQ xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<long> GatherMaskVector128(Vector128<long> source, long* baseAddress, Vector128<int> index, Vector128<long> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_mask_i32gather_epi64 (__m128i src, __int64 const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERDQ xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<ulong> GatherMaskVector128(Vector128<ulong> source, ulong* baseAddress, Vector128<int> index, Vector128<ulong> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128 _mm_mask_i32gather_ps (__m128 src, float const* base_addr, __m128i vindex, __m128 mask, const int scale)
+ /// VGATHERDPS xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherMaskVector128(Vector128<float> source, float* baseAddress, Vector128<int> index, Vector128<float> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128d _mm_mask_i32gather_pd (__m128d src, double const* base_addr, __m128i vindex, __m128d mask, const int scale)
+ /// VGATHERDPD xmm, vm32x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<double> GatherMaskVector128(Vector128<double> source, double* baseAddress, Vector128<int> index, Vector128<double> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_mask_i64gather_epi32 (__m128i src, int const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERQD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherMaskVector128(Vector128<int> source, int* baseAddress, Vector128<long> index, Vector128<int> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_mask_i64gather_epi32 (__m128i src, int const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERQD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherMaskVector128(Vector128<uint> source, uint* baseAddress, Vector128<long> index, Vector128<uint> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_mask_i64gather_epi64 (__m128i src, __int64 const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERQQ xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<long> GatherMaskVector128(Vector128<long> source, long* baseAddress, Vector128<long> index, Vector128<long> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm_mask_i64gather_epi64 (__m128i src, __int64 const* base_addr, __m128i vindex, __m128i mask, const int scale)
+ /// VPGATHERQQ xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<ulong> GatherMaskVector128(Vector128<ulong> source, ulong* baseAddress, Vector128<long> index, Vector128<ulong> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128 _mm_mask_i64gather_ps (__m128 src, float const* base_addr, __m128i vindex, __m128 mask, const int scale)
+ /// VGATHERQPS xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherMaskVector128(Vector128<float> source, float* baseAddress, Vector128<long> index, Vector128<float> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128d _mm_mask_i64gather_pd (__m128d src, double const* base_addr, __m128i vindex, __m128d mask, const int scale)
+ /// VGATHERQPD xmm, vm64x, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<double> GatherMaskVector128(Vector128<double> source, double* baseAddress, Vector128<long> index, Vector128<double> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_mask_i32gather_epi32 (__m256i src, int const* base_addr, __m256i vindex, __m256i mask, const int scale)
+ /// VPGATHERDD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<int> GatherMaskVector256(Vector256<int> source, int* baseAddress, Vector256<int> index, Vector256<int> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector256(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector256(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector256(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector256(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_mask_i32gather_epi32 (__m256i src, int const* base_addr, __m256i vindex, __m256i mask, const int scale)
+ /// VPGATHERDD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<uint> GatherMaskVector256(Vector256<uint> source, uint* baseAddress, Vector256<int> index, Vector256<uint> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector256(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector256(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector256(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector256(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_mask_i32gather_epi64 (__m256i src, __int64 const* base_addr, __m128i vindex, __m256i mask, const int scale)
+ /// VPGATHERDQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<long> GatherMaskVector256(Vector256<long> source, long* baseAddress, Vector128<int> index, Vector256<long> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector256(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector256(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector256(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector256(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_mask_i32gather_epi64 (__m256i src, __int64 const* base_addr, __m128i vindex, __m256i mask, const int scale)
+ /// VPGATHERDQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<ulong> GatherMaskVector256(Vector256<ulong> source, ulong* baseAddress, Vector128<int> index, Vector256<ulong> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector256(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector256(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector256(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector256(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256 _mm256_mask_i32gather_ps (__m256 src, float const* base_addr, __m256i vindex, __m256 mask, const int scale)
+ /// VPGATHERDPS ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<float> GatherMaskVector256(Vector256<float> source, float* baseAddress, Vector256<int> index, Vector256<float> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector256(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector256(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector256(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector256(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256d _mm256_mask_i32gather_pd (__m256d src, double const* base_addr, __m128i vindex, __m256d mask, const int scale)
+ /// VPGATHERDPD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<double> GatherMaskVector256(Vector256<double> source, double* baseAddress, Vector128<int> index, Vector256<double> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector256(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector256(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector256(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector256(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm256_mask_i64gather_epi32 (__m128i src, int const* base_addr, __m256i vindex, __m128i mask, const int scale)
+ /// VPGATHERQD xmm, vm32y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<int> GatherMaskVector128(Vector128<int> source, int* baseAddress, Vector256<long> index, Vector128<int> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128i _mm256_mask_i64gather_epi32 (__m128i src, int const* base_addr, __m256i vindex, __m128i mask, const int scale)
+ /// VPGATHERQD xmm, vm32y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<uint> GatherMaskVector128(Vector128<uint> source, uint* baseAddress, Vector256<long> index, Vector128<uint> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_mask_i64gather_epi64 (__m256i src, __int64 const* base_addr, __m256i vindex, __m256i mask, const int scale)
+ /// VPGATHERQQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<long> GatherMaskVector256(Vector256<long> source, long* baseAddress, Vector256<long> index, Vector256<long> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector256(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector256(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector256(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector256(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256i _mm256_mask_i64gather_epi64 (__m256i src, __int64 const* base_addr, __m256i vindex, __m256i mask, const int scale)
+ /// VPGATHERQQ ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<ulong> GatherMaskVector256(Vector256<ulong> source, ulong* baseAddress, Vector256<long> index, Vector256<ulong> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector256(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector256(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector256(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector256(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m128 _mm256_mask_i64gather_ps (__m128 src, float const* base_addr, __m256i vindex, __m128 mask, const int scale)
+ /// VGATHERQPS xmm, vm32y, xmm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector128<float> GatherMaskVector128(Vector128<float> source, float* baseAddress, Vector256<long> index, Vector128<float> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector128(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector128(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector128(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector128(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+ /// <summary>
+ /// __m256d _mm256_mask_i64gather_pd (__m256d src, double const* base_addr, __m256i vindex, __m256d mask, const int scale)
+ /// VGATHERQPD ymm, vm32y, ymm
+ /// The scale parameter should be 1, 2, 4 or 8, otherwise, ArgumentOutOfRangeException will be thrown.
+ /// </summary>
+ public static unsafe Vector256<double> GatherMaskVector256(Vector256<double> source, double* baseAddress, Vector256<long> index, Vector256<double> mask, byte scale)
+ {
+ switch (scale)
+ {
+ case 1:
+ return GatherMaskVector256(source, baseAddress, index, mask, 1);
+ case 2:
+ return GatherMaskVector256(source, baseAddress, index, mask, 2);
+ case 4:
+ return GatherMaskVector256(source, baseAddress, index, mask, 4);
+ case 8:
+ return GatherMaskVector256(source, baseAddress, index, mask, 8);
+ default:
+ throw new ArgumentOutOfRangeException(nameof(scale));
+ }
+ }
+
+ /// <summary>
+ /// __m256i _mm256_hadd_epi16 (__m256i a, __m256i b)
+ /// VPHADDW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> HorizontalAdd(Vector256<short> left, Vector256<short> right) => HorizontalAdd(left, right);
+ /// <summary>
+ /// __m256i _mm256_hadd_epi32 (__m256i a, __m256i b)
+ /// VPHADDD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> HorizontalAdd(Vector256<int> left, Vector256<int> right) => HorizontalAdd(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_hadds_epi16 (__m256i a, __m256i b)
+ /// VPHADDSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> HorizontalAddSaturate(Vector256<short> left, Vector256<short> right) => HorizontalAddSaturate(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_hsub_epi16 (__m256i a, __m256i b)
+ /// VPHSUBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> HorizontalSubtract(Vector256<short> left, Vector256<short> right) => HorizontalSubtract(left, right);
+ /// <summary>
+ /// __m256i _mm256_hsub_epi32 (__m256i a, __m256i b)
+ /// VPHSUBD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> HorizontalSubtract(Vector256<int> left, Vector256<int> right) => HorizontalSubtract(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_hsubs_epi16 (__m256i a, __m256i b)
+ /// VPHSUBSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> HorizontalSubtractSaturate(Vector256<short> left, Vector256<short> right) => HorizontalSubtractSaturate(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<sbyte> InsertVector128(Vector256<sbyte> value, Vector128<sbyte> data, byte index) => InsertVector128(value, data, index);
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xm128, imm8
+ /// </summary>
+ public new static unsafe Vector256<sbyte> InsertVector128(Vector256<sbyte> value, sbyte* address, byte index) => InsertVector128(value, address, index);
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<byte> InsertVector128(Vector256<byte> value, Vector128<byte> data, byte index) => InsertVector128(value, data, index);
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<byte> InsertVector128(Vector256<byte> value, byte* address, byte index) => InsertVector128(value, address, index);
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<short> InsertVector128(Vector256<short> value, Vector128<short> data, byte index) => InsertVector128(value, data, index);
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<short> InsertVector128(Vector256<short> value, short* address, byte index) => InsertVector128(value, address, index);
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<ushort> InsertVector128(Vector256<ushort> value, Vector128<ushort> data, byte index) => InsertVector128(value, data, index);
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<ushort> InsertVector128(Vector256<ushort> value, ushort* address, byte index) => InsertVector128(value, address, index);
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<int> InsertVector128(Vector256<int> value, Vector128<int> data, byte index) => InsertVector128(value, data, index);
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<int> InsertVector128(Vector256<int> value, int* address, byte index) => InsertVector128(value, address, index);
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<uint> InsertVector128(Vector256<uint> value, Vector128<uint> data, byte index) => InsertVector128(value, data, index);
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<uint> InsertVector128(Vector256<uint> value, uint* address, byte index) => InsertVector128(value, address, index);
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<long> InsertVector128(Vector256<long> value, Vector128<long> data, byte index) => InsertVector128(value, data, index);
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<long> InsertVector128(Vector256<long> value, long* address, byte index) => InsertVector128(value, address, index);
+
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, xmm, imm8
+ /// </summary>
+ public static Vector256<ulong> InsertVector128(Vector256<ulong> value, Vector128<ulong> data, byte index) => InsertVector128(value, data, index);
+ /// <summary>
+ /// __m256i _mm256_inserti128_si256 (__m256i a, __m128i b, const int imm8)
+ /// VINSERTI128 ymm, ymm, m128, imm8
+ /// </summary>
+ public new static unsafe Vector256<ulong> InsertVector128(Vector256<ulong> value, ulong* address, byte index) => InsertVector128(value, address, index);
+
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<sbyte> LoadAlignedVector256NonTemporal(sbyte* address) => LoadAlignedVector256NonTemporal(address);
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<byte> LoadAlignedVector256NonTemporal(byte* address) => LoadAlignedVector256NonTemporal(address);
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<short> LoadAlignedVector256NonTemporal(short* address) => LoadAlignedVector256NonTemporal(address);
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ushort> LoadAlignedVector256NonTemporal(ushort* address) => LoadAlignedVector256NonTemporal(address);
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<int> LoadAlignedVector256NonTemporal(int* address) => LoadAlignedVector256NonTemporal(address);
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<uint> LoadAlignedVector256NonTemporal(uint* address) => LoadAlignedVector256NonTemporal(address);
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<long> LoadAlignedVector256NonTemporal(long* address) => LoadAlignedVector256NonTemporal(address);
+ /// <summary>
+ /// __m256i _mm256_stream_load_si256 (__m256i const* mem_addr)
+ /// VMOVNTDQA ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ulong> LoadAlignedVector256NonTemporal(ulong* address) => LoadAlignedVector256NonTemporal(address);
+
+ /// <summary>
+ /// __m128i _mm_maskload_epi32 (int const* mem_addr, __m128i mask)
+ /// VPMASKMOVD xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<int> MaskLoad(int* address, Vector128<int> mask) => MaskLoad(address, mask);
+ /// <summary>
+ /// __m128i _mm_maskload_epi32 (int const* mem_addr, __m128i mask)
+ /// VPMASKMOVD xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<uint> MaskLoad(uint* address, Vector128<uint> mask) => MaskLoad(address, mask);
+ /// <summary>
+ /// __m128i _mm_maskload_epi64 (__int64 const* mem_addr, __m128i mask)
+ /// VPMASKMOVQ xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<long> MaskLoad(long* address, Vector128<long> mask) => MaskLoad(address, mask);
+ /// <summary>
+ /// __m128i _mm_maskload_epi64 (__int64 const* mem_addr, __m128i mask)
+ /// VPMASKMOVQ xmm, xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ulong> MaskLoad(ulong* address, Vector128<ulong> mask) => MaskLoad(address, mask);
+
+ /// <summary>
+ /// __m256i _mm256_maskload_epi32 (int const* mem_addr, __m256i mask)
+ /// VPMASKMOVD ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<int> MaskLoad(int* address, Vector256<int> mask) => MaskLoad(address, mask);
+ /// <summary>
+ /// __m256i _mm256_maskload_epi32 (int const* mem_addr, __m256i mask)
+ /// VPMASKMOVD ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<uint> MaskLoad(uint* address, Vector256<uint> mask) => MaskLoad(address, mask);
+ /// <summary>
+ /// __m256i _mm256_maskload_epi64 (__int64 const* mem_addr, __m256i mask)
+ /// VPMASKMOVQ ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<long> MaskLoad(long* address, Vector256<long> mask) => MaskLoad(address, mask);
+ /// <summary>
+ /// __m256i _mm256_maskload_epi64 (__int64 const* mem_addr, __m256i mask)
+ /// VPMASKMOVQ ymm, ymm, m256
+ /// </summary>
+ public static unsafe Vector256<ulong> MaskLoad(ulong* address, Vector256<ulong> mask) => MaskLoad(address, mask);
+
+ /// <summary>
+ /// void _mm_maskstore_epi32 (int* mem_addr, __m128i mask, __m128i a)
+ /// VPMASKMOVD m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(int* address, Vector128<int> mask, Vector128<int> source) => MaskStore(address, mask, source);
+ /// <summary>
+ /// void _mm_maskstore_epi32 (int* mem_addr, __m128i mask, __m128i a)
+ /// VPMASKMOVD m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(uint* address, Vector128<uint> mask, Vector128<uint> source) => MaskStore(address, mask, source);
+ /// <summary>
+ /// void _mm_maskstore_epi64 (__int64* mem_addr, __m128i mask, __m128i a)
+ /// VPMASKMOVQ m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(long* address, Vector128<long> mask, Vector128<long> source) => MaskStore(address, mask, source);
+ /// <summary>
+ /// void _mm_maskstore_epi64 (__int64* mem_addr, __m128i mask, __m128i a)
+ /// VPMASKMOVQ m128, xmm, xmm
+ /// </summary>
+ public static unsafe void MaskStore(ulong* address, Vector128<ulong> mask, Vector128<ulong> source) => MaskStore(address, mask, source);
+
+ /// <summary>
+ /// void _mm256_maskstore_epi32 (int* mem_addr, __m256i mask, __m256i a)
+ /// VPMASKMOVD m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(int* address, Vector256<int> mask, Vector256<int> source) => MaskStore(address, mask, source);
+ /// <summary>
+ /// void _mm256_maskstore_epi32 (int* mem_addr, __m256i mask, __m256i a)
+ /// VPMASKMOVD m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(uint* address, Vector256<uint> mask, Vector256<uint> source) => MaskStore(address, mask, source);
+ /// <summary>
+ /// void _mm256_maskstore_epi64 (__int64* mem_addr, __m256i mask, __m256i a)
+ /// VPMASKMOVQ m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(long* address, Vector256<long> mask, Vector256<long> source) => MaskStore(address, mask, source);
+ /// <summary>
+ /// void _mm256_maskstore_epi64 (__int64* mem_addr, __m256i mask, __m256i a)
+ /// VPMASKMOVQ m256, ymm, ymm
+ /// </summary>
+ public static unsafe void MaskStore(ulong* address, Vector256<ulong> mask, Vector256<ulong> source) => MaskStore(address, mask, source);
+
+ /// <summary>
+ /// __m256i _mm256_madd_epi16 (__m256i a, __m256i b)
+ /// VPMADDWD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> MultiplyAddAdjacent(Vector256<short> left, Vector256<short> right) => MultiplyAddAdjacent(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_maddubs_epi16 (__m256i a, __m256i b)
+ /// VPMADDUBSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> MultiplyAddAdjacent(Vector256<byte> left, Vector256<sbyte> right) => MultiplyAddAdjacent(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_max_epi8 (__m256i a, __m256i b)
+ /// VPMAXSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Max(Vector256<sbyte> left, Vector256<sbyte> right) => Max(left, right);
+ /// <summary>
+ /// __m256i _mm256_max_epu8 (__m256i a, __m256i b)
+ /// VPMAXUB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Max(Vector256<byte> left, Vector256<byte> right) => Max(left, right);
+ /// <summary>
+ /// __m256i _mm256_max_epi16 (__m256i a, __m256i b)
+ /// VPMAXSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Max(Vector256<short> left, Vector256<short> right) => Max(left, right);
+ /// <summary>
+ /// __m256i _mm256_max_epu16 (__m256i a, __m256i b)
+ /// VPMAXUW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Max(Vector256<ushort> left, Vector256<ushort> right) => Max(left, right);
+ /// <summary>
+ /// __m256i _mm256_max_epi32 (__m256i a, __m256i b)
+ /// VPMAXSD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Max(Vector256<int> left, Vector256<int> right) => Max(left, right);
+ /// <summary>
+ /// __m256i _mm256_max_epu32 (__m256i a, __m256i b)
+ /// VPMAXUD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Max(Vector256<uint> left, Vector256<uint> right) => Max(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_min_epi8 (__m256i a, __m256i b)
+ /// VPMINSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Min(Vector256<sbyte> left, Vector256<sbyte> right) => Min(left, right);
+ /// <summary>
+ /// __m256i _mm256_min_epu8 (__m256i a, __m256i b)
+ /// VPMINUB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Min(Vector256<byte> left, Vector256<byte> right) => Min(left, right);
+ /// <summary>
+ /// __m256i _mm256_min_epi16 (__m256i a, __m256i b)
+ /// VPMINSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Min(Vector256<short> left, Vector256<short> right) => Min(left, right);
+ /// <summary>
+ /// __m256i _mm256_min_epu16 (__m256i a, __m256i b)
+ /// VPMINUW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Min(Vector256<ushort> left, Vector256<ushort> right) => Min(left, right);
+ /// <summary>
+ /// __m256i _mm256_min_epi32 (__m256i a, __m256i b)
+ /// VPMINSD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Min(Vector256<int> left, Vector256<int> right) => Min(left, right);
+ /// <summary>
+ /// __m256i _mm256_min_epu32 (__m256i a, __m256i b)
+ /// VPMINUD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Min(Vector256<uint> left, Vector256<uint> right) => Min(left, right);
+
+ /// <summary>
+ /// int _mm256_movemask_epi8 (__m256i a)
+ /// VPMOVMSKB reg, ymm
+ /// </summary>
+ public static int MoveMask(Vector256<sbyte> value) => MoveMask(value);
+ /// <summary>
+ /// int _mm256_movemask_epi8 (__m256i a)
+ /// VPMOVMSKB reg, ymm
+ /// </summary>
+ public static int MoveMask(Vector256<byte> value) => MoveMask(value);
+
+ /// <summary>
+ /// __m256i _mm256_mpsadbw_epu8 (__m256i a, __m256i b, const int imm8)
+ /// VMPSADBW ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ushort> MultipleSumAbsoluteDifferences(Vector256<byte> left, Vector256<byte> right, byte mask) => MultipleSumAbsoluteDifferences(left, right, mask);
+
+ /// <summary>
+ /// __m256i _mm256_mul_epi32 (__m256i a, __m256i b)
+ /// VPMULDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> Multiply(Vector256<int> left, Vector256<int> right) => Multiply(left, right);
+ /// <summary>
+ /// __m256i _mm256_mul_epu32 (__m256i a, __m256i b)
+ /// VPMULUDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> Multiply(Vector256<uint> left, Vector256<uint> right) => Multiply(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_mulhi_epi16 (__m256i a, __m256i b)
+ /// VPMULHW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> MultiplyHigh(Vector256<short> left, Vector256<short> right) => MultiplyHigh(left, right);
+ /// <summary>
+ /// __m256i _mm256_mulhi_epu16 (__m256i a, __m256i b)
+ /// VPMULHUW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> MultiplyHigh(Vector256<ushort> left, Vector256<ushort> right) => MultiplyHigh(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_mulhrs_epi16 (__m256i a, __m256i b)
+ /// VPMULHRSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> MultiplyHighRoundScale(Vector256<short> left, Vector256<short> right) => MultiplyHighRoundScale(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_mullo_epi16 (__m256i a, __m256i b)
+ /// VPMULLW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> MultiplyLow(Vector256<short> left, Vector256<short> right) => MultiplyLow(left, right);
+ /// <summary>
+ /// __m256i _mm256_mullo_epi32 (__m256i a, __m256i b)
+ /// VPMULLD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> MultiplyLow(Vector256<int> left, Vector256<int> right) => MultiplyLow(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Or(Vector256<sbyte> left, Vector256<sbyte> right) => Or(left, right);
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Or(Vector256<byte> left, Vector256<byte> right) => Or(left, right);
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Or(Vector256<short> left, Vector256<short> right) => Or(left, right);
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Or(Vector256<ushort> left, Vector256<ushort> right) => Or(left, right);
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Or(Vector256<int> left, Vector256<int> right) => Or(left, right);
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Or(Vector256<uint> left, Vector256<uint> right) => Or(left, right);
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> Or(Vector256<long> left, Vector256<long> right) => Or(left, right);
+ /// <summary>
+ /// __m256i _mm256_or_si256 (__m256i a, __m256i b)
+ /// VPOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> Or(Vector256<ulong> left, Vector256<ulong> right) => Or(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_packs_epi16 (__m256i a, __m256i b)
+ /// VPACKSSWB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> PackSignedSaturate(Vector256<short> left, Vector256<short> right) => PackSignedSaturate(left, right);
+ /// <summary>
+ /// __m256i _mm256_packs_epi32 (__m256i a, __m256i b)
+ /// VPACKSSDW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> PackSignedSaturate(Vector256<int> left, Vector256<int> right) => PackSignedSaturate(left, right);
+ /// <summary>
+ /// __m256i _mm256_packus_epi16 (__m256i a, __m256i b)
+ /// VPACKUSWB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> PackUnsignedSaturate(Vector256<short> left, Vector256<short> right) => PackUnsignedSaturate(left, right);
+ /// <summary>
+ /// __m256i _mm256_packus_epi32 (__m256i a, __m256i b)
+ /// VPACKUSDW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> PackUnsignedSaturate(Vector256<int> left, Vector256<int> right) => PackUnsignedSaturate(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<sbyte> Permute2x128(Vector256<sbyte> left, Vector256<sbyte> right, byte control) => Permute2x128(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<byte> Permute2x128(Vector256<byte> left, Vector256<byte> right, byte control) => Permute2x128(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<short> Permute2x128(Vector256<short> left, Vector256<short> right, byte control) => Permute2x128(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ushort> Permute2x128(Vector256<ushort> left, Vector256<ushort> right, byte control) => Permute2x128(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<int> Permute2x128(Vector256<int> left, Vector256<int> right, byte control) => Permute2x128(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<uint> Permute2x128(Vector256<uint> left, Vector256<uint> right, byte control) => Permute2x128(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<long> Permute2x128(Vector256<long> left, Vector256<long> right, byte control) => Permute2x128(left, right, control);
+ /// <summary>
+ /// __m256i _mm256_permute2x128_si256 (__m256i a, __m256i b, const int imm8)
+ /// VPERM2I128 ymm, ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ulong> Permute2x128(Vector256<ulong> left, Vector256<ulong> right, byte control) => Permute2x128(left, right, control);
+
+ /// <summary>
+ /// __m256i _mm256_permute4x64_epi64 (__m256i a, const int imm8)
+ /// VPERMQ ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<long> Permute4x64(Vector256<long> value, byte control) => Permute4x64(value, control);
+ /// <summary>
+ /// __m256i _mm256_permute4x64_epi64 (__m256i a, const int imm8)
+ /// VPERMQ ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ulong> Permute4x64(Vector256<ulong> value, byte control) => Permute4x64(value, control);
+ /// <summary>
+ /// __m256d _mm256_permute4x64_pd (__m256d a, const int imm8)
+ /// VPERMPD ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<double> Permute4x64(Vector256<double> value, byte control) => Permute4x64(value, control);
+
+ /// <summary>
+ /// __m256i _mm256_permutevar8x32_epi32 (__m256i a, __m256i idx)
+ /// VPERMD ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<int> PermuteVar8x32(Vector256<int> left, Vector256<int> control) => PermuteVar8x32(left, control);
+ /// <summary>
+ /// __m256i _mm256_permutevar8x32_epi32 (__m256i a, __m256i idx)
+ /// VPERMD ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<uint> PermuteVar8x32(Vector256<uint> left, Vector256<uint> control) => PermuteVar8x32(left, control);
+ /// <summary>
+ /// __m256 _mm256_permutevar8x32_ps (__m256 a, __m256i idx)
+ /// VPERMPS ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<float> PermuteVar8x32(Vector256<float> left, Vector256<int> control) => PermuteVar8x32(left, control);
+
+ /// <summary>
+ /// __m256i _mm256_sll_epi16 (__m256i a, __m128i count)
+ /// VPSLLW ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<short> ShiftLeftLogical(Vector256<short> value, Vector128<short> count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_sll_epi16 (__m256i a, __m128i count)
+ /// VPSLLW ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ushort> ShiftLeftLogical(Vector256<ushort> value, Vector128<ushort> count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_sll_epi32 (__m256i a, __m128i count)
+ /// VPSLLD ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<int> ShiftLeftLogical(Vector256<int> value, Vector128<int> count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_sll_epi32 (__m256i a, __m128i count)
+ /// VPSLLD ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<uint> ShiftLeftLogical(Vector256<uint> value, Vector128<uint> count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_sll_epi64 (__m256i a, __m128i count)
+ /// VPSLLQ ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<long> ShiftLeftLogical(Vector256<long> value, Vector128<long> count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_sll_epi64 (__m256i a, __m128i count)
+ /// VPSLLQ ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ulong> ShiftLeftLogical(Vector256<ulong> value, Vector128<ulong> count) => ShiftLeftLogical(value, count);
+
+ /// <summary>
+ /// __m256i _mm256_slli_epi16 (__m256i a, int imm8)
+ /// VPSLLW ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<short> ShiftLeftLogical(Vector256<short> value, byte count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_slli_epi16 (__m256i a, int imm8)
+ /// VPSLLW ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ushort> ShiftLeftLogical(Vector256<ushort> value, byte count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_slli_epi32 (__m256i a, int imm8)
+ /// VPSLLD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<int> ShiftLeftLogical(Vector256<int> value, byte count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_slli_epi32 (__m256i a, int imm8)
+ /// VPSLLD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<uint> ShiftLeftLogical(Vector256<uint> value, byte count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_slli_epi64 (__m256i a, int imm8)
+ /// VPSLLQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<long> ShiftLeftLogical(Vector256<long> value, byte count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_slli_epi64 (__m256i a, int imm8)
+ /// VPSLLQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ulong> ShiftLeftLogical(Vector256<ulong> value, byte count) => ShiftLeftLogical(value, count);
+
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<sbyte> ShiftLeftLogical128BitLane(Vector256<sbyte> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<byte> ShiftLeftLogical128BitLane(Vector256<byte> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<short> ShiftLeftLogical128BitLane(Vector256<short> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ushort> ShiftLeftLogical128BitLane(Vector256<ushort> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<int> ShiftLeftLogical128BitLane(Vector256<int> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<uint> ShiftLeftLogical128BitLane(Vector256<uint> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<long> ShiftLeftLogical128BitLane(Vector256<long> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bslli_epi128 (__m256i a, const int imm8)
+ /// VPSLLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ulong> ShiftLeftLogical128BitLane(Vector256<ulong> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+
+ /// <summary>
+ /// __m256i _mm256_sllv_epi32 (__m256i a, __m256i count)
+ /// VPSLLVD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> ShiftLeftLogicalVariable(Vector256<int> value, Vector256<uint> count) => ShiftLeftLogicalVariable(value, count);
+ /// <summary>
+ /// __m256i _mm256_sllv_epi32 (__m256i a, __m256i count)
+ /// VPSLLVD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> ShiftLeftLogicalVariable(Vector256<uint> value, Vector256<uint> count) => ShiftLeftLogicalVariable(value, count);
+ /// <summary>
+ /// __m256i _mm256_sllv_epi64 (__m256i a, __m256i count)
+ /// VPSLLVQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> ShiftLeftLogicalVariable(Vector256<long> value, Vector256<ulong> count) => ShiftLeftLogicalVariable(value, count);
+ /// <summary>
+ /// __m256i _mm256_sllv_epi64 (__m256i a, __m256i count)
+ /// VPSLLVQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> ShiftLeftLogicalVariable(Vector256<ulong> value, Vector256<ulong> count) => ShiftLeftLogicalVariable(value, count);
+
+ /// <summary>
+ /// __m128i _mm_sllv_epi32 (__m128i a, __m128i count)
+ /// VPSLLVD xmm, ymm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftLeftLogicalVariable(Vector128<int> value, Vector128<uint> count) => ShiftLeftLogicalVariable(value, count);
+ /// <summary>
+ /// __m128i _mm_sllv_epi32 (__m128i a, __m128i count)
+ /// VPSLLVD xmm, ymm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> ShiftLeftLogicalVariable(Vector128<uint> value, Vector128<uint> count) => ShiftLeftLogicalVariable(value, count);
+ /// <summary>
+ /// __m128i _mm_sllv_epi64 (__m128i a, __m128i count)
+ /// VPSLLVQ xmm, ymm, xmm/m128
+ /// </summary>
+ public static Vector128<long> ShiftLeftLogicalVariable(Vector128<long> value, Vector128<ulong> count) => ShiftLeftLogicalVariable(value, count);
+ /// <summary>
+ /// __m128i _mm_sllv_epi64 (__m128i a, __m128i count)
+ /// VPSLLVQ xmm, ymm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> ShiftLeftLogicalVariable(Vector128<ulong> value, Vector128<ulong> count) => ShiftLeftLogicalVariable(value, count);
+
+ /// <summary>
+ /// _mm256_sra_epi16 (__m256i a, __m128i count)
+ /// VPSRAW ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<short> ShiftRightArithmetic(Vector256<short> value, Vector128<short> count) => ShiftRightArithmetic(value, count);
+ /// <summary>
+ /// _mm256_sra_epi32 (__m256i a, __m128i count)
+ /// VPSRAD ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<int> ShiftRightArithmetic(Vector256<int> value, Vector128<int> count) => ShiftRightArithmetic(value, count);
+
+ /// <summary>
+ /// __m256i _mm256_srai_epi16 (__m256i a, int imm8)
+ /// VPSRAW ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<short> ShiftRightArithmetic(Vector256<short> value, byte count) => ShiftRightArithmetic(value, count);
+ /// <summary>
+ /// __m256i _mm256_srai_epi32 (__m256i a, int imm8)
+ /// VPSRAD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<int> ShiftRightArithmetic(Vector256<int> value, byte count) => ShiftRightArithmetic(value, count);
+
+ /// <summary>
+ /// __m256i _mm256_srav_epi32 (__m256i a, __m256i count)
+ /// VPSRAVD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> ShiftRightArithmeticVariable(Vector256<int> value, Vector256<uint> count) => ShiftRightArithmeticVariable(value, count);
+
+ /// <summary>
+ /// __m128i _mm_srav_epi32 (__m128i a, __m128i count)
+ /// VPSRAVD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftRightArithmeticVariable(Vector128<int> value, Vector128<uint> count) => ShiftRightArithmeticVariable(value, count);
+
+ /// <summary>
+ /// __m256i _mm256_srl_epi16 (__m256i a, __m128i count)
+ /// VPSRLW ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<short> ShiftRightLogical(Vector256<short> value, Vector128<short> count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_srl_epi16 (__m256i a, __m128i count)
+ /// VPSRLW ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ushort> ShiftRightLogical(Vector256<ushort> value, Vector128<ushort> count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_srl_epi32 (__m256i a, __m128i count)
+ /// VPSRLD ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<int> ShiftRightLogical(Vector256<int> value, Vector128<int> count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_srl_epi32 (__m256i a, __m128i count)
+ /// VPSRLD ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<uint> ShiftRightLogical(Vector256<uint> value, Vector128<uint> count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_srl_epi64 (__m256i a, __m128i count)
+ /// VPSRLQ ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<long> ShiftRightLogical(Vector256<long> value, Vector128<long> count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_srl_epi64 (__m256i a, __m128i count)
+ /// VPSRLQ ymm, ymm, xmm/m128
+ /// </summary>
+ public static Vector256<ulong> ShiftRightLogical(Vector256<ulong> value, Vector128<ulong> count) => ShiftRightLogical(value, count);
+
+ /// <summary>
+ /// __m256i _mm256_srli_epi16 (__m256i a, int imm8)
+ /// VPSRLW ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<short> ShiftRightLogical(Vector256<short> value, byte count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_srli_epi16 (__m256i a, int imm8)
+ /// VPSRLW ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ushort> ShiftRightLogical(Vector256<ushort> value, byte count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_srli_epi32 (__m256i a, int imm8)
+ /// VPSRLD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<int> ShiftRightLogical(Vector256<int> value, byte count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_srli_epi32 (__m256i a, int imm8)
+ /// VPSRLD ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<uint> ShiftRightLogical(Vector256<uint> value, byte count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_srli_epi64 (__m256i a, int imm8)
+ /// VPSRLQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<long> ShiftRightLogical(Vector256<long> value, byte count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m256i _mm256_srli_epi64 (__m256i a, int imm8)
+ /// VPSRLQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ulong> ShiftRightLogical(Vector256<ulong> value, byte count) => ShiftRightLogical(value, count);
+
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<sbyte> ShiftRightLogical128BitLane(Vector256<sbyte> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<byte> ShiftRightLogical128BitLane(Vector256<byte> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<short> ShiftRightLogical128BitLane(Vector256<short> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ushort> ShiftRightLogical128BitLane(Vector256<ushort> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<int> ShiftRightLogical128BitLane(Vector256<int> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<uint> ShiftRightLogical128BitLane(Vector256<uint> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<long> ShiftRightLogical128BitLane(Vector256<long> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m256i _mm256_bsrli_epi128 (__m256i a, const int imm8)
+ /// VPSRLDQ ymm, ymm, imm8
+ /// </summary>
+ public static Vector256<ulong> ShiftRightLogical128BitLane(Vector256<ulong> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+
+ /// <summary>
+ /// __m256i _mm256_srlv_epi32 (__m256i a, __m256i count)
+ /// VPSRLVD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> ShiftRightLogicalVariable(Vector256<int> value, Vector256<uint> count) => ShiftRightLogicalVariable(value, count);
+ /// <summary>
+ /// __m256i _mm256_srlv_epi32 (__m256i a, __m256i count)
+ /// VPSRLVD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> ShiftRightLogicalVariable(Vector256<uint> value, Vector256<uint> count) => ShiftRightLogicalVariable(value, count);
+ /// <summary>
+ /// __m256i _mm256_srlv_epi64 (__m256i a, __m256i count)
+ /// VPSRLVQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> ShiftRightLogicalVariable(Vector256<long> value, Vector256<ulong> count) => ShiftRightLogicalVariable(value, count);
+ /// <summary>
+ /// __m256i _mm256_srlv_epi64 (__m256i a, __m256i count)
+ /// VPSRLVQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> ShiftRightLogicalVariable(Vector256<ulong> value, Vector256<ulong> count) => ShiftRightLogicalVariable(value, count);
+
+ /// <summary>
+ /// __m128i _mm_srlv_epi32 (__m128i a, __m128i count)
+ /// VPSRLVD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftRightLogicalVariable(Vector128<int> value, Vector128<uint> count) => ShiftRightLogicalVariable(value, count);
+ /// <summary>
+ /// __m128i _mm_srlv_epi32 (__m128i a, __m128i count)
+ /// VPSRLVD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> ShiftRightLogicalVariable(Vector128<uint> value, Vector128<uint> count) => ShiftRightLogicalVariable(value, count);
+ /// <summary>
+ /// __m128i _mm_srlv_epi64 (__m128i a, __m128i count)
+ /// VPSRLVQ xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> ShiftRightLogicalVariable(Vector128<long> value, Vector128<ulong> count) => ShiftRightLogicalVariable(value, count);
+ /// <summary>
+ /// __m128i _mm_srlv_epi64 (__m128i a, __m128i count)
+ /// VPSRLVQ xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> ShiftRightLogicalVariable(Vector128<ulong> value, Vector128<ulong> count) => ShiftRightLogicalVariable(value, count);
+
+ /// <summary>
+ /// __m256i _mm256_shuffle_epi8 (__m256i a, __m256i b)
+ /// VPSHUFB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Shuffle(Vector256<sbyte> value, Vector256<sbyte> mask) => Shuffle(value, mask);
+ /// <summary>
+ /// __m256i _mm256_shuffle_epi8 (__m256i a, __m256i b)
+ /// VPSHUFB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Shuffle(Vector256<byte> value, Vector256<byte> mask) => Shuffle(value, mask);
+ /// <summary>
+ /// __m256i _mm256_shuffle_epi32 (__m256i a, const int imm8)
+ /// VPSHUFD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Shuffle(Vector256<int> value, byte control) => Shuffle(value, control);
+ /// <summary>
+ /// __m256i _mm256_shuffle_epi32 (__m256i a, const int imm8)
+ /// VPSHUFD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Shuffle(Vector256<uint> value, byte control) => Shuffle(value, control);
+
+ /// <summary>
+ /// __m256i _mm256_shufflehi_epi16 (__m256i a, const int imm8)
+ /// VPSHUFHW ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<short> ShuffleHigh(Vector256<short> value, byte control) => ShuffleHigh(value, control);
+ /// <summary>
+ /// __m256i _mm256_shufflehi_epi16 (__m256i a, const int imm8)
+ /// VPSHUFHW ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ushort> ShuffleHigh(Vector256<ushort> value, byte control) => ShuffleHigh(value, control);
+
+ /// <summary>
+ /// __m256i _mm256_shufflelo_epi16 (__m256i a, const int imm8)
+ /// VPSHUFLW ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<short> ShuffleLow(Vector256<short> value, byte control) => ShuffleLow(value, control);
+ /// <summary>
+ /// __m256i _mm256_shufflelo_epi16 (__m256i a, const int imm8)
+ /// VPSHUFLW ymm, ymm/m256, imm8
+ /// </summary>
+ public static Vector256<ushort> ShuffleLow(Vector256<ushort> value, byte control) => ShuffleLow(value, control);
+
+ /// <summary>
+ /// __m256i _mm256_sign_epi8 (__m256i a, __m256i b)
+ /// VPSIGNB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Sign(Vector256<sbyte> left, Vector256<sbyte> right) => Sign(left, right);
+ /// <summary>
+ /// __m256i _mm256_sign_epi16 (__m256i a, __m256i b)
+ /// VPSIGNW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Sign(Vector256<short> left, Vector256<short> right) => Sign(left, right);
+ /// <summary>
+ /// __m256i _mm256_sign_epi32 (__m256i a, __m256i b)
+ /// VPSIGND ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Sign(Vector256<int> left, Vector256<int> right) => Sign(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_sub_epi8 (__m256i a, __m256i b)
+ /// VPSUBB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Subtract(Vector256<sbyte> left, Vector256<sbyte> right) => Subtract(left, right);
+ /// <summary>
+ /// __m256i _mm256_sub_epi8 (__m256i a, __m256i b)
+ /// VPSUBB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Subtract(Vector256<byte> left, Vector256<byte> right) => Subtract(left, right);
+ /// <summary>
+ /// __m256i _mm256_sub_epi16 (__m256i a, __m256i b)
+ /// VPSUBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Subtract(Vector256<short> left, Vector256<short> right) => Subtract(left, right);
+ /// <summary>
+ /// __m256i _mm256_sub_epi16 (__m256i a, __m256i b)
+ /// VPSUBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Subtract(Vector256<ushort> left, Vector256<ushort> right) => Subtract(left, right);
+ /// <summary>
+ /// __m256i _mm256_sub_epi32 (__m256i a, __m256i b)
+ /// VPSUBD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Subtract(Vector256<int> left, Vector256<int> right) => Subtract(left, right);
+ /// <summary>
+ /// __m256i _mm256_sub_epi32 (__m256i a, __m256i b)
+ /// VPSUBD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Subtract(Vector256<uint> left, Vector256<uint> right) => Subtract(left, right);
+ /// <summary>
+ /// __m256i _mm256_sub_epi64 (__m256i a, __m256i b)
+ /// VPSUBQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> Subtract(Vector256<long> left, Vector256<long> right) => Subtract(left, right);
+ /// <summary>
+ /// __m256i _mm256_sub_epi64 (__m256i a, __m256i b)
+ /// VPSUBQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> Subtract(Vector256<ulong> left, Vector256<ulong> right) => Subtract(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_subs_epi8 (__m256i a, __m256i b)
+ /// VPSUBSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> SubtractSaturate(Vector256<sbyte> left, Vector256<sbyte> right) => SubtractSaturate(left, right);
+ /// <summary>
+ /// __m256i _mm256_subs_epi16 (__m256i a, __m256i b)
+ /// VPSUBSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> SubtractSaturate(Vector256<short> left, Vector256<short> right) => SubtractSaturate(left, right);
+ /// <summary>
+ /// __m256i _mm256_subs_epu8 (__m256i a, __m256i b)
+ /// VPSUBUSB ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> SubtractSaturate(Vector256<byte> left, Vector256<byte> right) => SubtractSaturate(left, right);
+ /// <summary>
+ /// __m256i _mm256_subs_epu16 (__m256i a, __m256i b)
+ /// VPSUBUSW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> SubtractSaturate(Vector256<ushort> left, Vector256<ushort> right) => SubtractSaturate(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_sad_epu8 (__m256i a, __m256i b)
+ /// VPSADBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> SumAbsoluteDifferences(Vector256<byte> left, Vector256<byte> right) => SumAbsoluteDifferences(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi8 (__m256i a, __m256i b)
+ /// VPUNPCKHBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> UnpackHigh(Vector256<sbyte> left, Vector256<sbyte> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi8 (__m256i a, __m256i b)
+ /// VPUNPCKHBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> UnpackHigh(Vector256<byte> left, Vector256<byte> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi16 (__m256i a, __m256i b)
+ /// VPUNPCKHWD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> UnpackHigh(Vector256<short> left, Vector256<short> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi16 (__m256i a, __m256i b)
+ /// VPUNPCKHWD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> UnpackHigh(Vector256<ushort> left, Vector256<ushort> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi32 (__m256i a, __m256i b)
+ /// VPUNPCKHDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> UnpackHigh(Vector256<int> left, Vector256<int> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi32 (__m256i a, __m256i b)
+ /// VPUNPCKHDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> UnpackHigh(Vector256<uint> left, Vector256<uint> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi64 (__m256i a, __m256i b)
+ /// VPUNPCKHQDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> UnpackHigh(Vector256<long> left, Vector256<long> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpackhi_epi64 (__m256i a, __m256i b)
+ /// VPUNPCKHQDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> UnpackHigh(Vector256<ulong> left, Vector256<ulong> right) => UnpackHigh(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi8 (__m256i a, __m256i b)
+ /// VPUNPCKLBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> UnpackLow(Vector256<sbyte> left, Vector256<sbyte> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi8 (__m256i a, __m256i b)
+ /// VPUNPCKLBW ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> UnpackLow(Vector256<byte> left, Vector256<byte> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi16 (__m256i a, __m256i b)
+ /// VPUNPCKLWD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> UnpackLow(Vector256<short> left, Vector256<short> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi16 (__m256i a, __m256i b)
+ /// VPUNPCKLWD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> UnpackLow(Vector256<ushort> left, Vector256<ushort> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi32 (__m256i a, __m256i b)
+ /// VPUNPCKLDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> UnpackLow(Vector256<int> left, Vector256<int> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi32 (__m256i a, __m256i b)
+ /// VPUNPCKLDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> UnpackLow(Vector256<uint> left, Vector256<uint> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi64 (__m256i a, __m256i b)
+ /// VPUNPCKLQDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> UnpackLow(Vector256<long> left, Vector256<long> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m256i _mm256_unpacklo_epi64 (__m256i a, __m256i b)
+ /// VPUNPCKLQDQ ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> UnpackLow(Vector256<ulong> left, Vector256<ulong> right) => UnpackLow(left, right);
+
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<sbyte> Xor(Vector256<sbyte> left, Vector256<sbyte> right) => Xor(left, right);
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<byte> Xor(Vector256<byte> left, Vector256<byte> right) => Xor(left, right);
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<short> Xor(Vector256<short> left, Vector256<short> right) => Xor(left, right);
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ushort> Xor(Vector256<ushort> left, Vector256<ushort> right) => Xor(left, right);
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<int> Xor(Vector256<int> left, Vector256<int> right) => Xor(left, right);
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<uint> Xor(Vector256<uint> left, Vector256<uint> right) => Xor(left, right);
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<long> Xor(Vector256<long> left, Vector256<long> right) => Xor(left, right);
+ /// <summary>
+ /// __m256i _mm256_xor_si256 (__m256i a, __m256i b)
+ /// VPXOR ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<ulong> Xor(Vector256<ulong> left, Vector256<ulong> right) => Xor(left, right);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi1.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi1.PlatformNotSupported.cs
new file mode 100644
index 000000000..2b0b48fe7
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi1.PlatformNotSupported.cs
@@ -0,0 +1,96 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel BMI1 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Bmi1
+ {
+ internal Bmi1() { }
+
+ public static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// unsigned int _andn_u32 (unsigned int a, unsigned int b)
+ /// ANDN r32a, r32b, reg/m32
+ /// </summary>
+ public static uint AndNot(uint left, uint right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _andn_u64 (unsigned __int64 a, unsigned __int64 b)
+ /// ANDN r64a, r64b, reg/m64
+ /// </summary>
+ public static ulong AndNot(ulong left, ulong right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// unsigned int _bextr_u32 (unsigned int a, unsigned int start, unsigned int len)
+ /// BEXTR r32a, reg/m32, r32b
+ /// </summary>
+ public static uint BitFieldExtract(uint value, byte start, byte length) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _bextr_u64 (unsigned __int64 a, unsigned int start, unsigned int len)
+ /// BEXTR r64a, reg/m64, r64b
+ /// </summary>
+ public static ulong BitFieldExtract(ulong value, byte start, byte length) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned int _bextr2_u32 (unsigned int a, unsigned int control)
+ /// BEXTR r32a, reg/m32, r32b
+ /// </summary>
+ public static uint BitFieldExtract(uint value, ushort control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _bextr2_u64 (unsigned __int64 a, unsigned __int64 control)
+ /// BEXTR r64a, reg/m64, r64b
+ /// </summary>
+ public static ulong BitFieldExtract(ulong value, ushort control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// unsigned int _blsi_u32 (unsigned int a)
+ /// BLSI reg, reg/m32
+ /// </summary>
+ public static uint ExtractLowestSetBit(uint value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _blsi_u64 (unsigned __int64 a)
+ /// BLSI reg, reg/m64
+ /// </summary>
+ public static ulong ExtractLowestSetBit(ulong value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// unsigned int _blsmsk_u32 (unsigned int a)
+ /// BLSMSK reg, reg/m32
+ /// </summary>
+ public static uint GetMaskUpToLowestSetBit(uint value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _blsmsk_u64 (unsigned __int64 a)
+ /// BLSMSK reg, reg/m64
+ /// </summary>
+ public static ulong GetMaskUpToLowestSetBit(ulong value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// unsigned int _blsr_u32 (unsigned int a)
+ /// BLSR reg, reg/m32
+ /// </summary>
+ public static uint ResetLowestSetBit(uint value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _blsr_u64 (unsigned __int64 a)
+ /// BLSR reg, reg/m64
+ /// </summary>
+ public static ulong ResetLowestSetBit(ulong value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_tzcnt_32 (unsigned int a)
+ /// TZCNT reg, reg/m32
+ /// </summary>
+ public static uint TrailingZeroCount(uint value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm_tzcnt_64 (unsigned __int64 a)
+ /// TZCNT reg, reg/m64
+ /// </summary>
+ public static ulong TrailingZeroCount(ulong value) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi1.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi1.cs
new file mode 100644
index 000000000..f06f54d83
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi1.cs
@@ -0,0 +1,96 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel BMI1 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Bmi1
+ {
+ internal Bmi1() { }
+
+ public static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// unsigned int _andn_u32 (unsigned int a, unsigned int b)
+ /// ANDN r32a, r32b, reg/m32
+ /// </summary>
+ public static uint AndNot(uint left, uint right) => AndNot(left, right);
+ /// <summary>
+ /// unsigned __int64 _andn_u64 (unsigned __int64 a, unsigned __int64 b)
+ /// ANDN r64a, r64b, reg/m64
+ /// </summary>
+ public static ulong AndNot(ulong left, ulong right) => AndNot(left, right);
+
+ /// <summary>
+ /// unsigned int _bextr_u32 (unsigned int a, unsigned int start, unsigned int len)
+ /// BEXTR r32a, reg/m32, r32b
+ /// </summary>
+ public static uint BitFieldExtract(uint value, byte start, byte length) => BitFieldExtract(value, start, length);
+ /// <summary>
+ /// unsigned __int64 _bextr_u64 (unsigned __int64 a, unsigned int start, unsigned int len)
+ /// BEXTR r64a, reg/m64, r64b
+ /// </summary>
+ public static ulong BitFieldExtract(ulong value, byte start, byte length) => BitFieldExtract(value, start, length);
+ /// <summary>
+ /// unsigned int _bextr2_u32 (unsigned int a, unsigned int control)
+ /// BEXTR r32a, reg/m32, r32b
+ /// </summary>
+ public static uint BitFieldExtract(uint value, ushort control) => BitFieldExtract(value, control);
+ /// <summary>
+ /// unsigned __int64 _bextr2_u64 (unsigned __int64 a, unsigned __int64 control)
+ /// BEXTR r64a, reg/m64, r64b
+ /// </summary>
+ public static ulong BitFieldExtract(ulong value, ushort control) => BitFieldExtract(value, control);
+
+ /// <summary>
+ /// unsigned int _blsi_u32 (unsigned int a)
+ /// BLSI reg, reg/m32
+ /// </summary>
+ public static uint ExtractLowestSetBit(uint value) => ExtractLowestSetBit(value);
+ /// <summary>
+ /// unsigned __int64 _blsi_u64 (unsigned __int64 a)
+ /// BLSI reg, reg/m64
+ /// </summary>
+ public static ulong ExtractLowestSetBit(ulong value) => ExtractLowestSetBit(value);
+
+ /// <summary>
+ /// unsigned int _blsmsk_u32 (unsigned int a)
+ /// BLSMSK reg, reg/m32
+ /// </summary>
+ public static uint GetMaskUpToLowestSetBit(uint value) => GetMaskUpToLowestSetBit(value);
+ /// <summary>
+ /// unsigned __int64 _blsmsk_u64 (unsigned __int64 a)
+ /// BLSMSK reg, reg/m64
+ /// </summary>
+ public static ulong GetMaskUpToLowestSetBit(ulong value) => GetMaskUpToLowestSetBit(value);
+
+ /// <summary>
+ /// unsigned int _blsr_u32 (unsigned int a)
+ /// BLSR reg, reg/m32
+ /// </summary>
+ public static uint ResetLowestSetBit(uint value) => ResetLowestSetBit(value);
+ /// <summary>
+ /// unsigned __int64 _blsr_u64 (unsigned __int64 a)
+ /// BLSR reg, reg/m64
+ /// </summary>
+ public static ulong ResetLowestSetBit(ulong value) => ResetLowestSetBit(value);
+
+ /// <summary>
+ /// int _mm_tzcnt_32 (unsigned int a)
+ /// TZCNT reg, reg/m32
+ /// </summary>
+ public static uint TrailingZeroCount(uint value) => TrailingZeroCount(value);
+ /// <summary>
+ /// __int64 _mm_tzcnt_64 (unsigned __int64 a)
+ /// TZCNT reg, reg/m64
+ /// </summary>
+ public static ulong TrailingZeroCount(ulong value) => TrailingZeroCount(value);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi2.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi2.PlatformNotSupported.cs
new file mode 100644
index 000000000..0789d6f3c
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi2.PlatformNotSupported.cs
@@ -0,0 +1,64 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel BMI2 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Bmi2
+ {
+ internal Bmi2() { }
+
+ public static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// unsigned int _bzhi_u32 (unsigned int a, unsigned int index)
+ /// BZHI r32a, reg/m32, r32b
+ /// </summary>
+ public static uint ZeroHighBits(uint value, uint index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _bzhi_u64 (unsigned __int64 a, unsigned int index)
+ /// BZHI r64a, reg/m32, r64b
+ /// </summary>
+ public static ulong ZeroHighBits(ulong value, ulong index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// unsigned int _mulx_u32 (unsigned int a, unsigned int b, unsigned int* hi)
+ /// MULX r32a, r32b, reg/m32
+ /// </summary>
+ public static unsafe uint MultiplyNoFlags(uint left, uint right, uint* high) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _mulx_u64 (unsigned __int64 a, unsigned __int64 b, unsigned __int64* hi)
+ /// MULX r64a, r64b, reg/m64
+ /// </summary>
+ public static unsafe ulong MultiplyNoFlags(ulong left, ulong right, ulong* high) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// unsigned int _pdep_u32 (unsigned int a, unsigned int mask)
+ /// PDEP r32a, r32b, reg/m32
+ /// </summary>
+ public static uint ParallelBitDeposit(uint value, uint mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _pdep_u64 (unsigned __int64 a, unsigned __int64 mask)
+ /// PDEP r64a, r64b, reg/m64
+ /// </summary>
+ public static ulong ParallelBitDeposit(ulong value, ulong mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// unsigned int _pext_u32 (unsigned int a, unsigned int mask)
+ /// PEXT r32a, r32b, reg/m32
+ /// </summary>
+ public static uint ParallelBitExtract(uint value, uint mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _pext_u64 (unsigned __int64 a, unsigned __int64 mask)
+ /// PEXT r64a, r64b, reg/m64
+ /// </summary>
+ public static ulong ParallelBitExtract(ulong value, ulong mask) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi2.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi2.cs
new file mode 100644
index 000000000..d8fb1521a
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Bmi2.cs
@@ -0,0 +1,64 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel BMI2 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Bmi2
+ {
+ internal Bmi2() { }
+
+ public static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// unsigned int _bzhi_u32 (unsigned int a, unsigned int index)
+ /// BZHI r32a, reg/m32, r32b
+ /// </summary>
+ public static uint ZeroHighBits(uint value, uint index) => ZeroHighBits(value, index);
+ /// <summary>
+ /// unsigned __int64 _bzhi_u64 (unsigned __int64 a, unsigned int index)
+ /// BZHI r64a, reg/m32, r64b
+ /// </summary>
+ public static ulong ZeroHighBits(ulong value, ulong index) => ZeroHighBits(value, index);
+
+ /// <summary>
+ /// unsigned int _mulx_u32 (unsigned int a, unsigned int b, unsigned int* hi)
+ /// MULX r32a, r32b, reg/m32
+ /// </summary>
+ public static unsafe uint MultiplyNoFlags(uint left, uint right, uint* high) => MultiplyNoFlags(left, right, high);
+ /// <summary>
+ /// unsigned __int64 _mulx_u64 (unsigned __int64 a, unsigned __int64 b, unsigned __int64* hi)
+ /// MULX r64a, r64b, reg/m64
+ /// </summary>
+ public static unsafe ulong MultiplyNoFlags(ulong left, ulong right, ulong* high) => MultiplyNoFlags(left, right, high);
+
+ /// <summary>
+ /// unsigned int _pdep_u32 (unsigned int a, unsigned int mask)
+ /// PDEP r32a, r32b, reg/m32
+ /// </summary>
+ public static uint ParallelBitDeposit(uint value, uint mask) => ParallelBitDeposit(value, mask);
+ /// <summary>
+ /// unsigned __int64 _pdep_u64 (unsigned __int64 a, unsigned __int64 mask)
+ /// PDEP r64a, r64b, reg/m64
+ /// </summary>
+ public static ulong ParallelBitDeposit(ulong value, ulong mask) => ParallelBitDeposit(value, mask);
+
+ /// <summary>
+ /// unsigned int _pext_u32 (unsigned int a, unsigned int mask)
+ /// PEXT r32a, r32b, reg/m32
+ /// </summary>
+ public static uint ParallelBitExtract(uint value, uint mask) => ParallelBitExtract(value, mask);
+ /// <summary>
+ /// unsigned __int64 _pext_u64 (unsigned __int64 a, unsigned __int64 mask)
+ /// PEXT r64a, r64b, reg/m64
+ /// </summary>
+ public static ulong ParallelBitExtract(ulong value, ulong mask) => ParallelBitExtract(value, mask);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Enums.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Enums.cs
new file mode 100644
index 000000000..cf8cd4370
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Enums.cs
@@ -0,0 +1,189 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.Intrinsics.X86
+{
+ public enum FloatComparisonMode : byte
+ {
+ /// <summary>
+ /// _CMP_EQ_OQ
+ /// </summary>
+ EqualOrderedNonSignaling = 0,
+
+ /// <summary>
+ /// _CMP_LT_OS
+ /// </summary>
+ LessThanOrderedSignaling = 1,
+
+ /// <summary>
+ /// _CMP_LE_OS
+ /// </summary>
+ LessThanOrEqualOrderedSignaling = 2,
+
+ /// <summary>
+ /// _CMP_UNORD_Q
+ /// </summary>
+ UnorderedNonSignaling = 3,
+
+ /// <summary>
+ /// _CMP_NEQ_UQ
+ /// </summary>
+ NotEqualUnorderedNonSignaling = 4,
+
+ /// <summary>
+ /// _CMP_NLT_US
+ /// </summary>
+ NotLessThanUnorderedSignaling = 5,
+
+ /// <summary>
+ /// _CMP_NLE_US
+ /// </summary>
+ NotLessThanOrEqualUnorderedSignaling = 6,
+
+ /// <summary>
+ /// _CMP_ORD_Q
+ /// </summary>
+ OrderedNonSignaling = 7,
+
+ /// <summary>
+ /// _CMP_EQ_UQ
+ /// </summary>
+ EqualUnorderedNonSignaling = 8,
+
+ /// <summary>
+ /// _CMP_NGE_US
+ /// </summary>
+ NotGreaterThanOrEqualUnorderedSignaling = 9,
+
+ /// <summary>
+ /// _CMP_NGT_US
+ /// </summary>
+ NotGreaterThanUnorderedSignaling = 10,
+
+ /// <summary>
+ /// _CMP_FALSE_OQ
+ /// </summary>
+ FalseOrderedNonSignaling = 11,
+
+ /// <summary>
+ /// _CMP_NEQ_OQ
+ /// </summary>
+ NotEqualOrderedNonSignaling = 12,
+
+ /// <summary>
+ /// _CMP_GE_OS
+ /// </summary>
+ GreaterThanOrEqualOrderedSignaling = 13,
+
+ /// <summary>
+ /// _CMP_GT_OS
+ /// </summary>
+ GreaterThanOrderedSignaling = 14,
+
+ /// <summary>
+ /// _CMP_TRUE_UQ
+ /// </summary>
+ TrueUnorderedNonSignaling = 15,
+
+ /// <summary>
+ /// _CMP_EQ_OS
+ /// </summary>
+ EqualOrderedSignaling = 16,
+
+ /// <summary>
+ /// _CMP_LT_OQ
+ /// </summary>
+ LessThanOrderedNonSignaling = 17,
+
+ /// <summary>
+ /// _CMP_LE_OQ
+ /// </summary>
+ LessThanOrEqualOrderedNonSignaling = 18,
+
+ /// <summary>
+ /// _CMP_UNORD_S
+ /// </summary>
+ UnorderedSignaling = 19,
+
+ /// <summary>
+ /// _CMP_NEQ_US
+ /// </summary>
+ NotEqualUnorderedSignaling = 20,
+
+ /// <summary>
+ /// _CMP_NLT_UQ
+ /// </summary>
+ NotLessThanUnorderedNonSignaling = 21,
+
+ /// <summary>
+ /// _CMP_NLE_UQ
+ /// </summary>
+ NotLessThanOrEqualUnorderedNonSignaling = 22,
+
+ /// <summary>
+ /// _CMP_ORD_S
+ /// </summary>
+ OrderedSignaling = 23,
+
+ /// <summary>
+ /// _CMP_EQ_US
+ /// </summary>
+ EqualUnorderedSignaling = 24,
+
+ /// <summary>
+ /// _CMP_NGE_UQ
+ /// </summary>
+ NotGreaterThanOrEqualUnorderedNonSignaling = 25,
+
+ /// <summary>
+ /// _CMP_NGT_UQ
+ /// </summary>
+ NotGreaterThanUnorderedNonSignaling = 26,
+
+ /// <summary>
+ /// _CMP_FALSE_OS
+ /// </summary>
+ FalseOrderedSignaling = 27,
+
+ /// <summary>
+ /// _CMP_NEQ_OS
+ /// </summary>
+ NotEqualOrderedSignaling = 28,
+
+ /// <summary>
+ /// _CMP_GE_OQ
+ /// </summary>
+ GreaterThanOrEqualOrderedNonSignaling = 29,
+
+ /// <summary>
+ /// _CMP_GT_OQ
+ /// </summary>
+ GreaterThanOrderedNonSignaling = 30,
+
+ /// <summary>
+ /// _CMP_TRUE_US
+ /// </summary>
+ TrueUnorderedSignaling = 31,
+ }
+
+ public enum StringComparisonMode : byte {
+ EqualAny = 0x00,
+ Ranges = 0x04,
+ EqualEach = 0x08,
+ EqualOrdered = 0x0c,
+ NegativePolarity = 0x10,
+ MaskedNegativePolarity = 0x30,
+ LeastSignificant = 0x00,
+ MostSignificant = 0x40,
+ }
+
+
+ public enum ResultsFlag : byte {
+ CFlag = 0,
+ NotCFlagAndNotZFlag = 1,
+ OFlag = 2,
+ SFlag = 3,
+ ZFlag = 4,
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Fma.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Fma.PlatformNotSupported.cs
new file mode 100644
index 000000000..91becab4d
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Fma.PlatformNotSupported.cs
@@ -0,0 +1,190 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel FMA hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Fma : Avx
+ {
+ internal Fma() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// __m128 _mm_fmadd_ps (__m128 a, __m128 b, __m128 c)
+ /// VFMADDPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplyAdd(Vector128<float> a, Vector128<float> b, Vector128<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_fmadd_pd (__m128d a, __m128d b, __m128d c)
+ /// VFMADDPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplyAdd(Vector128<double> a, Vector128<double> b, Vector128<double> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_fmadd_ps (__m256 a, __m256 b, __m256 c)
+ /// VFMADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplyAdd(Vector256<float> a, Vector256<float> b, Vector256<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_fmadd_pd (__m256d a, __m256d b, __m256d c)
+ /// VFMADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplyAdd(Vector256<double> a, Vector256<double> b, Vector256<double> c) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_fmadd_ss (__m128 a, __m128 b, __m128 c)
+ /// VFMADDSS xmm, xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MultiplyAddScalar(Vector128<float> a, Vector128<float> b, Vector128<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_fmadd_sd (__m128d a, __m128d b, __m128d c)
+ /// VFMADDSS xmm, xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MultiplyAddScalar(Vector128<double> a, Vector128<double> b, Vector128<double> c) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_fmaddsub_ps (__m128 a, __m128 b, __m128 c)
+ /// VFMADDSUBPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplyAddSubtract(Vector128<float> a, Vector128<float> b, Vector128<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_fmaddsub_pd (__m128d a, __m128d b, __m128d c)
+ /// VFMADDSUBPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplyAddSubtract(Vector128<double> a, Vector128<double> b, Vector128<double> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_fmaddsub_ps (__m256 a, __m256 b, __m256 c)
+ /// VFMADDSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplyAddSubtract(Vector256<float> a, Vector256<float> b, Vector256<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_fmaddsub_pd (__m256d a, __m256d b, __m256d c)
+ /// VFMADDSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplyAddSubtract(Vector256<double> a, Vector256<double> b, Vector256<double> c) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_fmsub_ps (__m128 a, __m128 b, __m128 c)
+ /// VFMSUBPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplySubtract(Vector128<float> a, Vector128<float> b, Vector128<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_fmsub_pd (__m128d a, __m128d b, __m128d c)
+ /// VFMSUBPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplySubtract(Vector128<double> a, Vector128<double> b, Vector128<double> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_fmsub_ps (__m256 a, __m256 b, __m256 c)
+ /// VFMSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplySubtract(Vector256<float> a, Vector256<float> b, Vector256<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_fmsub_pd (__m256d a, __m256d b, __m256d c)
+ /// VFMSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplySubtract(Vector256<double> a, Vector256<double> b, Vector256<double> c) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_fmsub_ss (__m128 a, __m128 b, __m128 c)
+ /// VFMSUBSS xmm, xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MultiplySubtractScalar(Vector128<float> a, Vector128<float> b, Vector128<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_fmsub_sd (__m128d a, __m128d b, __m128d c)
+ /// VFMSUBSD xmm, xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MultiplySubtractScalar(Vector128<double> a, Vector128<double> b, Vector128<double> c) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_fmsubadd_ps (__m128 a, __m128 b, __m128 c)
+ /// VFMSUBADDPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplySubtractAdd(Vector128<float> a, Vector128<float> b, Vector128<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_fmsubadd_pd (__m128d a, __m128d b, __m128d c)
+ /// VFMSUBADDPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplySubtractAdd(Vector128<double> a, Vector128<double> b, Vector128<double> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_fmsubadd_ps (__m256 a, __m256 b, __m256 c)
+ /// VFMSUBADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplySubtractAdd(Vector256<float> a, Vector256<float> b, Vector256<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_fmsubadd_pd (__m256d a, __m256d b, __m256d c)
+ /// VFMSUBADDPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplySubtractAdd(Vector256<double> a, Vector256<double> b, Vector256<double> c) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_fnmadd_ps (__m128 a, __m128 b, __m128 c)
+ /// VFNMADDPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplyAddNegated(Vector128<float> a, Vector128<float> b, Vector128<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_fnmadd_pd (__m128d a, __m128d b, __m128d c)
+ /// VFNMADDPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplyAddNegated(Vector128<double> a, Vector128<double> b, Vector128<double> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_fnmadd_ps (__m256 a, __m256 b, __m256 c)
+ /// VFNMADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplyAddNegated(Vector256<float> a, Vector256<float> b, Vector256<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_fnmadd_pd (__m256d a, __m256d b, __m256d c)
+ /// VFNMADDPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplyAddNegated(Vector256<double> a, Vector256<double> b, Vector256<double> c) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_fnmadd_ss (__m128 a, __m128 b, __m128 c)
+ /// VFNMADDSS xmm, xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MultiplyAddNegatedScalar(Vector128<float> a, Vector128<float> b, Vector128<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_fnmadd_sd (__m128d a, __m128d b, __m128d c)
+ /// VFNMADDSD xmm, xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MultiplyAddNegatedScalar(Vector128<double> a, Vector128<double> b, Vector128<double> c) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_fnmsub_ps (__m128 a, __m128 b, __m128 c)
+ /// VFNMSUBPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplySubtractNegated(Vector128<float> a, Vector128<float> b, Vector128<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_fnmsub_pd (__m128d a, __m128d b, __m128d c)
+ /// VFNMSUBPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplySubtractNegated(Vector128<double> a, Vector128<double> b, Vector128<double> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256 _mm256_fnmsub_ps (__m256 a, __m256 b, __m256 c)
+ /// VFNMSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplySubtractNegated(Vector256<float> a, Vector256<float> b, Vector256<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m256d _mm256_fnmsub_pd (__m256d a, __m256d b, __m256d c)
+ /// VFNMSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplySubtractNegated(Vector256<double> a, Vector256<double> b, Vector256<double> c) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_fnmsub_ss (__m128 a, __m128 b, __m128 c)
+ /// VFNMSUBSS xmm, xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MultiplySubtractNegatedScalar(Vector128<float> a, Vector128<float> b, Vector128<float> c) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_fnmsub_sd (__m128d a, __m128d b, __m128d c)
+ /// VFNMSUBSD xmm, xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MultiplySubtractNegatedScalar(Vector128<double> a, Vector128<double> b, Vector128<double> c) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Fma.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Fma.cs
new file mode 100644
index 000000000..88cb8d0cb
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Fma.cs
@@ -0,0 +1,190 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel FMA hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Fma : Avx
+ {
+ internal Fma() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// __m128 _mm_fmadd_ps (__m128 a, __m128 b, __m128 c)
+ /// VFMADDPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplyAdd(Vector128<float> a, Vector128<float> b, Vector128<float> c) => MultiplyAdd(a, b, c);
+ /// <summary>
+ /// __m128d _mm_fmadd_pd (__m128d a, __m128d b, __m128d c)
+ /// VFMADDPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplyAdd(Vector128<double> a, Vector128<double> b, Vector128<double> c) => MultiplyAdd(a, b, c);
+ /// <summary>
+ /// __m256 _mm256_fmadd_ps (__m256 a, __m256 b, __m256 c)
+ /// VFMADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplyAdd(Vector256<float> a, Vector256<float> b, Vector256<float> c) => MultiplyAdd(a, b, c);
+ /// <summary>
+ /// __m256d _mm256_fmadd_pd (__m256d a, __m256d b, __m256d c)
+ /// VFMADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplyAdd(Vector256<double> a, Vector256<double> b, Vector256<double> c) => MultiplyAdd(a, b, c);
+
+ /// <summary>
+ /// __m128 _mm_fmadd_ss (__m128 a, __m128 b, __m128 c)
+ /// VFMADDSS xmm, xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MultiplyAddScalar(Vector128<float> a, Vector128<float> b, Vector128<float> c) => MultiplyAddScalar(a, b, c);
+ /// <summary>
+ /// __m128d _mm_fmadd_sd (__m128d a, __m128d b, __m128d c)
+ /// VFMADDSS xmm, xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MultiplyAddScalar(Vector128<double> a, Vector128<double> b, Vector128<double> c) => MultiplyAddScalar(a, b, c);
+
+ /// <summary>
+ /// __m128 _mm_fmaddsub_ps (__m128 a, __m128 b, __m128 c)
+ /// VFMADDSUBPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplyAddSubtract(Vector128<float> a, Vector128<float> b, Vector128<float> c) => MultiplyAddSubtract(a, b, c);
+ /// <summary>
+ /// __m128d _mm_fmaddsub_pd (__m128d a, __m128d b, __m128d c)
+ /// VFMADDSUBPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplyAddSubtract(Vector128<double> a, Vector128<double> b, Vector128<double> c) => MultiplyAddSubtract(a, b, c);
+ /// <summary>
+ /// __m256 _mm256_fmaddsub_ps (__m256 a, __m256 b, __m256 c)
+ /// VFMADDSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplyAddSubtract(Vector256<float> a, Vector256<float> b, Vector256<float> c) => MultiplyAddSubtract(a, b, c);
+ /// <summary>
+ /// __m256d _mm256_fmaddsub_pd (__m256d a, __m256d b, __m256d c)
+ /// VFMADDSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplyAddSubtract(Vector256<double> a, Vector256<double> b, Vector256<double> c) => MultiplyAddSubtract(a, b, c);
+
+ /// <summary>
+ /// __m128 _mm_fmsub_ps (__m128 a, __m128 b, __m128 c)
+ /// VFMSUBPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplySubtract(Vector128<float> a, Vector128<float> b, Vector128<float> c) => MultiplySubtract(a, b, c);
+ /// <summary>
+ /// __m128d _mm_fmsub_pd (__m128d a, __m128d b, __m128d c)
+ /// VFMSUBPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplySubtract(Vector128<double> a, Vector128<double> b, Vector128<double> c) => MultiplySubtract(a, b, c);
+ /// <summary>
+ /// __m256 _mm256_fmsub_ps (__m256 a, __m256 b, __m256 c)
+ /// VFMSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplySubtract(Vector256<float> a, Vector256<float> b, Vector256<float> c) => MultiplySubtract(a, b, c);
+ /// <summary>
+ /// __m256d _mm256_fmsub_pd (__m256d a, __m256d b, __m256d c)
+ /// VFMSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplySubtract(Vector256<double> a, Vector256<double> b, Vector256<double> c) => MultiplySubtract(a, b, c);
+
+ /// <summary>
+ /// __m128 _mm_fmsub_ss (__m128 a, __m128 b, __m128 c)
+ /// VFMSUBSS xmm, xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MultiplySubtractScalar(Vector128<float> a, Vector128<float> b, Vector128<float> c) => MultiplySubtractScalar(a, b, c);
+ /// <summary>
+ /// __m128d _mm_fmsub_sd (__m128d a, __m128d b, __m128d c)
+ /// VFMSUBSD xmm, xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MultiplySubtractScalar(Vector128<double> a, Vector128<double> b, Vector128<double> c) => MultiplySubtractScalar(a, b, c);
+
+ /// <summary>
+ /// __m128 _mm_fmsubadd_ps (__m128 a, __m128 b, __m128 c)
+ /// VFMSUBADDPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplySubtractAdd(Vector128<float> a, Vector128<float> b, Vector128<float> c) => MultiplySubtractAdd(a, b, c);
+ /// <summary>
+ /// __m128d _mm_fmsubadd_pd (__m128d a, __m128d b, __m128d c)
+ /// VFMSUBADDPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplySubtractAdd(Vector128<double> a, Vector128<double> b, Vector128<double> c) => MultiplySubtractAdd(a, b, c);
+ /// <summary>
+ /// __m256 _mm256_fmsubadd_ps (__m256 a, __m256 b, __m256 c)
+ /// VFMSUBADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplySubtractAdd(Vector256<float> a, Vector256<float> b, Vector256<float> c) => MultiplySubtractAdd(a, b, c);
+ /// <summary>
+ /// __m256d _mm256_fmsubadd_pd (__m256d a, __m256d b, __m256d c)
+ /// VFMSUBADDPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplySubtractAdd(Vector256<double> a, Vector256<double> b, Vector256<double> c) => MultiplySubtractAdd(a, b, c);
+
+ /// <summary>
+ /// __m128 _mm_fnmadd_ps (__m128 a, __m128 b, __m128 c)
+ /// VFNMADDPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplyAddNegated(Vector128<float> a, Vector128<float> b, Vector128<float> c) => MultiplyAddNegated(a, b, c);
+ /// <summary>
+ /// __m128d _mm_fnmadd_pd (__m128d a, __m128d b, __m128d c)
+ /// VFNMADDPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplyAddNegated(Vector128<double> a, Vector128<double> b, Vector128<double> c) => MultiplyAddNegated(a, b, c);
+ /// <summary>
+ /// __m256 _mm256_fnmadd_ps (__m256 a, __m256 b, __m256 c)
+ /// VFNMADDPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplyAddNegated(Vector256<float> a, Vector256<float> b, Vector256<float> c) => MultiplyAddNegated(a, b, c);
+ /// <summary>
+ /// __m256d _mm256_fnmadd_pd (__m256d a, __m256d b, __m256d c)
+ /// VFNMADDPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplyAddNegated(Vector256<double> a, Vector256<double> b, Vector256<double> c) => MultiplyAddNegated(a, b, c);
+
+ /// <summary>
+ /// __m128 _mm_fnmadd_ss (__m128 a, __m128 b, __m128 c)
+ /// VFNMADDSS xmm, xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MultiplyAddNegatedScalar(Vector128<float> a, Vector128<float> b, Vector128<float> c) => MultiplyAddNegatedScalar(a, b, c);
+ /// <summary>
+ /// __m128d _mm_fnmadd_sd (__m128d a, __m128d b, __m128d c)
+ /// VFNMADDSD xmm, xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MultiplyAddNegatedScalar(Vector128<double> a, Vector128<double> b, Vector128<double> c) => MultiplyAddNegatedScalar(a, b, c);
+
+ /// <summary>
+ /// __m128 _mm_fnmsub_ps (__m128 a, __m128 b, __m128 c)
+ /// VFNMSUBPS xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MultiplySubtractNegated(Vector128<float> a, Vector128<float> b, Vector128<float> c) => MultiplySubtractNegated(a, b, c);
+ /// <summary>
+ /// __m128d _mm_fnmsub_pd (__m128d a, __m128d b, __m128d c)
+ /// VFNMSUBPD xmm, xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> MultiplySubtractNegated(Vector128<double> a, Vector128<double> b, Vector128<double> c) => MultiplySubtractNegated(a, b, c);
+ /// <summary>
+ /// __m256 _mm256_fnmsub_ps (__m256 a, __m256 b, __m256 c)
+ /// VFNMSUBPS ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<float> MultiplySubtractNegated(Vector256<float> a, Vector256<float> b, Vector256<float> c) => MultiplySubtractNegated(a, b, c);
+ /// <summary>
+ /// __m256d _mm256_fnmsub_pd (__m256d a, __m256d b, __m256d c)
+ /// VFNMSUBPD ymm, ymm, ymm/m256
+ /// </summary>
+ public static Vector256<double> MultiplySubtractNegated(Vector256<double> a, Vector256<double> b, Vector256<double> c) => MultiplySubtractNegated(a, b, c);
+
+ /// <summary>
+ /// __m128 _mm_fnmsub_ss (__m128 a, __m128 b, __m128 c)
+ /// VFNMSUBSS xmm, xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MultiplySubtractNegatedScalar(Vector128<float> a, Vector128<float> b, Vector128<float> c) => MultiplySubtractNegatedScalar(a, b, c);
+ /// <summary>
+ /// __m128d _mm_fnmsub_sd (__m128d a, __m128d b, __m128d c)
+ /// VFNMSUBSD xmm, xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MultiplySubtractNegatedScalar(Vector128<double> a, Vector128<double> b, Vector128<double> c) => MultiplySubtractNegatedScalar(a, b, c);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Lzcnt.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Lzcnt.PlatformNotSupported.cs
new file mode 100644
index 000000000..4f9276216
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Lzcnt.PlatformNotSupported.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel LZCNT hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Lzcnt
+ {
+ internal Lzcnt() { }
+
+ public static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// unsigned int _lzcnt_u32 (unsigned int a)
+ /// LZCNT reg, reg/m32
+ /// </summary>
+ public static uint LeadingZeroCount(uint value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _lzcnt_u64 (unsigned __int64 a)
+ /// LZCNT reg, reg/m64
+ /// </summary>
+ public static ulong LeadingZeroCount(ulong value) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Lzcnt.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Lzcnt.cs
new file mode 100644
index 000000000..5e9594f7d
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Lzcnt.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel LZCNT hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Lzcnt
+ {
+ internal Lzcnt() { }
+
+ public static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// unsigned int _lzcnt_u32 (unsigned int a)
+ /// LZCNT reg, reg/m32
+ /// </summary>
+ public static uint LeadingZeroCount(uint value) => LeadingZeroCount(value);
+ /// <summary>
+ /// unsigned __int64 _lzcnt_u64 (unsigned __int64 a)
+ /// LZCNT reg, reg/m64
+ /// </summary>
+ public static ulong LeadingZeroCount(ulong value) => LeadingZeroCount(value);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Pclmulqdq.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Pclmulqdq.PlatformNotSupported.cs
new file mode 100644
index 000000000..b79e50a2b
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Pclmulqdq.PlatformNotSupported.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel PCLMULQDQ hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Pclmulqdq : Sse2
+ {
+ internal Pclmulqdq() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// __m128i _mm_clmulepi64_si128 (__m128i a, __m128i b, const int imm8)
+ /// PCLMULQDQ xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<long> CarrylessMultiply(Vector128<long> left, Vector128<long> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_clmulepi64_si128 (__m128i a, __m128i b, const int imm8)
+ /// PCLMULQDQ xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ulong> CarrylessMultiply(Vector128<ulong> left, Vector128<ulong> right, byte control) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Pclmulqdq.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Pclmulqdq.cs
new file mode 100644
index 000000000..c108e65f0
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Pclmulqdq.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel PCLMULQDQ hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Pclmulqdq : Sse2
+ {
+ internal Pclmulqdq() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// __m128i _mm_clmulepi64_si128 (__m128i a, __m128i b, const int imm8)
+ /// PCLMULQDQ xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<long> CarrylessMultiply(Vector128<long> left, Vector128<long> right, byte control) => CarrylessMultiply(left, right, control);
+ /// <summary>
+ /// __m128i _mm_clmulepi64_si128 (__m128i a, __m128i b, const int imm8)
+ /// PCLMULQDQ xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ulong> CarrylessMultiply(Vector128<ulong> left, Vector128<ulong> right, byte control) => CarrylessMultiply(left, right, control);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Popcnt.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Popcnt.PlatformNotSupported.cs
new file mode 100644
index 000000000..bf045bd1f
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Popcnt.PlatformNotSupported.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel POPCNT hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Popcnt : Sse42
+ {
+ internal Popcnt() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// int _mm_popcnt_u32 (unsigned int a)
+ /// POPCNT reg, reg/m32
+ /// </summary>
+ public static uint PopCount(uint value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm_popcnt_u64 (unsigned __int64 a)
+ /// POPCNT reg64, reg/m64
+ /// </summary>
+ public static ulong PopCount(ulong value) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Popcnt.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Popcnt.cs
new file mode 100644
index 000000000..ba73eb234
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Popcnt.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel POPCNT hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Popcnt : Sse42
+ {
+ internal Popcnt() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// int _mm_popcnt_u32 (unsigned int a)
+ /// POPCNT reg, reg/m32
+ /// </summary>
+ public static uint PopCount(uint value) => PopCount(value);
+ /// <summary>
+ /// __int64 _mm_popcnt_u64 (unsigned __int64 a)
+ /// POPCNT reg, reg/m64
+ /// </summary>
+ public static ulong PopCount(ulong value) => PopCount(value);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.PlatformNotSupported.cs
new file mode 100644
index 000000000..77c63cee3
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.PlatformNotSupported.cs
@@ -0,0 +1,606 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSE hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Sse
+ {
+ internal Sse() { }
+
+ public static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// __m128 _mm_add_ps (__m128 a, __m128 b)
+ /// ADDPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Add(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_add_ss (__m128 a, __m128 b)
+ /// ADDSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> AddScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_and_ps (__m128 a, __m128 b)
+ /// ANDPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> And(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_andnot_ps (__m128 a, __m128 b)
+ /// ANDNPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> AndNot(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpeq_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(0)
+ /// </summary>
+ public static Vector128<float> CompareEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comieq_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareEqualOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomieq_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpeq_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(0)
+ /// </summary>
+ public static Vector128<float> CompareEqualScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpgt_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(6)
+ /// </summary>
+ public static Vector128<float> CompareGreaterThan(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comigt_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareGreaterThanOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomigt_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareGreaterThanUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpgt_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(6)
+ /// </summary>
+ public static Vector128<float> CompareGreaterThanScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpge_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(5)
+ /// </summary>
+ public static Vector128<float> CompareGreaterThanOrEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comige_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareGreaterThanOrEqualOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomige_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareGreaterThanOrEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpge_ss (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m32, imm8(5)
+ /// </summary>
+ public static Vector128<float> CompareGreaterThanOrEqualScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmplt_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(1)
+ /// </summary>
+ public static Vector128<float> CompareLessThan(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comilt_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareLessThanOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomilt_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareLessThanUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmplt_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(1)
+ /// </summary>
+ public static Vector128<float> CompareLessThanScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmple_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(2)
+ /// </summary>
+ public static Vector128<float> CompareLessThanOrEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comile_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareLessThanOrEqualOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomile_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareLessThanOrEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmple_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(2)
+ /// </summary>
+ public static Vector128<float> CompareLessThanOrEqualScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpneq_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<float> CompareNotEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comineq_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareNotEqualOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomineq_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareNotEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpneq_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(4)
+ /// </summary>
+ public static Vector128<float> CompareNotEqualScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpngt_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(2)
+ /// </summary>
+ public static Vector128<float> CompareNotGreaterThan(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpngt_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(2)
+ /// </summary>
+ public static Vector128<float> CompareNotGreaterThanScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpnge_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(1)
+ /// </summary>
+ public static Vector128<float> CompareNotGreaterThanOrEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpnge_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(1)
+ /// </summary>
+ public static Vector128<float> CompareNotGreaterThanOrEqualScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpnlt_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(5)
+ /// </summary>
+ public static Vector128<float> CompareNotLessThan(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpnlt_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(5)
+ /// </summary>
+ public static Vector128<float> CompareNotLessThanScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpnle_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(6)
+ /// </summary>
+ public static Vector128<float> CompareNotLessThanOrEqual(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpnle_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(6)
+ /// </summary>
+ public static Vector128<float> CompareNotLessThanOrEqualScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpord_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(7)
+ /// </summary>
+ public static Vector128<float> CompareOrdered(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpord_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(7)
+ /// </summary>
+ public static Vector128<float> CompareOrderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpunord_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(3)
+ /// </summary>
+ public static Vector128<float> CompareUnordered(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cmpunord_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(3)
+ /// </summary>
+ public static Vector128<float> CompareUnorderedScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cvtss_si32 (__m128 a)
+ /// CVTSS2SI r32, xmm/m32
+ /// </summary>
+ public static int ConvertToInt32(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm_cvtss_si64 (__m128 a)
+ /// CVTSS2SI r64, xmm/m32
+ /// </summary>
+ public static long ConvertToInt64(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// float _mm_cvtss_f32 (__m128 a)
+ /// HELPER: MOVSS
+ /// </summary>
+ public static float ConvertToSingle(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_cvtsi32_ss (__m128 a, int b)
+ /// CVTSI2SS xmm, reg/m32
+ /// </summary>
+ public static Vector128<float> ConvertScalarToVector128Single(Vector128<float> upper, int value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_cvtsi64_ss (__m128 a, __int64 b)
+ /// CVTSI2SS xmm, reg/m64
+ /// </summary>
+ public static Vector128<float> ConvertScalarToVector128Single(Vector128<float> upper, long value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cvttss_si32 (__m128 a)
+ /// CVTTSS2SI r32, xmm/m32
+ /// </summary>
+ public static int ConvertToInt32WithTruncation(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm_cvttss_si64 (__m128 a)
+ /// CVTTSS2SI r64, xmm/m32
+ /// </summary>
+ public static long ConvertToInt64WithTruncation(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_div_ps (__m128 a, __m128 b)
+ /// DIVPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Divide(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_div_ss (__m128 a, __m128 b)
+ /// DIVSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> DivideScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_loadu_ps (float const* mem_address)
+ /// MOVUPS xmm, m128
+ /// </summary>
+ public static unsafe Vector128<float> LoadVector128(float* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_load_ss (float const* mem_address)
+ /// MOVSS xmm, m32
+ /// </summary>
+ public static unsafe Vector128<float> LoadScalarVector128(float* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_load_ps (float const* mem_address)
+ /// MOVAPS xmm, m128
+ /// </summary>
+ public static unsafe Vector128<float> LoadAlignedVector128(float* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_loadh_pi (__m128 a, __m64 const* mem_addr)
+ /// MOVHPS xmm, m64
+ /// </summary>
+ public static unsafe Vector128<float> LoadHigh(Vector128<float> lower, float* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_loadl_pi (__m128 a, __m64 const* mem_addr)
+ /// MOVLPS xmm, m64
+ /// </summary>
+ public static unsafe Vector128<float> LoadLow(Vector128<float> upper, float* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_max_ps (__m128 a, __m128 b)
+ /// MAXPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Max(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_max_ss (__m128 a, __m128 b)
+ /// MAXSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MaxScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_min_ps (__m128 a, __m128 b)
+ /// MINPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Min(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_min_ss (__m128 a, __m128 b)
+ /// MINSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MinScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_move_ss (__m128 a, __m128 b)
+ /// MOVSS xmm, xmm
+ /// </summary>
+ public static Vector128<float> MoveScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_movehl_ps (__m128 a, __m128 b)
+ /// MOVHLPS xmm, xmm
+ /// </summary>
+ public static Vector128<float> MoveHighToLow(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_movelh_ps (__m128 a, __m128 b)
+ /// MOVLHPS xmm, xmm
+ /// </summary>
+ public static Vector128<float> MoveLowToHigh(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_movemask_ps (__m128 a)
+ /// MOVMSKPS reg, xmm
+ /// </summary>
+ public static int MoveMask(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_mul_ps (__m128 a, __m128 b)
+ /// MULPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Multiply(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_mul_ss (__m128 a, __m128 b)
+ /// MULPS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MultiplyScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_prefetch(char* p, int i)
+ /// PREFETCHT0 m8
+ /// </summary>
+ public static unsafe void Prefetch0(void* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_prefetch(char* p, int i)
+ /// PREFETCHT1 m8
+ /// </summary>
+ public static unsafe void Prefetch1(void* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_prefetch(char* p, int i)
+ /// PREFETCHT2 m8
+ /// </summary>
+ public static unsafe void Prefetch2(void* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_prefetch(char* p, int i)
+ /// PREFETCHNTA m8
+ /// </summary>
+ public static unsafe void PrefetchNonTemporal(void* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_or_ps (__m128 a, __m128 b)
+ /// ORPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Or(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_rcp_ps (__m128 a)
+ /// RCPPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Reciprocal(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_rcp_ss (__m128 a)
+ /// RCPSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> ReciprocalScalar(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_rcp_ss (__m128 a, __m128 b)
+ /// RCPSS xmm, xmm/m32
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector128<float> ReciprocalScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_rsqrt_ps (__m128 a)
+ /// RSQRTPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> ReciprocalSqrt(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_rsqrt_ss (__m128 a)
+ /// RSQRTSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> ReciprocalSqrtScalar(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_rsqrt_ss (__m128 a, __m128 b)
+ /// RSQRTSS xmm, xmm/m32
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector128<float> ReciprocalSqrtScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_set_ps (float e3, float e2, float e1, float e0)
+ /// </summary>
+ public static Vector128<float> SetVector128(float e3, float e2, float e1, float e0) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_set_ss (float a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<float> SetScalarVector128(float value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_set1_ps (float a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<float> SetAllVector128(float value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_setzero_ps (void)
+ /// HELPER - XORPS
+ /// </summary>
+ public static Vector128<float> SetZeroVector128() { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_castpd_ps (__m128d a)
+ /// HELPER - No Codegen
+ /// __m128i _mm_castpd_si128 (__m128d a)
+ /// HELPER - No Codegen
+ /// __m128d _mm_castps_pd (__m128 a)
+ /// HELPER - No Codegen
+ /// __m128i _mm_castps_si128 (__m128 a)
+ /// HELPER - No Codegen
+ /// __m128d _mm_castsi128_pd (__m128i a)
+ /// HELPER - No Codegen
+ /// __m128 _mm_castsi128_ps (__m128i a)
+ /// HELPER - No Codegen
+ /// </summary>
+ public static Vector128<U> StaticCast<T, U>(Vector128<T> value) where T : struct where U : struct { throw new PlatformNotSupportedException(); }
+
+
+ /// <summary>
+ /// __m128 _mm_shuffle_ps (__m128 a, __m128 b, unsigned int control)
+ /// SHUFPS xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<float> Shuffle(Vector128<float> left, Vector128<float> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_sqrt_ps (__m128 a)
+ /// SQRTPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Sqrt(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_sqrt_ss (__m128 a)
+ /// SQRTSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> SqrtScalar(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_sqrt_ss (__m128 a, __m128 b)
+ /// SQRTSS xmm, xmm/m32
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector128<float> SqrtScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_store_ps (float* mem_addr, __m128 a)
+ /// MOVAPS m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(float* address, Vector128<float> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_stream_ps (float* mem_addr, __m128 a)
+ /// MOVNTPS m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(float* address, Vector128<float> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_storeu_ps (float* mem_addr, __m128 a)
+ /// MOVUPS m128, xmm
+ /// </summary>
+ public static unsafe void Store(float* address, Vector128<float> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_sfence(void)
+ /// SFENCE
+ /// </summary>
+ public static void StoreFence() { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_store_ss (float* mem_addr, __m128 a)
+ /// MOVSS m32, xmm
+ /// </summary>
+ public static unsafe void StoreScalar(float* address, Vector128<float> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_storeh_pi (__m64* mem_addr, __m128 a)
+ /// MOVHPS m64, xmm
+ /// </summary>
+ public static unsafe void StoreHigh(float* address, Vector128<float> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_storel_pi (__m64* mem_addr, __m128 a)
+ /// MOVLPS m64, xmm
+ /// </summary>
+ public static unsafe void StoreLow(float* address, Vector128<float> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_sub_ps (__m128d a, __m128d b)
+ /// SUBPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Subtract(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_sub_ss (__m128 a, __m128 b)
+ /// SUBSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> SubtractScalar(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_unpackhi_ps (__m128 a, __m128 b)
+ /// UNPCKHPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> UnpackHigh(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_unpacklo_ps (__m128 a, __m128 b)
+ /// UNPCKLPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> UnpackLow(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_xor_ps (__m128 a, __m128 b)
+ /// XORPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Xor(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.cs
new file mode 100644
index 000000000..3b01aee70
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse.cs
@@ -0,0 +1,631 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSE hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Sse
+ {
+ internal Sse() { }
+
+ public static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// __m128 _mm_add_ps (__m128 a, __m128 b)
+ /// ADDPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Add(Vector128<float> left, Vector128<float> right) => Add(left, right);
+
+ /// <summary>
+ /// __m128 _mm_add_ss (__m128 a, __m128 b)
+ /// ADDSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> AddScalar(Vector128<float> left, Vector128<float> right) => AddScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_and_ps (__m128 a, __m128 b)
+ /// ANDPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> And(Vector128<float> left, Vector128<float> right) => And(left, right);
+
+ /// <summary>
+ /// __m128 _mm_andnot_ps (__m128 a, __m128 b)
+ /// ANDNPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> AndNot(Vector128<float> left, Vector128<float> right) => AndNot(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpeq_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(0)
+ /// </summary>
+ public static Vector128<float> CompareEqual(Vector128<float> left, Vector128<float> right) => CompareEqual(left, right);
+
+ /// <summary>
+ /// int _mm_comieq_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareEqualOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareEqualOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomieq_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareEqualUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpeq_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(0)
+ /// </summary>
+ public static Vector128<float> CompareEqualScalar(Vector128<float> left, Vector128<float> right) => CompareEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpgt_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(6)
+ /// </summary>
+ public static Vector128<float> CompareGreaterThan(Vector128<float> left, Vector128<float> right) => CompareGreaterThan(left, right);
+
+ /// <summary>
+ /// int _mm_comigt_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareGreaterThanOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareGreaterThanOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomigt_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareGreaterThanUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareGreaterThanUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpgt_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(6)
+ /// </summary>
+ public static Vector128<float> CompareGreaterThanScalar(Vector128<float> left, Vector128<float> right) => CompareGreaterThanScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpge_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(5)
+ /// </summary>
+ public static Vector128<float> CompareGreaterThanOrEqual(Vector128<float> left, Vector128<float> right) => CompareGreaterThanOrEqual(left, right);
+
+ /// <summary>
+ /// int _mm_comige_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareGreaterThanOrEqualOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareGreaterThanOrEqualOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomige_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareGreaterThanOrEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareGreaterThanOrEqualUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpge_ss (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m32, imm8(5)
+ /// </summary>
+ public static Vector128<float> CompareGreaterThanOrEqualScalar(Vector128<float> left, Vector128<float> right) => CompareGreaterThanOrEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmplt_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(1)
+ /// </summary>
+ public static Vector128<float> CompareLessThan(Vector128<float> left, Vector128<float> right) => CompareLessThan(left, right);
+
+ /// <summary>
+ /// int _mm_comilt_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareLessThanOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareLessThanOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomilt_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareLessThanUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareLessThanUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmplt_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(1)
+ /// </summary>
+ public static Vector128<float> CompareLessThanScalar(Vector128<float> left, Vector128<float> right) => CompareLessThanScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmple_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(2)
+ /// </summary>
+ public static Vector128<float> CompareLessThanOrEqual(Vector128<float> left, Vector128<float> right) => CompareLessThanOrEqual(left, right);
+
+ /// <summary>
+ /// int _mm_comile_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareLessThanOrEqualOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareLessThanOrEqualOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomile_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareLessThanOrEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareLessThanOrEqualUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmple_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(2)
+ /// </summary>
+ public static Vector128<float> CompareLessThanOrEqualScalar(Vector128<float> left, Vector128<float> right) => CompareLessThanOrEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpneq_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<float> CompareNotEqual(Vector128<float> left, Vector128<float> right) => CompareNotEqual(left, right);
+
+ /// <summary>
+ /// int _mm_comineq_ss (__m128 a, __m128 b)
+ /// COMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareNotEqualOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareNotEqualOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomineq_ss (__m128 a, __m128 b)
+ /// UCOMISS xmm, xmm/m32
+ /// </summary>
+ public static bool CompareNotEqualUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareNotEqualUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpneq_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(4)
+ /// </summary>
+ public static Vector128<float> CompareNotEqualScalar(Vector128<float> left, Vector128<float> right) => CompareNotEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpngt_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(2)
+ /// </summary>
+ public static Vector128<float> CompareNotGreaterThan(Vector128<float> left, Vector128<float> right) => CompareNotGreaterThan(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpngt_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(2)
+ /// </summary>
+ public static Vector128<float> CompareNotGreaterThanScalar(Vector128<float> left, Vector128<float> right) => CompareNotGreaterThanScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpnge_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(1)
+ /// </summary>
+ public static Vector128<float> CompareNotGreaterThanOrEqual(Vector128<float> left, Vector128<float> right) => CompareNotGreaterThanOrEqual(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpnge_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(1)
+ /// </summary>
+ public static Vector128<float> CompareNotGreaterThanOrEqualScalar(Vector128<float> left, Vector128<float> right) => CompareNotGreaterThanOrEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpnlt_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(5)
+ /// </summary>
+ public static Vector128<float> CompareNotLessThan(Vector128<float> left, Vector128<float> right) => CompareNotLessThan(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpnlt_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(5)
+ /// </summary>
+ public static Vector128<float> CompareNotLessThanScalar(Vector128<float> left, Vector128<float> right) => CompareNotLessThanScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpnle_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(6)
+ /// </summary>
+ public static Vector128<float> CompareNotLessThanOrEqual(Vector128<float> left, Vector128<float> right) => CompareNotLessThanOrEqual(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpnle_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(6)
+ /// </summary>
+ public static Vector128<float> CompareNotLessThanOrEqualScalar(Vector128<float> left, Vector128<float> right) => CompareNotLessThanOrEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpord_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(7)
+ /// </summary>
+ public static Vector128<float> CompareOrdered(Vector128<float> left, Vector128<float> right) => CompareOrdered(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpord_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(7)
+ /// </summary>
+ public static Vector128<float> CompareOrderedScalar(Vector128<float> left, Vector128<float> right) => CompareOrderedScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpunord_ps (__m128 a, __m128 b)
+ /// CMPPS xmm, xmm/m128, imm8(3)
+ /// </summary>
+ public static Vector128<float> CompareUnordered(Vector128<float> left, Vector128<float> right) => CompareUnordered(left, right);
+
+ /// <summary>
+ /// __m128 _mm_cmpunord_ss (__m128 a, __m128 b)
+ /// CMPSS xmm, xmm/m32, imm8(3)
+ /// </summary>
+ public static Vector128<float> CompareUnorderedScalar(Vector128<float> left, Vector128<float> right) => CompareUnorderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_cvtss_si32 (__m128 a)
+ /// CVTSS2SI r32, xmm/m32
+ /// </summary>
+ public static int ConvertToInt32(Vector128<float> value) => ConvertToInt32(value);
+ /// <summary>
+ /// __int64 _mm_cvtss_si64 (__m128 a)
+ /// CVTSS2SI r64, xmm/m32
+ /// </summary>
+ public static long ConvertToInt64(Vector128<float> value) => ConvertToInt64(value);
+
+ /// <summary>
+ /// float _mm_cvtss_f32 (__m128 a)
+ /// HELPER: MOVSS
+ /// </summary>
+ public static float ConvertToSingle(Vector128<float> value) => ConvertToSingle(value);
+
+ /// <summary>
+ /// __m128 _mm_cvtsi32_ss (__m128 a, int b)
+ /// CVTSI2SS xmm, reg/m32
+ /// </summary>
+ public static Vector128<float> ConvertScalarToVector128Single(Vector128<float> upper, int value) => ConvertScalarToVector128Single(upper, value);
+ /// <summary>
+ /// __m128 _mm_cvtsi64_ss (__m128 a, __int64 b)
+ /// CVTSI2SS xmm, reg/m64
+ /// </summary>
+ public static Vector128<float> ConvertScalarToVector128Single(Vector128<float> upper, long value) => ConvertScalarToVector128Single(upper, value);
+
+ /// <summary>
+ /// int _mm_cvttss_si32 (__m128 a)
+ /// CVTTSS2SI r32, xmm/m32
+ /// </summary>
+ public static int ConvertToInt32WithTruncation(Vector128<float> value) => ConvertToInt32WithTruncation(value);
+ /// <summary>
+ /// __int64 _mm_cvttss_si64 (__m128 a)
+ /// CVTTSS2SI r64, xmm/m32
+ /// </summary>
+ public static long ConvertToInt64WithTruncation(Vector128<float> value) => ConvertToInt64WithTruncation(value);
+
+ /// <summary>
+ /// __m128 _mm_div_ps (__m128 a, __m128 b)
+ /// DIVPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Divide(Vector128<float> left, Vector128<float> right) => Divide(left, right);
+
+ /// <summary>
+ /// __m128 _mm_div_ss (__m128 a, __m128 b)
+ /// DIVSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> DivideScalar(Vector128<float> left, Vector128<float> right) => DivideScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_loadu_ps (float const* mem_address)
+ /// MOVUPS xmm, m128
+ /// </summary>
+ public static unsafe Vector128<float> LoadVector128(float* address) => LoadVector128(address);
+
+ /// <summary>
+ /// __m128 _mm_load_ss (float const* mem_address)
+ /// MOVSS xmm, m32
+ /// </summary>
+ public static unsafe Vector128<float> LoadScalarVector128(float* address) => LoadScalarVector128(address);
+
+ /// <summary>
+ /// __m128 _mm_load_ps (float const* mem_address)
+ /// MOVAPS xmm, m128
+ /// </summary>
+ public static unsafe Vector128<float> LoadAlignedVector128(float* address) => LoadAlignedVector128(address);
+
+ /// <summary>
+ /// __m128 _mm_loadh_pi (__m128 a, __m64 const* mem_addr)
+ /// MOVHPS xmm, m64
+ /// </summary>
+ public static unsafe Vector128<float> LoadHigh(Vector128<float> lower, float* address) => LoadHigh(lower, address);
+
+ /// <summary>
+ /// __m128 _mm_loadl_pi (__m128 a, __m64 const* mem_addr)
+ /// MOVLPS xmm, m64
+ /// </summary>
+ public static unsafe Vector128<float> LoadLow(Vector128<float> upper, float* address) => LoadLow(upper, address);
+
+ /// <summary>
+ /// __m128 _mm_max_ps (__m128 a, __m128 b)
+ /// MAXPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Max(Vector128<float> left, Vector128<float> right) => Max(left, right);
+
+ /// <summary>
+ /// __m128 _mm_max_ss (__m128 a, __m128 b)
+ /// MAXSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MaxScalar(Vector128<float> left, Vector128<float> right) => MaxScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_min_ps (__m128 a, __m128 b)
+ /// MINPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Min(Vector128<float> left, Vector128<float> right) => Min(left, right);
+
+ /// <summary>
+ /// __m128 _mm_min_ss (__m128 a, __m128 b)
+ /// MINSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MinScalar(Vector128<float> left, Vector128<float> right) => MinScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_move_ss (__m128 a, __m128 b)
+ /// MOVSS xmm, xmm
+ /// </summary>
+ public static Vector128<float> MoveScalar(Vector128<float> upper, Vector128<float> value) => MoveScalar(upper, value);
+
+ /// <summary>
+ /// __m128 _mm_movehl_ps (__m128 a, __m128 b)
+ /// MOVHLPS xmm, xmm
+ /// </summary>
+ public static Vector128<float> MoveHighToLow(Vector128<float> left, Vector128<float> right) => MoveHighToLow(left, right);
+
+ /// <summary>
+ /// __m128 _mm_movelh_ps (__m128 a, __m128 b)
+ /// MOVLHPS xmm, xmm
+ /// </summary>
+ public static Vector128<float> MoveLowToHigh(Vector128<float> left, Vector128<float> right) => MoveLowToHigh(left, right);
+
+ /// <summary>
+ /// int _mm_movemask_ps (__m128 a)
+ /// MOVMSKPS reg, xmm
+ /// </summary>
+ public static int MoveMask(Vector128<float> value) => MoveMask(value);
+
+ /// <summary>
+ /// __m128 _mm_mul_ps (__m128 a, __m128 b)
+ /// MULPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Multiply(Vector128<float> left, Vector128<float> right) => Multiply(left, right);
+
+ /// <summary>
+ /// __m128 _mm_mul_ss (__m128 a, __m128 b)
+ /// MULPS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> MultiplyScalar(Vector128<float> left, Vector128<float> right) => MultiplyScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_or_ps (__m128 a, __m128 b)
+ /// ORPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Or(Vector128<float> left, Vector128<float> right) => Or(left, right);
+
+ /// <summary>
+ /// void _mm_prefetch(char* p, int i)
+ /// PREFETCHT0 m8
+ /// </summary>
+ public static unsafe void Prefetch0(void* address) => Prefetch0(address);
+
+ /// <summary>
+ /// void _mm_prefetch(char* p, int i)
+ /// PREFETCHT1 m8
+ /// </summary>
+ public static unsafe void Prefetch1(void* address) => Prefetch1(address);
+
+ /// <summary>
+ /// void _mm_prefetch(char* p, int i)
+ /// PREFETCHT2 m8
+ /// </summary>
+ public static unsafe void Prefetch2(void* address) => Prefetch2(address);
+
+ /// <summary>
+ /// void _mm_prefetch(char* p, int i)
+ /// PREFETCHNTA m8
+ /// </summary>
+ public static unsafe void PrefetchNonTemporal(void* address) => PrefetchNonTemporal(address);
+
+ /// <summary>
+ /// __m128 _mm_rcp_ps (__m128 a)
+ /// RCPPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Reciprocal(Vector128<float> value) => Reciprocal(value);
+
+ /// <summary>
+ /// __m128 _mm_rcp_ss (__m128 a)
+ /// RCPSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> ReciprocalScalar(Vector128<float> value) => ReciprocalScalar(value);
+
+ /// <summary>
+ /// __m128 _mm_rcp_ss (__m128 a, __m128 b)
+ /// RCPSS xmm, xmm/m32
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector128<float> ReciprocalScalar(Vector128<float> upper, Vector128<float> value) => ReciprocalScalar(upper, value);
+
+ /// <summary>
+ /// __m128 _mm_rsqrt_ps (__m128 a)
+ /// RSQRTPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> ReciprocalSqrt(Vector128<float> value) => ReciprocalSqrt(value);
+
+ /// <summary>
+ /// __m128 _mm_rsqrt_ss (__m128 a)
+ /// RSQRTSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> ReciprocalSqrtScalar(Vector128<float> value) => ReciprocalSqrtScalar(value);
+
+ /// <summary>
+ /// __m128 _mm_rsqrt_ss (__m128 a, __m128 b)
+ /// RSQRTSS xmm, xmm/m32
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector128<float> ReciprocalSqrtScalar(Vector128<float> upper, Vector128<float> value) => ReciprocalSqrtScalar(upper, value);
+
+ /// <summary>
+ /// __m128 _mm_set1_ps (float a)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<float> SetAllVector128(float value)
+ {
+ // Zero vector and load value et index 0
+ Vector128<float> vector = SetScalarVector128(value);
+ // Create { vl vl vl vl } and return result
+ return Shuffle(vector, vector, 0);
+ }
+
+ /// <summary>
+ /// __m128 _mm_set_ss (float a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<float> SetScalarVector128(float value) => SetScalarVector128(value);
+
+ /// <summary>
+ /// __m128 _mm_set_ps (float e3, float e2, float e1, float e0)
+ /// </summary>
+ public static unsafe Vector128<float> SetVector128(float e3, float e2, float e1, float e0)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load e2 et index 0
+ Vector128<float> e2Vector = SetScalarVector128(e2);
+ Vector128<float> e1Vector = SetScalarVector128(e1);
+ Vector128<float> e0Vector = SetScalarVector128(e0);
+ // Create { -- -- e2 e0 }
+ e0Vector = UnpackLow(e0Vector, e2Vector);
+ e2Vector = SetScalarVector128(e3);
+ // Create { -- -- e3 e1 }
+ e1Vector = UnpackLow(e1Vector, e2Vector);
+ // Create { e3 e2 e1 e0 } and return result
+ return UnpackLow(e0Vector, e1Vector);
+ }
+
+ /// <summary>
+ /// __m128d _mm_setzero_ps (void)
+ /// HELPER - XORPS
+ /// </summary>
+ public static Vector128<float> SetZeroVector128() => SetZeroVector128();
+
+ /// <summary>
+ /// __m128 _mm_castpd_ps (__m128d a)
+ /// HELPER - No Codegen
+ /// __m128i _mm_castpd_si128 (__m128d a)
+ /// HELPER - No Codegen
+ /// __m128d _mm_castps_pd (__m128 a)
+ /// HELPER - No Codegen
+ /// __m128i _mm_castps_si128 (__m128 a)
+ /// HELPER - No Codegen
+ /// __m128d _mm_castsi128_pd (__m128i a)
+ /// HELPER - No Codegen
+ /// __m128 _mm_castsi128_ps (__m128i a)
+ /// HELPER - No Codegen
+ /// </summary>
+ public static Vector128<U> StaticCast<T, U>(Vector128<T> value) where T : struct where U : struct
+ {
+ return StaticCast<T, U>(value);
+ }
+
+ /// <summary>
+ /// __m128 _mm_shuffle_ps (__m128 a, __m128 b, unsigned int control)
+ /// SHUFPS xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<float> Shuffle(Vector128<float> left, Vector128<float> right, byte control) => Shuffle(left, right, control);
+
+ /// <summary>
+ /// __m128 _mm_sqrt_ps (__m128 a)
+ /// SQRTPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Sqrt(Vector128<float> value) => Sqrt(value);
+
+ /// <summary>
+ /// __m128 _mm_sqrt_ss (__m128 a)
+ /// SQRTSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> SqrtScalar(Vector128<float> value) => SqrtScalar(value);
+
+ /// <summary>
+ /// __m128 _mm_sqrt_ss (__m128 a, __m128 b)
+ /// SQRTSS xmm, xmm/m32
+ /// The above native signature does not exist. We provide this additional overload for consistency with the other scalar APIs.
+ /// </summary>
+ public static Vector128<float> SqrtScalar(Vector128<float> upper, Vector128<float> value) => SqrtScalar(upper, value);
+
+ /// <summary>
+ /// void _mm_store_ps (float* mem_addr, __m128 a)
+ /// MOVAPS m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(float* address, Vector128<float> source) => StoreAligned(address, source);
+
+ /// <summary>
+ /// void _mm_stream_ps (float* mem_addr, __m128 a)
+ /// MOVNTPS m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(float* address, Vector128<float> source) => StoreAlignedNonTemporal(address, source);
+
+ /// <summary>
+ /// void _mm_storeu_ps (float* mem_addr, __m128 a)
+ /// MOVUPS m128, xmm
+ /// </summary>
+ public static unsafe void Store(float* address, Vector128<float> source) => Store(address, source);
+
+ /// <summary>
+ /// void _mm_sfence(void)
+ /// SFENCE
+ /// </summary>
+ public static void StoreFence() => StoreFence();
+
+ /// <summary>
+ /// void _mm_store_ss (float* mem_addr, __m128 a)
+ /// MOVSS m32, xmm
+ /// </summary>
+ public static unsafe void StoreScalar(float* address, Vector128<float> source) => StoreScalar(address, source);
+
+ /// <summary>
+ /// void _mm_storeh_pi (__m64* mem_addr, __m128 a)
+ /// MOVHPS m64, xmm
+ /// </summary>
+ public static unsafe void StoreHigh(float* address, Vector128<float> source) => StoreHigh(address, source);
+
+ /// <summary>
+ /// void _mm_storel_pi (__m64* mem_addr, __m128 a)
+ /// MOVLPS m64, xmm
+ /// </summary>
+ public static unsafe void StoreLow(float* address, Vector128<float> source) => StoreLow(address, source);
+
+ /// <summary>
+ /// __m128d _mm_sub_ps (__m128d a, __m128d b)
+ /// SUBPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Subtract(Vector128<float> left, Vector128<float> right) => Subtract(left, right);
+
+ /// <summary>
+ /// __m128 _mm_sub_ss (__m128 a, __m128 b)
+ /// SUBSS xmm, xmm/m32
+ /// </summary>
+ public static Vector128<float> SubtractScalar(Vector128<float> left, Vector128<float> right) => SubtractScalar(left, right);
+
+ /// <summary>
+ /// __m128 _mm_unpackhi_ps (__m128 a, __m128 b)
+ /// UNPCKHPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> UnpackHigh(Vector128<float> left, Vector128<float> right) => UnpackHigh(left, right);
+
+ /// <summary>
+ /// __m128 _mm_unpacklo_ps (__m128 a, __m128 b)
+ /// UNPCKLPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> UnpackLow(Vector128<float> left, Vector128<float> right) => UnpackLow(left, right);
+
+ /// <summary>
+ /// __m128 _mm_xor_ps (__m128 a, __m128 b)
+ /// XORPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> Xor(Vector128<float> left, Vector128<float> right) => Xor(left, right);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.PlatformNotSupported.cs
new file mode 100644
index 000000000..0f9b1959b
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.PlatformNotSupported.cs
@@ -0,0 +1,1763 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSE2 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Sse2 : Sse
+ {
+ internal Sse2() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// __m128i _mm_add_epi8 (__m128i a, __m128i b)
+ /// PADDB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Add(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_add_epi8 (__m128i a, __m128i b)
+ /// PADDB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Add(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_add_epi16 (__m128i a, __m128i b)
+ /// PADDW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Add(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_add_epi16 (__m128i a, __m128i b)
+ /// PADDW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Add(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_add_epi32 (__m128i a, __m128i b)
+ /// PADDD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Add(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_add_epi32 (__m128i a, __m128i b)
+ /// PADDD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Add(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_add_epi64 (__m128i a, __m128i b)
+ /// PADDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> Add(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_add_epi64 (__m128i a, __m128i b)
+ /// PADDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> Add(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_add_pd (__m128d a, __m128d b)
+ /// ADDPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Add(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_add_sd (__m128d a, __m128d b)
+ /// ADDSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> AddScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_adds_epi8 (__m128i a, __m128i b)
+ /// PADDSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> AddSaturate(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_adds_epu8 (__m128i a, __m128i b)
+ /// PADDUSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> AddSaturate(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_adds_epi16 (__m128i a, __m128i b)
+ /// PADDSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> AddSaturate(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_adds_epu16 (__m128i a, __m128i b)
+ /// PADDUSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> AddSaturate(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> And(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> And(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> And(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> And(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> And(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> And(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> And(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> And(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_and_pd (__m128d a, __m128d b)
+ /// ANDPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> And(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> AndNot(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> AndNot(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> AndNot(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> AndNot(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> AndNot(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> AndNot(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> AndNot(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> AndNot(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_andnot_pd (__m128d a, __m128d b)
+ /// ADDNPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> AndNot(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_avg_epu8 (__m128i a, __m128i b)
+ /// PAVGB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Average(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_avg_epu16 (__m128i a, __m128i b)
+ /// PAVGW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Average(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi8 (__m128i a, __m128i b)
+ /// PCMPEQB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> CompareEqual(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi8 (__m128i a, __m128i b)
+ /// PCMPEQB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> CompareEqual(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi16 (__m128i a, __m128i b)
+ /// PCMPEQW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> CompareEqual(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi16 (__m128i a, __m128i b)
+ /// PCMPEQW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> CompareEqual(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi32 (__m128i a, __m128i b)
+ /// PCMPEQD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> CompareEqual(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi32 (__m128i a, __m128i b)
+ /// PCMPEQD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> CompareEqual(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_cmpeq_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(0)
+ /// </summary>
+ public static Vector128<double> CompareEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comieq_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareEqualOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomieq_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpeq_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(0)
+ /// </summary>
+ public static Vector128<double> CompareEqualScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpgt_epi8 (__m128i a, __m128i b)
+ /// PCMPGTB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> CompareGreaterThan(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cmpgt_epi16 (__m128i a, __m128i b)
+ /// PCMPGTW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> CompareGreaterThan(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cmpgt_epi32 (__m128i a, __m128i b)
+ /// PCMPGTD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> CompareGreaterThan(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_cmpgt_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(6)
+ /// </summary>
+ public static Vector128<double> CompareGreaterThan(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comigt_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareGreaterThanOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomigt_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareGreaterThanUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpgt_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(6)
+ /// </summary>
+ public static Vector128<double> CompareGreaterThanScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpge_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(5)
+ /// </summary>
+ public static Vector128<double> CompareGreaterThanOrEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comige_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareGreaterThanOrEqualOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomige_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareGreaterThanOrEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpge_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(5)
+ /// </summary>
+ public static Vector128<double> CompareGreaterThanOrEqualScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmplt_epi8 (__m128i a, __m128i b)
+ /// PCMPGTB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> CompareLessThan(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cmplt_epi16 (__m128i a, __m128i b)
+ /// PCMPGTW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> CompareLessThan(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cmplt_epi32 (__m128i a, __m128i b)
+ /// PCMPGTD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> CompareLessThan(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_cmplt_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(1)
+ /// </summary>
+ public static Vector128<double> CompareLessThan(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comilt_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareLessThanOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomilt_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareLessThanUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmplt_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(1)
+ /// </summary>
+ public static Vector128<double> CompareLessThanScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmple_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(2)
+ /// </summary>
+ public static Vector128<double> CompareLessThanOrEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comile_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareLessThanOrEqualOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomile_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareLessThanOrEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmple_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(2)
+ /// </summary>
+ public static Vector128<double> CompareLessThanOrEqualScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpneq_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<double> CompareNotEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_comineq_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareNotEqualOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_ucomineq_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareNotEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpneq_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(4)
+ /// </summary>
+ public static Vector128<double> CompareNotEqualScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpngt_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(2)
+ /// </summary>
+ public static Vector128<double> CompareNotGreaterThan(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpngt_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(2)
+ /// </summary>
+ public static Vector128<double> CompareNotGreaterThanScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpnge_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(1)
+ /// </summary>
+ public static Vector128<double> CompareNotGreaterThanOrEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpnge_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(1)
+ /// </summary>
+ public static Vector128<double> CompareNotGreaterThanOrEqualScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpnlt_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(5)
+ /// </summary>
+ public static Vector128<double> CompareNotLessThan(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpnlt_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(5)
+ /// </summary>
+ public static Vector128<double> CompareNotLessThanScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpnle_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(6)
+ /// </summary>
+ public static Vector128<double> CompareNotLessThanOrEqual(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpnle_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(6)
+ /// </summary>
+ public static Vector128<double> CompareNotLessThanOrEqualScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpord_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(7)
+ /// </summary>
+ public static Vector128<double> CompareOrdered(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpord_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(7)
+ /// </summary>
+ public static Vector128<double> CompareOrderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpunord_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(3)
+ /// </summary>
+ public static Vector128<double> CompareUnordered(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cmpunord_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(3)
+ /// </summary>
+ public static Vector128<double> CompareUnorderedScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cvtps_epi32 (__m128 a)
+ /// CVTPS2DQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtpd_epi32 (__m128d a)
+ /// CVTPD2DQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_cvtepi32_ps (__m128i a)
+ /// CVTDQ2PS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> ConvertToVector128Single(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_cvtpd_ps (__m128d a)
+ /// CVTPD2PS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> ConvertToVector128Single(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_cvtepi32_pd (__m128i a)
+ /// CVTDQ2PD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> ConvertToVector128Double(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_cvtps_pd (__m128 a)
+ /// CVTPS2PD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> ConvertToVector128Double(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// double _mm_cvtsd_f64(__m128d a)
+ /// HELPER: MOVSD
+ /// </summary>
+ public static double ConvertToDouble(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_cvtsd_si32 (__m128d a)
+ /// CVTSD2SI r32, xmm/m64
+ /// </summary>
+ public static int ConvertToInt32(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_cvtsi128_si32 (__m128i a)
+ /// MOVD reg/m32, xmm
+ /// </summary>
+ public static int ConvertToInt32(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm_cvtsd_si64 (__m128d a)
+ /// CVTSD2SI r64, xmm/m64
+ /// </summary>
+ public static long ConvertToInt64(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm_cvtsi128_si64 (__m128i a)
+ /// MOVQ reg/m64, xmm
+ /// </summary>
+ public static long ConvertToInt64(Vector128<long> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_cvtsi128_si32 (__m128i a)
+ /// MOVD reg/m32, xmm
+ /// </summary>
+ public static uint ConvertToUInt32(Vector128<uint> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm_cvtsi128_si64 (__m128i a)
+ /// MOVQ reg/m64, xmm
+ /// </summary>
+ public static ulong ConvertToUInt64(Vector128<ulong> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_cvtsi32_sd (__m128d a, int b)
+ /// CVTSI2SD xmm, reg/m64
+ /// </summary>
+ public static Vector128<double> ConvertScalarToVector128Double(Vector128<double> upper, int value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_cvtsi64_sd (__m128d a, int b)
+ /// CVTSI2SD xmm, reg/m64
+ /// </summary>
+ public static Vector128<double> ConvertScalarToVector128Double(Vector128<double> upper, long value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_cvtss_sd (__m128d a, __m128 b)
+ /// CVTSS2SD xmm, xmm/m32
+ /// </summary>
+ public static Vector128<double> ConvertScalarToVector128Double(Vector128<double> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtsi32_si128 (int a)
+ /// MOVD xmm, reg/m32
+ /// </summary>
+ public static Vector128<int> ConvertScalarToVector128Int32(int value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtsi64_si128 (__int64 a)
+ /// MOVQ xmm, reg/m64
+ /// </summary>
+ public static Vector128<long> ConvertScalarToVector128Int64(long value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_cvtsd_ss (__m128 a, __m128d b)
+ /// CVTSD2SS xmm, xmm/m64
+ /// </summary>
+ public static Vector128<float> ConvertScalarToVector128Single(Vector128<float> upper, Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtsi32_si128 (int a)
+ /// MOVD xmm, reg/m32
+ /// </summary>
+ public static Vector128<uint> ConvertScalarToVector128UInt32(uint value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtsi64_si128 (__int64 a)
+ /// MOVQ xmm, reg/m64
+ /// </summary>
+ public static Vector128<ulong> ConvertScalarToVector128UInt64(ulong value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cvttps_epi32 (__m128 a)
+ /// CVTTPS2DQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32WithTruncation(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvttpd_epi32 (__m128d a)
+ /// CVTTPD2DQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32WithTruncation(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cvttsd_si32 (__m128d a)
+ /// CVTTSD2SI reg, xmm/m64
+ /// </summary>
+ public static int ConvertToInt32WithTruncation(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm_cvttsd_si64 (__m128d a)
+ /// CVTTSD2SI reg, xmm/m64
+ /// </summary>
+ public static long ConvertToInt64WithTruncation(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_div_pd (__m128d a, __m128d b)
+ /// DIVPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Divide(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_div_sd (__m128d a, __m128d b)
+ /// DIVSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> DivideScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_extract_epi16 (__m128i a, int immediate)
+ /// PEXTRW reg, xmm, imm8
+ /// </summary>
+ public static ushort Extract(Vector128<ushort> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_insert_epi16 (__m128i a, int i, int immediate)
+ /// PINSRW xmm, reg/m16, imm8
+ /// </summary>
+ public static Vector128<short> Insert(Vector128<short> value, short data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_insert_epi16 (__m128i a, int i, int immediate)
+ /// PINSRW xmm, reg/m16, imm8
+ /// </summary>
+ public static Vector128<ushort> Insert(Vector128<ushort> value, ushort data, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<sbyte> LoadVector128(sbyte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<byte> LoadVector128(byte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<short> LoadVector128(short* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ushort> LoadVector128(ushort* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<int> LoadVector128(int* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<uint> LoadVector128(uint* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<long> LoadVector128(long* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ulong> LoadVector128(ulong* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_loadu_pd (double const* mem_address)
+ /// MOVUPD xmm, m128
+ /// </summary>
+ public static unsafe Vector128<double> LoadVector128(double* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_load_sd (double const* mem_address)
+ /// MOVSD xmm, m64
+ /// </summary>
+ public static unsafe Vector128<double> LoadScalarVector128(double* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<sbyte> LoadAlignedVector128(sbyte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<byte> LoadAlignedVector128(byte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<short> LoadAlignedVector128(short* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ushort> LoadAlignedVector128(ushort* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<int> LoadAlignedVector128(int* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<uint> LoadAlignedVector128(uint* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<long> LoadAlignedVector128(long* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ulong> LoadAlignedVector128(ulong* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_load_pd (double const* mem_address)
+ /// MOVAPD xmm, m128
+ /// </summary>
+ public static unsafe Vector128<double> LoadAlignedVector128(double* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_lfence(void)
+ /// LFENCE
+ /// </summary>
+ public static void LoadFence() { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_loadh_pd (__m128d a, double const* mem_addr)
+ /// MOVHPD xmm, m64
+ /// </summary>
+ public static unsafe Vector128<double> LoadHigh(Vector128<double> lower, double* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_loadl_pd (__m128d a, double const* mem_addr)
+ /// MOVLPD xmm, m64
+ /// </summary>
+ public static unsafe Vector128<double> LoadLow(Vector128<double> upper, double* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_loadl_epi32 (__m128i const* mem_addr)
+ /// MOVD xmm, reg/m64
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static unsafe Vector128<int> LoadScalarVector128(int* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_loadl_epi32 (__m128i const* mem_addr)
+ /// MOVD xmm, reg/m64
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static unsafe Vector128<uint> LoadScalarVector128(uint* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_loadl_epi64 (__m128i const* mem_addr)
+ /// MOVQ xmm, reg/m64
+ /// </summary>
+ public static unsafe Vector128<long> LoadScalarVector128(long* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_loadl_epi64 (__m128i const* mem_addr)
+ /// MOVQ xmm, reg/m64
+ /// </summary>
+ public static unsafe Vector128<ulong> LoadScalarVector128(ulong* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_maskmoveu_si128 (__m128i a, __m128i mask, char* mem_address)
+ /// MASKMOVDQU xmm, xmm
+ /// </summary>
+ public static unsafe void MaskMove(Vector128<sbyte> source, Vector128<sbyte> mask, sbyte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_maskmoveu_si128 (__m128i a, __m128i mask, char* mem_address)
+ /// MASKMOVDQU xmm, xmm
+ /// </summary>
+ public static unsafe void MaskMove(Vector128<byte> source, Vector128<byte> mask, byte* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_max_epu8 (__m128i a, __m128i b)
+ /// PMAXUB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Max(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_max_epi16 (__m128i a, __m128i b)
+ /// PMAXSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Max(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_max_pd (__m128d a, __m128d b)
+ /// MAXPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Max(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_max_sd (__m128d a, __m128d b)
+ /// MAXSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MaxScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_mfence(void)
+ /// MFENCE
+ /// </summary>
+ public static void MemoryFence() { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_min_epu8 (__m128i a, __m128i b)
+ /// PMINUB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Min(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_min_epi16 (__m128i a, __m128i b)
+ /// PMINSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Min(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_min_pd (__m128d a, __m128d b)
+ /// MINPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Min(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_min_sd (__m128d a, __m128d b)
+ /// MINSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MinScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_move_sd (__m128d a, __m128d b)
+ /// MOVSD xmm, xmm
+ /// </summary>
+ public static Vector128<double> MoveScalar(Vector128<double> upper, Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_movemask_epi8 (__m128i a)
+ /// PMOVMSKB reg, xmm
+ /// </summary>
+ public static int MoveMask(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_movemask_epi8 (__m128i a)
+ /// PMOVMSKB reg, xmm
+ /// </summary>
+ public static int MoveMask(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_movemask_pd (__m128d a)
+ /// MOVMSKPD reg, xmm
+ /// </summary>
+ public static int MoveMask(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_move_epi64 (__m128i a)
+ /// MOVQ xmm, xmm
+ /// </summary>
+ public static Vector128<long> MoveScalar(Vector128<long> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_move_epi64 (__m128i a)
+ /// MOVQ xmm, xmm
+ /// </summary>
+ public static Vector128<ulong> MoveScalar(Vector128<ulong> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_mul_epu32 (__m128i a, __m128i b)
+ /// PMULUDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> Multiply(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_mul_pd (__m128d a, __m128d b)
+ /// MULPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Multiply(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_mul_sd (__m128d a, __m128d b)
+ /// MULSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MultiplyScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_mulhi_epi16 (__m128i a, __m128i b)
+ /// PMULHW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> MultiplyHigh(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_mulhi_epu16 (__m128i a, __m128i b)
+ /// PMULHUW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> MultiplyHigh(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_madd_epi16 (__m128i a, __m128i b)
+ /// PMADDWD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> MultiplyAddAdjacent(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_mullo_epi16 (__m128i a, __m128i b)
+ /// PMULLW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> MultiplyLow(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Or(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Or(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Or(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Or(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Or(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Or(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> Or(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> Or(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_or_pd (__m128d a, __m128d b)
+ /// ORPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Or(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_packs_epi16 (__m128i a, __m128i b)
+ /// PACKSSWB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> PackSignedSaturate(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_packs_epi32 (__m128i a, __m128i b)
+ /// PACKSSDW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> PackSignedSaturate(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_packus_epi16 (__m128i a, __m128i b)
+ /// PACKUSWB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> PackUnsignedSaturate(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// ___m128i _mm_set_epi8 (char e15, char e14, char e13, char e12, char e11, char e10, char e9, char e8, char e7, char e6, char e5, char e4, char e3, char e2, char e1, char e0)
+ /// HELPER
+ /// </summary>
+ public static Vector128<sbyte> SetVector128(sbyte e15, sbyte e14, sbyte e13, sbyte e12, sbyte e11, sbyte e10, sbyte e9, sbyte e8, sbyte e7, sbyte e6, sbyte e5, sbyte e4, sbyte e3, sbyte e2, sbyte e1, sbyte e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// ___m128i _mm_set_epi8 (char e15, char e14, char e13, char e12, char e11, char e10, char e9, char e8, char e7, char e6, char e5, char e4, char e3, char e2, char e1, char e0)
+ /// HELPER
+ /// </summary>
+ public static Vector128<byte> SetVector128(byte e15, byte e14, byte e13, byte e12, byte e11, byte e10, byte e9, byte e8, byte e7, byte e6, byte e5, byte e4, byte e3, byte e2, byte e1, byte e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set_epi16 (short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0)
+ /// HELPER
+ /// </summary>
+ public static Vector128<short> SetVector128(short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set_epi16 (short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0)
+ /// HELPER
+ /// </summary>
+ public static Vector128<ushort> SetVector128(ushort e7, ushort e6, ushort e5, ushort e4, ushort e3, ushort e2, ushort e1, ushort e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set_epi32 (int e3, int e2, int e1, int e0)
+ /// HELPER
+ /// </summary>
+ public static Vector128<int> SetVector128(int e3, int e2, int e1, int e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set_epi32 (int e3, int e2, int e1, int e0)
+ /// HELPER
+ /// </summary>
+ public static Vector128<uint> SetVector128(uint e3, uint e2, uint e1, uint e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set_epi64x (__int64 e1, __int64 e0)
+ /// HELPER
+ /// </summary>
+ public static Vector128<long> SetVector128(long e1, long e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set_epi64x (__int64 e1, __int64 e0)
+ /// HELPER
+ /// </summary>
+ public static Vector128<ulong> SetVector128(ulong e1, ulong e0) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_set_pd (double e1, double e0)
+ /// HELPER
+ /// </summary>
+ public static Vector128<double> SetVector128(double e1, double e0) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_set_sd (double a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<double> SetScalarVector128(double value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_set1_epi8 (char a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<byte> SetAllVector128(byte value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set1_epi8 (char a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<sbyte> SetAllVector128(sbyte value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set1_epi16 (short a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<short> SetAllVector128(short value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set1_epi16 (short a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<ushort> SetAllVector128(ushort value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set1_epi32 (int a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<int> SetAllVector128(int value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set1_epi32 (int a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<uint> SetAllVector128(uint value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set1_epi64x (long long a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<long> SetAllVector128(long value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_set1_epi64x (long long a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<ulong> SetAllVector128(ulong value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_set1_pd (double a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<double> SetAllVector128(double value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_setzero_si128 ()
+ /// HELPER: PXOR
+ /// __m128d _mm_setzero_pd (void)
+ /// HELPER: XORPD
+ /// </summary>
+ public static Vector128<T> SetZeroVector128<T>() where T : struct { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_sad_epu8 (__m128i a, __m128i b)
+ /// PSADBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> SumAbsoluteDifferences(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_shuffle_epi32 (__m128i a, int immediate)
+ /// PSHUFD xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<int> Shuffle(Vector128<int> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_shuffle_epi32 (__m128i a, int immediate)
+ /// PSHUFD xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<uint> Shuffle(Vector128<uint> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_shuffle_pd (__m128d a, __m128d b, int immediate)
+ /// SHUFPD xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<double> Shuffle(Vector128<double> left, Vector128<double> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_shufflehi_epi16 (__m128i a, int immediate)
+ /// PSHUFHW xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<short> ShuffleHigh(Vector128<short> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_shufflehi_epi16 (__m128i a, int control)
+ /// PSHUFHW xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> ShuffleHigh(Vector128<ushort> value, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_shufflelo_epi16 (__m128i a, int control)
+ /// PSHUFLW xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<short> ShuffleLow(Vector128<short> value, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_shufflelo_epi16 (__m128i a, int control)
+ /// PSHUFLW xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> ShuffleLow(Vector128<ushort> value, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_sll_epi16 (__m128i a, __m128i count)
+ /// PSLLW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> ShiftLeftLogical(Vector128<short> value, Vector128<short> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sll_epi16 (__m128i a, __m128i count)
+ /// PSLLW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> ShiftLeftLogical(Vector128<ushort> value, Vector128<ushort> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sll_epi32 (__m128i a, __m128i count)
+ /// PSLLD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftLeftLogical(Vector128<int> value, Vector128<int> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sll_epi32 (__m128i a, __m128i count)
+ /// PSLLD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> ShiftLeftLogical(Vector128<uint> value, Vector128<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sll_epi64 (__m128i a, __m128i count)
+ /// PSLLQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> ShiftLeftLogical(Vector128<long> value, Vector128<long> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sll_epi64 (__m128i a, __m128i count)
+ /// PSLLQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> ShiftLeftLogical(Vector128<ulong> value, Vector128<ulong> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_slli_epi16 (__m128i a, int immediate)
+ /// PSLLW xmm, imm8
+ /// </summary>
+ public static Vector128<short> ShiftLeftLogical(Vector128<short> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_slli_epi16 (__m128i a, int immediate)
+ /// PSLLW xmm, imm8
+ /// </summary>
+ public static Vector128<ushort> ShiftLeftLogical(Vector128<ushort> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_slli_epi32 (__m128i a, int immediate)
+ /// PSLLD xmm, imm8
+ /// </summary>
+ public static Vector128<int> ShiftLeftLogical(Vector128<int> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_slli_epi32 (__m128i a, int immediate)
+ /// PSLLD xmm, imm8
+ /// </summary>
+ public static Vector128<uint> ShiftLeftLogical(Vector128<uint> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_slli_epi64 (__m128i a, int immediate)
+ /// PSLLQ xmm, imm8
+ /// </summary>
+ public static Vector128<long> ShiftLeftLogical(Vector128<long> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_slli_epi64 (__m128i a, int immediate)
+ /// PSLLQ xmm, imm8
+ /// </summary>
+ public static Vector128<ulong> ShiftLeftLogical(Vector128<ulong> value, byte count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<sbyte> ShiftLeftLogical128BitLane(Vector128<sbyte> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<byte> ShiftLeftLogical128BitLane(Vector128<byte> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<short> ShiftLeftLogical128BitLane(Vector128<short> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<ushort> ShiftLeftLogical128BitLane(Vector128<ushort> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<int> ShiftLeftLogical128BitLane(Vector128<int> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<uint> ShiftLeftLogical128BitLane(Vector128<uint> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<long> ShiftLeftLogical128BitLane(Vector128<long> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<ulong> ShiftLeftLogical128BitLane(Vector128<ulong> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_sra_epi16 (__m128i a, __m128i count)
+ /// PSRAW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> ShiftRightArithmetic(Vector128<short> value, Vector128<short> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sra_epi32 (__m128i a, __m128i count)
+ /// PSRAD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftRightArithmetic(Vector128<int> value, Vector128<int> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_srai_epi16 (__m128i a, int immediate)
+ /// PSRAW xmm, imm8
+ /// </summary>
+ public static Vector128<short> ShiftRightArithmetic(Vector128<short> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srai_epi32 (__m128i a, int immediate)
+ /// PSRAD xmm, imm8
+ /// </summary>
+ public static Vector128<int> ShiftRightArithmetic(Vector128<int> value, byte count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_srl_epi16 (__m128i a, __m128i count)
+ /// PSRLW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> ShiftRightLogical(Vector128<short> value, Vector128<short> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srl_epi16 (__m128i a, __m128i count)
+ /// PSRLW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> ShiftRightLogical(Vector128<ushort> value, Vector128<ushort> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srl_epi32 (__m128i a, __m128i count)
+ /// PSRLD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftRightLogical(Vector128<int> value, Vector128<int> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srl_epi32 (__m128i a, __m128i count)
+ /// PSRLD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> ShiftRightLogical(Vector128<uint> value, Vector128<uint> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srl_epi64 (__m128i a, __m128i count)
+ /// PSRLQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> ShiftRightLogical(Vector128<long> value, Vector128<long> count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srl_epi64 (__m128i a, __m128i count)
+ /// PSRLQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> ShiftRightLogical(Vector128<ulong> value, Vector128<ulong> count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_srli_epi16 (__m128i a, int immediate)
+ /// PSRLW xmm, imm8
+ /// </summary>
+ public static Vector128<short> ShiftRightLogical(Vector128<short> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srli_epi16 (__m128i a, int immediate)
+ /// PSRLW xmm, imm8
+ /// </summary>
+ public static Vector128<ushort> ShiftRightLogical(Vector128<ushort> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srli_epi32 (__m128i a, int immediate)
+ /// PSRLD xmm, imm8
+ /// </summary>
+ public static Vector128<int> ShiftRightLogical(Vector128<int> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srli_epi32 (__m128i a, int immediate)
+ /// PSRLD xmm, imm8
+ /// </summary>
+ public static Vector128<uint> ShiftRightLogical(Vector128<uint> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srli_epi64 (__m128i a, int immediate)
+ /// PSRLQ xmm, imm8
+ /// </summary>
+ public static Vector128<long> ShiftRightLogical(Vector128<long> value, byte count) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_srli_epi64 (__m128i a, int immediate)
+ /// PSRLQ xmm, imm8
+ /// </summary>
+ public static Vector128<ulong> ShiftRightLogical(Vector128<ulong> value, byte count) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<sbyte> ShiftRightLogical128BitLane(Vector128<sbyte> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<byte> ShiftRightLogical128BitLane(Vector128<byte> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<short> ShiftRightLogical128BitLane(Vector128<short> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<ushort> ShiftRightLogical128BitLane(Vector128<ushort> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<int> ShiftRightLogical128BitLane(Vector128<int> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<uint> ShiftRightLogical128BitLane(Vector128<uint> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<long> ShiftRightLogical128BitLane(Vector128<long> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<ulong> ShiftRightLogical128BitLane(Vector128<ulong> value, byte numBytes) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_sqrt_pd (__m128d a)
+ /// SQRTPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Sqrt(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_sqrt_sd (__m128d a)
+ /// SQRTSD xmm, xmm/64
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> SqrtScalar(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_sqrt_sd (__m128d a, __m128d b)
+ /// SQRTSD xmm, xmm/64
+ /// </summary>
+ public static Vector128<double> SqrtScalar(Vector128<double> upper, Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_store_sd (double* mem_addr, __m128d a)
+ /// MOVSD m64, xmm
+ /// </summary>
+ public static unsafe void StoreScalar(double* address, Vector128<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(sbyte* address, Vector128<sbyte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(byte* address, Vector128<byte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(short* address, Vector128<short> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(ushort* address, Vector128<ushort> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(int* address, Vector128<int> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(uint* address, Vector128<uint> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(long* address, Vector128<long> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(ulong* address, Vector128<ulong> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_store_pd (double* mem_addr, __m128d a)
+ /// MOVAPD m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(double* address, Vector128<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(sbyte* address, Vector128<sbyte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(byte* address, Vector128<byte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(short* address, Vector128<short> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(ushort* address, Vector128<ushort> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(int* address, Vector128<int> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(uint* address, Vector128<uint> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(long* address, Vector128<long> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(ulong* address, Vector128<ulong> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_stream_pd (double* mem_addr, __m128d a)
+ /// MOVNTPD m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(double* address, Vector128<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(sbyte* address, Vector128<sbyte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(byte* address, Vector128<byte> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(short* address, Vector128<short> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(ushort* address, Vector128<ushort> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(int* address, Vector128<int> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(uint* address, Vector128<uint> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(long* address, Vector128<long> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(ulong* address, Vector128<ulong> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_storeu_pd (double* mem_addr, __m128d a)
+ /// MOVUPD m128, xmm
+ /// </summary>
+ public static unsafe void Store(double* address, Vector128<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_storeh_pd (double* mem_addr, __m128d a)
+ /// MOVHPD m64, xmm
+ /// </summary>
+ public static unsafe void StoreHigh(double* address, Vector128<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_storel_epi64 (__m128i* mem_addr, __m128i a)
+ /// MOVQ m64, xmm
+ /// </summary>
+ public static unsafe void StoreLow(long* address, Vector128<long> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_storel_epi64 (__m128i* mem_addr, __m128i a)
+ /// MOVQ m64, xmm
+ /// </summary>
+ public static unsafe void StoreLow(ulong* address, Vector128<ulong> source) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_storel_pd (double* mem_addr, __m128d a)
+ /// MOVLPD m64, xmm
+ /// </summary>
+ public static unsafe void StoreLow(double* address, Vector128<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_stream_si32(int *p, int a)
+ /// MOVNTI m32, r32
+ /// </summary>
+ public static unsafe void StoreNonTemporal(int* address, int value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_stream_si32(int *p, int a)
+ /// MOVNTI m32, r32
+ /// </summary>
+ public static unsafe void StoreNonTemporal(uint* address, uint value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// void _mm_stream_si64(__int64 *p, __int64 a)
+ /// MOVNTI m64, r64
+ /// </summary>
+ public static unsafe void StoreNonTemporal(long* address, long value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// void _mm_stream_si64(__int64 *p, __int64 a)
+ /// MOVNTI m64, r64
+ /// </summary>
+ public static unsafe void StoreNonTemporal(ulong* address, ulong value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_sub_epi8 (__m128i a, __m128i b)
+ /// PSUBB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Subtract(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sub_epi8 (__m128i a, __m128i b)
+ /// PSUBB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Subtract(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sub_epi16 (__m128i a, __m128i b)
+ /// PSUBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Subtract(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sub_epi16 (__m128i a, __m128i b)
+ /// PSUBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Subtract(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sub_epi32 (__m128i a, __m128i b)
+ /// PSUBD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Subtract(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sub_epi32 (__m128i a, __m128i b)
+ /// PSUBD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Subtract(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sub_epi64 (__m128i a, __m128i b)
+ /// PSUBQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> Subtract(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sub_epi64 (__m128i a, __m128i b)
+ /// PSUBQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> Subtract(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_sub_pd (__m128d a, __m128d b)
+ /// SUBPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Subtract(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_sub_sd (__m128d a, __m128d b)
+ /// SUBSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> SubtractScalar(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_subs_epi8 (__m128i a, __m128i b)
+ /// PSUBSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> SubtractSaturate(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_subs_epi16 (__m128i a, __m128i b)
+ /// PSUBSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> SubtractSaturate(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_subs_epu8 (__m128i a, __m128i b)
+ /// PSUBUSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> SubtractSaturate(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_subs_epu16 (__m128i a, __m128i b)
+ /// PSUBUSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> SubtractSaturate(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi8 (__m128i a, __m128i b)
+ /// PUNPCKHBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> UnpackHigh(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi8 (__m128i a, __m128i b)
+ /// PUNPCKHBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> UnpackHigh(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi16 (__m128i a, __m128i b)
+ /// PUNPCKHWD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> UnpackHigh(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi16 (__m128i a, __m128i b)
+ /// PUNPCKHWD xmm, xmm/m128
+ /// </summary
+ public static Vector128<ushort> UnpackHigh(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi32 (__m128i a, __m128i b)
+ /// PUNPCKHDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> UnpackHigh(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi32 (__m128i a, __m128i b)
+ /// PUNPCKHDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> UnpackHigh(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi64 (__m128i a, __m128i b)
+ /// PUNPCKHQDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> UnpackHigh(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi64 (__m128i a, __m128i b)
+ /// PUNPCKHQDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> UnpackHigh(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_unpackhi_pd (__m128d a, __m128d b)
+ /// UNPCKHPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> UnpackHigh(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi8 (__m128i a, __m128i b)
+ /// PUNPCKLBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> UnpackLow(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi8 (__m128i a, __m128i b)
+ /// PUNPCKLBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> UnpackLow(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi16 (__m128i a, __m128i b)
+ /// PUNPCKLWD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> UnpackLow(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi16 (__m128i a, __m128i b)
+ /// PUNPCKLWD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> UnpackLow(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi32 (__m128i a, __m128i b)
+ /// PUNPCKLDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> UnpackLow(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi32 (__m128i a, __m128i b)
+ /// PUNPCKLDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> UnpackLow(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi64 (__m128i a, __m128i b)
+ /// PUNPCKLQDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> UnpackLow(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi64 (__m128i a, __m128i b)
+ /// PUNPCKLQDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> UnpackLow(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_unpacklo_pd (__m128d a, __m128d b)
+ /// UNPCKLPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> UnpackLow(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Xor(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Xor(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Xor(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Xor(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Xor(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Xor(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> Xor(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> Xor(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_xor_pd (__m128d a, __m128d b)
+ /// XORPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Xor(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.cs
new file mode 100644
index 000000000..0f8b9a8f5
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse2.cs
@@ -0,0 +1,2002 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSE2 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Sse2 : Sse
+ {
+ internal Sse2() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// __m128i _mm_add_epi8 (__m128i a, __m128i b)
+ /// PADDB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Add(Vector128<byte> left, Vector128<byte> right) => Add(left, right);
+ /// <summary>
+ /// __m128i _mm_add_epi8 (__m128i a, __m128i b)
+ /// PADDB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Add(Vector128<sbyte> left, Vector128<sbyte> right) => Add(left, right);
+ /// <summary>
+ /// __m128i _mm_add_epi16 (__m128i a, __m128i b)
+ /// PADDW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Add(Vector128<short> left, Vector128<short> right) => Add(left, right);
+ /// <summary>
+ /// __m128i _mm_add_epi16 (__m128i a, __m128i b)
+ /// PADDW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Add(Vector128<ushort> left, Vector128<ushort> right) => Add(left, right);
+ /// <summary>
+ /// __m128i _mm_add_epi32 (__m128i a, __m128i b)
+ /// PADDD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Add(Vector128<int> left, Vector128<int> right) => Add(left, right);
+ /// <summary>
+ /// __m128i _mm_add_epi32 (__m128i a, __m128i b)
+ /// PADDD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Add(Vector128<uint> left, Vector128<uint> right) => Add(left, right);
+ /// <summary>
+ /// __m128i _mm_add_epi64 (__m128i a, __m128i b)
+ /// PADDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> Add(Vector128<long> left, Vector128<long> right) => Add(left, right);
+ /// <summary>
+ /// __m128i _mm_add_epi64 (__m128i a, __m128i b)
+ /// PADDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> Add(Vector128<ulong> left, Vector128<ulong> right) => Add(left, right);
+ /// <summary>
+ /// __m128d _mm_add_pd (__m128d a, __m128d b)
+ /// ADDPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Add(Vector128<double> left, Vector128<double> right) => Add(left, right);
+
+ /// <summary>
+ /// __m128d _mm_add_sd (__m128d a, __m128d b)
+ /// ADDSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> AddScalar(Vector128<double> left, Vector128<double> right) => AddScalar(left, right);
+
+ /// <summary>
+ /// __m128i _mm_adds_epi8 (__m128i a, __m128i b)
+ /// PADDSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> AddSaturate(Vector128<sbyte> left, Vector128<sbyte> right) => AddSaturate(left, right);
+ /// <summary>
+ /// __m128i _mm_adds_epu8 (__m128i a, __m128i b)
+ /// PADDUSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> AddSaturate(Vector128<byte> left, Vector128<byte> right) => AddSaturate(left, right);
+ /// <summary>
+ /// __m128i _mm_adds_epi16 (__m128i a, __m128i b)
+ /// PADDSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> AddSaturate(Vector128<short> left, Vector128<short> right) => AddSaturate(left, right);
+ /// <summary>
+ /// __m128i _mm_adds_epu16 (__m128i a, __m128i b)
+ /// PADDUSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> AddSaturate(Vector128<ushort> left, Vector128<ushort> right) => AddSaturate(left, right);
+
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> And(Vector128<byte> left, Vector128<byte> right) => And(left, right);
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> And(Vector128<sbyte> left, Vector128<sbyte> right) => And(left, right);
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> And(Vector128<short> left, Vector128<short> right) => And(left, right);
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> And(Vector128<ushort> left, Vector128<ushort> right) => And(left, right);
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> And(Vector128<int> left, Vector128<int> right) => And(left, right);
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> And(Vector128<uint> left, Vector128<uint> right) => And(left, right);
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> And(Vector128<long> left, Vector128<long> right) => And(left, right);
+ /// <summary>
+ /// __m128i _mm_and_si128 (__m128i a, __m128i b)
+ /// PAND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> And(Vector128<ulong> left, Vector128<ulong> right) => And(left, right);
+ /// <summary>
+ /// __m128d _mm_and_pd (__m128d a, __m128d b)
+ /// ANDPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> And(Vector128<double> left, Vector128<double> right) => And(left, right);
+
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> AndNot(Vector128<byte> left, Vector128<byte> right) => AndNot(left, right);
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> AndNot(Vector128<sbyte> left, Vector128<sbyte> right) => AndNot(left, right);
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> AndNot(Vector128<short> left, Vector128<short> right) => AndNot(left, right);
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> AndNot(Vector128<ushort> left, Vector128<ushort> right) => AndNot(left, right);
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> AndNot(Vector128<int> left, Vector128<int> right) => AndNot(left, right);
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> AndNot(Vector128<uint> left, Vector128<uint> right) => AndNot(left, right);
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> AndNot(Vector128<long> left, Vector128<long> right) => AndNot(left, right);
+ /// <summary>
+ /// __m128i _mm_andnot_si128 (__m128i a, __m128i b)
+ /// PANDN xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> AndNot(Vector128<ulong> left, Vector128<ulong> right) => AndNot(left, right);
+ /// <summary>
+ /// __m128d _mm_andnot_pd (__m128d a, __m128d b)
+ /// ADDNPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> AndNot(Vector128<double> left, Vector128<double> right) => AndNot(left, right);
+
+ /// <summary>
+ /// __m128i _mm_avg_epu8 (__m128i a, __m128i b)
+ /// PAVGB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Average(Vector128<byte> left, Vector128<byte> right) => Average(left, right);
+ /// <summary>
+ /// __m128i _mm_avg_epu16 (__m128i a, __m128i b)
+ /// PAVGW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Average(Vector128<ushort> left, Vector128<ushort> right) => Average(left, right);
+
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi8 (__m128i a, __m128i b)
+ /// PCMPEQB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> CompareEqual(Vector128<sbyte> left, Vector128<sbyte> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi8 (__m128i a, __m128i b)
+ /// PCMPEQB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> CompareEqual(Vector128<byte> left, Vector128<byte> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi16 (__m128i a, __m128i b)
+ /// PCMPEQW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> CompareEqual(Vector128<short> left, Vector128<short> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi16 (__m128i a, __m128i b)
+ /// PCMPEQW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> CompareEqual(Vector128<ushort> left, Vector128<ushort> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi32 (__m128i a, __m128i b)
+ /// PCMPEQD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> CompareEqual(Vector128<int> left, Vector128<int> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi32 (__m128i a, __m128i b)
+ /// PCMPEQD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> CompareEqual(Vector128<uint> left, Vector128<uint> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m128d _mm_cmpeq_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(0)
+ /// </summary>
+ public static Vector128<double> CompareEqual(Vector128<double> left, Vector128<double> right) => CompareEqual(left, right);
+
+ /// <summary>
+ /// int _mm_comieq_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareEqualOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareEqualOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomieq_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareEqualUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpeq_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(0)
+ /// </summary>
+ public static Vector128<double> CompareEqualScalar(Vector128<double> left, Vector128<double> right) => CompareEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128i _mm_cmpgt_epi8 (__m128i a, __m128i b)
+ /// PCMPGTB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> CompareGreaterThan(Vector128<sbyte> left, Vector128<sbyte> right) => CompareGreaterThan(left, right);
+ /// <summary>
+ /// __m128i _mm_cmpgt_epi16 (__m128i a, __m128i b)
+ /// PCMPGTW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> CompareGreaterThan(Vector128<short> left, Vector128<short> right) => CompareGreaterThan(left, right);
+ /// <summary>
+ /// __m128i _mm_cmpgt_epi32 (__m128i a, __m128i b)
+ /// PCMPGTD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> CompareGreaterThan(Vector128<int> left, Vector128<int> right) => CompareGreaterThan(left, right);
+ /// <summary>
+ /// __m128d _mm_cmpgt_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(6)
+ /// </summary>
+ public static Vector128<double> CompareGreaterThan(Vector128<double> left, Vector128<double> right) => CompareGreaterThan(left, right);
+
+ /// <summary>
+ /// int _mm_comigt_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareGreaterThanOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareGreaterThanOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomigt_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareGreaterThanUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareGreaterThanUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpgt_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(6)
+ /// </summary>
+ public static Vector128<double> CompareGreaterThanScalar(Vector128<double> left, Vector128<double> right) => CompareGreaterThanScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpge_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(5)
+ /// </summary>
+ public static Vector128<double> CompareGreaterThanOrEqual(Vector128<double> left, Vector128<double> right) => CompareGreaterThanOrEqual(left, right);
+
+ /// <summary>
+ /// int _mm_comige_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareGreaterThanOrEqualOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareGreaterThanOrEqualOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomige_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareGreaterThanOrEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareGreaterThanOrEqualUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpge_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(5)
+ /// </summary>
+ public static Vector128<double> CompareGreaterThanOrEqualScalar(Vector128<double> left, Vector128<double> right) => CompareGreaterThanOrEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128i _mm_cmplt_epi8 (__m128i a, __m128i b)
+ /// PCMPGTB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> CompareLessThan(Vector128<sbyte> left, Vector128<sbyte> right) => CompareLessThan(left, right);
+ /// <summary>
+ /// __m128i _mm_cmplt_epi16 (__m128i a, __m128i b)
+ /// PCMPGTW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> CompareLessThan(Vector128<short> left, Vector128<short> right) => CompareLessThan(left, right);
+ /// <summary>
+ /// __m128i _mm_cmplt_epi32 (__m128i a, __m128i b)
+ /// PCMPGTD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> CompareLessThan(Vector128<int> left, Vector128<int> right) => CompareLessThan(left, right);
+ /// <summary>
+ /// __m128d _mm_cmplt_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(1)
+ /// </summary>
+ public static Vector128<double> CompareLessThan(Vector128<double> left, Vector128<double> right) => CompareLessThan(left, right);
+
+ /// <summary>
+ /// int _mm_comilt_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareLessThanOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareLessThanOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomilt_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareLessThanUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareLessThanUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmplt_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(1)
+ /// </summary>
+ public static Vector128<double> CompareLessThanScalar(Vector128<double> left, Vector128<double> right) => CompareLessThanScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmple_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(2)
+ /// </summary>
+ public static Vector128<double> CompareLessThanOrEqual(Vector128<double> left, Vector128<double> right) => CompareLessThanOrEqual(left, right);
+
+ /// <summary>
+ /// int _mm_comile_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareLessThanOrEqualOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareLessThanOrEqualOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomile_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareLessThanOrEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareLessThanOrEqualUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmple_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(2)
+ /// </summary>
+ public static Vector128<double> CompareLessThanOrEqualScalar(Vector128<double> left, Vector128<double> right) => CompareLessThanOrEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpneq_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<double> CompareNotEqual(Vector128<double> left, Vector128<double> right) => CompareNotEqual(left, right);
+
+ /// <summary>
+ /// int _mm_comineq_sd (__m128d a, __m128d b)
+ /// COMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareNotEqualOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareNotEqualOrderedScalar(left, right);
+
+ /// <summary>
+ /// int _mm_ucomineq_sd (__m128d a, __m128d b)
+ /// UCOMISS xmm, xmm/m64
+ /// </summary>
+ public static bool CompareNotEqualUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareNotEqualUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpneq_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(4)
+ /// </summary>
+ public static Vector128<double> CompareNotEqualScalar(Vector128<double> left, Vector128<double> right) => CompareNotEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpngt_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(2)
+ /// </summary>
+ public static Vector128<double> CompareNotGreaterThan(Vector128<double> left, Vector128<double> right) => CompareNotGreaterThan(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpngt_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(2)
+ /// </summary>
+ public static Vector128<double> CompareNotGreaterThanScalar(Vector128<double> left, Vector128<double> right) => CompareNotGreaterThanScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpnge_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(1)
+ /// </summary>
+ public static Vector128<double> CompareNotGreaterThanOrEqual(Vector128<double> left, Vector128<double> right) => CompareNotGreaterThanOrEqual(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpnge_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(1)
+ /// </summary>
+ public static Vector128<double> CompareNotGreaterThanOrEqualScalar(Vector128<double> left, Vector128<double> right) => CompareNotGreaterThanOrEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpnlt_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(5)
+ /// </summary>
+ public static Vector128<double> CompareNotLessThan(Vector128<double> left, Vector128<double> right) => CompareNotLessThan(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpnlt_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(5)
+ /// </summary>
+ public static Vector128<double> CompareNotLessThanScalar(Vector128<double> left, Vector128<double> right) => CompareNotLessThanScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpnle_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(6)
+ /// </summary>
+ public static Vector128<double> CompareNotLessThanOrEqual(Vector128<double> left, Vector128<double> right) => CompareNotLessThanOrEqual(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpnle_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(6)
+ /// </summary>
+ public static Vector128<double> CompareNotLessThanOrEqualScalar(Vector128<double> left, Vector128<double> right) => CompareNotLessThanOrEqualScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpord_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(7)
+ /// </summary>
+ public static Vector128<double> CompareOrdered(Vector128<double> left, Vector128<double> right) => CompareOrdered(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpord_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(7)
+ /// </summary>
+ public static Vector128<double> CompareOrderedScalar(Vector128<double> left, Vector128<double> right) => CompareOrderedScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpunord_pd (__m128d a, __m128d b)
+ /// CMPPD xmm, xmm/m128, imm8(3)
+ /// </summary>
+ public static Vector128<double> CompareUnordered(Vector128<double> left, Vector128<double> right) => CompareUnordered(left, right);
+
+ /// <summary>
+ /// __m128d _mm_cmpunord_sd (__m128d a, __m128d b)
+ /// CMPSD xmm, xmm/m64, imm8(3)
+ /// </summary>
+ public static Vector128<double> CompareUnorderedScalar(Vector128<double> left, Vector128<double> right) => CompareUnorderedScalar(left, right);
+
+ /// <summary>
+ /// __m128i _mm_cvtps_epi32 (__m128 a)
+ /// CVTPS2DQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<float> value) => ConvertToVector128Int32(value);
+ /// <summary>
+ /// __m128i _mm_cvtpd_epi32 (__m128d a)
+ /// CVTPD2DQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<double> value) => ConvertToVector128Int32(value);
+ /// <summary>
+ /// __m128 _mm_cvtepi32_ps (__m128i a)
+ /// CVTDQ2PS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> ConvertToVector128Single(Vector128<int> value) => ConvertToVector128Single(value);
+ /// <summary>
+ /// __m128 _mm_cvtpd_ps (__m128d a)
+ /// CVTPD2PS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> ConvertToVector128Single(Vector128<double> value) => ConvertToVector128Single(value);
+ /// <summary>
+ /// __m128d _mm_cvtepi32_pd (__m128i a)
+ /// CVTDQ2PD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> ConvertToVector128Double(Vector128<int> value) => ConvertToVector128Double(value);
+ /// <summary>
+ /// __m128d _mm_cvtps_pd (__m128 a)
+ /// CVTPS2PD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> ConvertToVector128Double(Vector128<float> value) => ConvertToVector128Double(value);
+
+ /// <summary>
+ /// double _mm_cvtsd_f64(__m128d a)
+ /// HELPER: MOVSD
+ /// </summary>
+ public static double ConvertToDouble(Vector128<double> value) => ConvertToDouble(value);
+ /// <summary>
+ /// int _mm_cvtsd_si32 (__m128d a)
+ /// CVTSD2SI r32, xmm/m64
+ /// </summary>
+ public static int ConvertToInt32(Vector128<double> value) => ConvertToInt32(value);
+ /// <summary>
+ /// int _mm_cvtsi128_si32 (__m128i a)
+ /// MOVD reg/m32, xmm
+ /// </summary>
+ public static int ConvertToInt32(Vector128<int> value) => ConvertToInt32(value);
+ /// <summary>
+ /// __int64 _mm_cvtsd_si64 (__m128d a)
+ /// CVTSD2SI r64, xmm/m64
+ /// </summary>
+ public static long ConvertToInt64(Vector128<double> value) => ConvertToInt64(value);
+ /// <summary>
+ /// __int64 _mm_cvtsi128_si64 (__m128i a)
+ /// MOVQ reg/m64, xmm
+ /// </summary>
+ public static long ConvertToInt64(Vector128<long> value) => ConvertToInt64(value);
+ /// <summary>
+ /// int _mm_cvtsi128_si32 (__m128i a)
+ /// MOVD reg/m32, xmm
+ /// </summary>
+ public static uint ConvertToUInt32(Vector128<uint> value) => ConvertToUInt32(value);
+ /// <summary>
+ /// __int64 _mm_cvtsi128_si64 (__m128i a)
+ /// MOVQ reg/m64, xmm
+ /// </summary>
+ public static ulong ConvertToUInt64(Vector128<ulong> value) => ConvertToUInt64(value);
+
+ /// <summary>
+ /// __m128d _mm_cvtsi32_sd (__m128d a, int b)
+ /// CVTSI2SD xmm, reg/m64
+ /// </summary>
+ public static Vector128<double> ConvertScalarToVector128Double(Vector128<double> upper, int value) => ConvertScalarToVector128Double(upper, value);
+ /// <summary>
+ /// __m128d _mm_cvtsi64_sd (__m128d a, int b)
+ /// CVTSI2SD xmm, reg/m64
+ /// </summary>
+ public static Vector128<double> ConvertScalarToVector128Double(Vector128<double> upper, long value) => ConvertScalarToVector128Double(upper, value);
+ /// <summary>
+ /// __m128d _mm_cvtss_sd (__m128d a, __m128 b)
+ /// CVTSS2SD xmm, xmm/m32
+ /// </summary>
+ public static Vector128<double> ConvertScalarToVector128Double(Vector128<double> upper, Vector128<float> value) => ConvertScalarToVector128Double(upper, value);
+ /// <summary>
+ /// __m128i _mm_cvtsi32_si128 (int a)
+ /// MOVD xmm, reg/m32
+ /// </summary>
+ public static Vector128<int> ConvertScalarToVector128Int32(int value) => ConvertScalarToVector128Int32(value);
+ /// <summary>
+ /// __m128i _mm_cvtsi64_si128 (__int64 a)
+ /// MOVQ xmm, reg/m64
+ /// </summary>
+ public static Vector128<long> ConvertScalarToVector128Int64(long value) => ConvertScalarToVector128Int64(value);
+ /// <summary>
+ /// __m128 _mm_cvtsd_ss (__m128 a, __m128d b)
+ /// CVTSD2SS xmm, xmm/m64
+ /// </summary>
+ public static Vector128<float> ConvertScalarToVector128Single(Vector128<float> upper, Vector128<double> value) => ConvertScalarToVector128Single(upper, value);
+ /// <summary>
+ /// __m128i _mm_cvtsi32_si128 (int a)
+ /// MOVD xmm, reg/m32
+ /// </summary>
+ public static Vector128<uint> ConvertScalarToVector128UInt32(uint value) => ConvertScalarToVector128UInt32(value);
+ /// <summary>
+ /// __m128i _mm_cvtsi64_si128 (__int64 a)
+ /// MOVQ xmm, reg/m64
+ /// </summary>
+ public static Vector128<ulong> ConvertScalarToVector128UInt64(ulong value) => ConvertScalarToVector128UInt64(value);
+
+ /// <summary>
+ /// __m128i _mm_cvttps_epi32 (__m128 a)
+ /// CVTTPS2DQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32WithTruncation(Vector128<float> value) => ConvertToVector128Int32WithTruncation(value);
+ /// <summary>
+ /// __m128i _mm_cvttpd_epi32 (__m128d a)
+ /// CVTTPD2DQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32WithTruncation(Vector128<double> value) => ConvertToVector128Int32WithTruncation(value);
+
+ /// <summary>
+ /// int _mm_cvttsd_si32 (__m128d a)
+ /// CVTTSD2SI reg, xmm/m64
+ /// </summary>
+ public static int ConvertToInt32WithTruncation(Vector128<double> value) => ConvertToInt32WithTruncation(value);
+ /// <summary>
+ /// __int64 _mm_cvttsd_si64 (__m128d a)
+ /// CVTTSD2SI reg, xmm/m64
+ /// </summary>
+ public static long ConvertToInt64WithTruncation(Vector128<double> value) => ConvertToInt64WithTruncation(value);
+
+ /// <summary>
+ /// __m128d _mm_div_pd (__m128d a, __m128d b)
+ /// DIVPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Divide(Vector128<double> left, Vector128<double> right) => Divide(left, right);
+
+ /// <summary>
+ /// __m128d _mm_div_sd (__m128d a, __m128d b)
+ /// DIVSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> DivideScalar(Vector128<double> left, Vector128<double> right) => DivideScalar(left, right);
+
+ /// <summary>
+ /// int _mm_extract_epi16 (__m128i a, int immediate)
+ /// PEXTRW reg, xmm, imm8
+ /// </summary>
+ public static ushort Extract(Vector128<ushort> value, byte index) => Extract(value, index);
+
+ /// <summary>
+ /// __m128i _mm_insert_epi16 (__m128i a, int i, int immediate)
+ /// PINSRW xmm, reg/m16, imm8
+ /// </summary>
+ public static Vector128<short> Insert(Vector128<short> value, short data, byte index) => Insert(value, data, index);
+ /// <summary>
+ /// __m128i _mm_insert_epi16 (__m128i a, int i, int immediate)
+ /// PINSRW xmm, reg/m16, imm8
+ /// </summary>
+ public static Vector128<ushort> Insert(Vector128<ushort> value, ushort data, byte index) => Insert(value, data, index);
+
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<sbyte> LoadVector128(sbyte* address) => LoadVector128(address);
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<byte> LoadVector128(byte* address) => LoadVector128(address);
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<short> LoadVector128(short* address) => LoadVector128(address);
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ushort> LoadVector128(ushort* address) => LoadVector128(address);
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<int> LoadVector128(int* address) => LoadVector128(address);
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<uint> LoadVector128(uint* address) => LoadVector128(address);
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<long> LoadVector128(long* address) => LoadVector128(address);
+ /// <summary>
+ /// __m128i _mm_loadu_si128 (__m128i const* mem_address)
+ /// MOVDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ulong> LoadVector128(ulong* address) => LoadVector128(address);
+ /// <summary>
+ /// __m128d _mm_loadu_pd (double const* mem_address)
+ /// MOVUPD xmm, m128
+ /// </summary>
+ public static unsafe Vector128<double> LoadVector128(double* address) => LoadVector128(address);
+
+ /// <summary>
+ /// __m128d _mm_load_sd (double const* mem_address)
+ /// MOVSD xmm, m64
+ /// </summary>
+ public static unsafe Vector128<double> LoadScalarVector128(double* address) => LoadScalarVector128(address);
+
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<sbyte> LoadAlignedVector128(sbyte* address) => LoadAlignedVector128(address);
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<byte> LoadAlignedVector128(byte* address) => LoadAlignedVector128(address);
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<short> LoadAlignedVector128(short* address) => LoadAlignedVector128(address);
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ushort> LoadAlignedVector128(ushort* address) => LoadAlignedVector128(address);
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<int> LoadAlignedVector128(int* address) => LoadAlignedVector128(address);
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<uint> LoadAlignedVector128(uint* address) => LoadAlignedVector128(address);
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<long> LoadAlignedVector128(long* address) => LoadAlignedVector128(address);
+ /// <summary>
+ /// __m128i _mm_load_si128 (__m128i const* mem_address)
+ /// MOVDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ulong> LoadAlignedVector128(ulong* address) => LoadAlignedVector128(address);
+ /// <summary>
+ /// __m128d _mm_load_pd (double const* mem_address)
+ /// MOVAPD xmm, m128
+ /// </summary>
+ public static unsafe Vector128<double> LoadAlignedVector128(double* address) => LoadAlignedVector128(address);
+
+ /// <summary>
+ /// void _mm_lfence(void)
+ /// LFENCE
+ /// </summary>
+ public static void LoadFence() => LoadFence();
+
+ /// <summary>
+ /// __m128d _mm_loadh_pd (__m128d a, double const* mem_addr)
+ /// MOVHPD xmm, m64
+ /// </summary>
+ public static unsafe Vector128<double> LoadHigh(Vector128<double> lower, double* address) => LoadHigh(lower, address);
+
+ /// <summary>
+ /// __m128d _mm_loadl_pd (__m128d a, double const* mem_addr)
+ /// MOVLPD xmm, m64
+ /// </summary>
+ public static unsafe Vector128<double> LoadLow(Vector128<double> upper, double* address) => LoadLow(upper, address);
+
+ /// <summary>
+ /// __m128i _mm_loadl_epi32 (__m128i const* mem_addr)
+ /// MOVD xmm, reg/m32
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static unsafe Vector128<int> LoadScalarVector128(int* address) => LoadScalarVector128(address);
+ /// <summary>
+ /// __m128i _mm_loadl_epi32 (__m128i const* mem_addr)
+ /// MOVD xmm, reg/m32
+ /// The above native signature does not exist. We provide this additional overload for completeness.
+ /// </summary>
+ public static unsafe Vector128<uint> LoadScalarVector128(uint* address) => LoadScalarVector128(address);
+ /// <summary>
+ /// __m128i _mm_loadl_epi64 (__m128i const* mem_addr)
+ /// MOVQ xmm, reg/m64
+ /// </summary>
+ public static unsafe Vector128<long> LoadScalarVector128(long* address) => LoadScalarVector128(address);
+ /// <summary>
+ /// __m128i _mm_loadl_epi64 (__m128i const* mem_addr)
+ /// MOVQ xmm, reg/m64
+ /// </summary>
+ public static unsafe Vector128<ulong> LoadScalarVector128(ulong* address) => LoadScalarVector128(address);
+
+ /// <summary>
+ /// void _mm_maskmoveu_si128 (__m128i a, __m128i mask, char* mem_address)
+ /// MASKMOVDQU xmm, xmm
+ /// </summary>
+ public static unsafe void MaskMove(Vector128<sbyte> source, Vector128<sbyte> mask, sbyte* address) => MaskMove(source, mask, address);
+ /// <summary>
+ /// void _mm_maskmoveu_si128 (__m128i a, __m128i mask, char* mem_address)
+ /// MASKMOVDQU xmm, xmm
+ /// </summary>
+ public static unsafe void MaskMove(Vector128<byte> source, Vector128<byte> mask, byte* address) => MaskMove(source, mask, address);
+
+ /// <summary>
+ /// __m128i _mm_max_epu8 (__m128i a, __m128i b)
+ /// PMAXUB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Max(Vector128<byte> left, Vector128<byte> right) => Max(left, right);
+ /// <summary>
+ /// __m128i _mm_max_epi16 (__m128i a, __m128i b)
+ /// PMAXSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Max(Vector128<short> left, Vector128<short> right) => Max(left, right);
+ /// <summary>
+ /// __m128d _mm_max_pd (__m128d a, __m128d b)
+ /// MAXPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Max(Vector128<double> left, Vector128<double> right) => Max(left, right);
+
+ /// <summary>
+ /// __m128d _mm_max_sd (__m128d a, __m128d b)
+ /// MAXSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MaxScalar(Vector128<double> left, Vector128<double> right) => MaxScalar(left, right);
+
+ /// <summary>
+ /// void _mm_mfence(void)
+ /// MFENCE
+ /// </summary>
+ public static void MemoryFence() => MemoryFence();
+
+ /// <summary>
+ /// __m128i _mm_min_epu8 (__m128i a, __m128i b)
+ /// PMINUB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Min(Vector128<byte> left, Vector128<byte> right) => Min(left, right);
+ /// <summary>
+ /// __m128i _mm_min_epi16 (__m128i a, __m128i b)
+ /// PMINSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Min(Vector128<short> left, Vector128<short> right) => Min(left, right);
+ /// <summary>
+ /// __m128d _mm_min_pd (__m128d a, __m128d b)
+ /// MINPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Min(Vector128<double> left, Vector128<double> right) => Min(left, right);
+
+ /// <summary>
+ /// __m128d _mm_min_sd (__m128d a, __m128d b)
+ /// MINSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MinScalar(Vector128<double> left, Vector128<double> right) => MinScalar(left, right);
+
+ /// <summary>
+ /// __m128d _mm_move_sd (__m128d a, __m128d b)
+ /// MOVSD xmm, xmm
+ /// </summary>
+ public static Vector128<double> MoveScalar(Vector128<double> upper, Vector128<double> value) => MoveScalar(upper, value);
+
+ /// <summary>
+ /// int _mm_movemask_epi8 (__m128i a)
+ /// PMOVMSKB reg, xmm
+ /// </summary>
+ public static int MoveMask(Vector128<sbyte> value) => MoveMask(value);
+ /// <summary>
+ /// int _mm_movemask_epi8 (__m128i a)
+ /// PMOVMSKB reg, xmm
+ /// </summary>
+ public static int MoveMask(Vector128<byte> value) => MoveMask(value);
+ /// <summary>
+ /// int _mm_movemask_pd (__m128d a)
+ /// MOVMSKPD reg, xmm
+ /// </summary>
+ public static int MoveMask(Vector128<double> value) => MoveMask(value);
+
+ /// <summary>
+ /// __m128i _mm_move_epi64 (__m128i a)
+ /// MOVQ xmm, xmm
+ /// </summary>
+ public static Vector128<long> MoveScalar(Vector128<long> value) => MoveScalar(value);
+ /// <summary>
+ /// __m128i _mm_move_epi64 (__m128i a)
+ /// MOVQ xmm, xmm
+ /// </summary>
+ public static Vector128<ulong> MoveScalar(Vector128<ulong> value) => MoveScalar(value);
+
+ /// <summary>
+ /// __m128i _mm_mul_epu32 (__m128i a, __m128i b)
+ /// PMULUDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> Multiply(Vector128<uint> left, Vector128<uint> right) => Multiply(left, right);
+ /// <summary>
+ /// __m128d _mm_mul_pd (__m128d a, __m128d b)
+ /// MULPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Multiply(Vector128<double> left, Vector128<double> right) => Multiply(left, right);
+
+ /// <summary>
+ /// __m128d _mm_mul_sd (__m128d a, __m128d b)
+ /// MULSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MultiplyScalar(Vector128<double> left, Vector128<double> right) => MultiplyScalar(left, right);
+
+ /// <summary>
+ /// __m128i _mm_mulhi_epi16 (__m128i a, __m128i b)
+ /// PMULHW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> MultiplyHigh(Vector128<short> left, Vector128<short> right) => MultiplyHigh(left, right);
+ /// <summary>
+ /// __m128i _mm_mulhi_epu16 (__m128i a, __m128i b)
+ /// PMULHUW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> MultiplyHigh(Vector128<ushort> left, Vector128<ushort> right) => MultiplyHigh(left, right);
+
+ /// <summary>
+ /// __m128i _mm_madd_epi16 (__m128i a, __m128i b)
+ /// PMADDWD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> MultiplyAddAdjacent(Vector128<short> left, Vector128<short> right) => MultiplyAddAdjacent(left, right);
+
+ /// <summary>
+ /// __m128i _mm_mullo_epi16 (__m128i a, __m128i b)
+ /// PMULLW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> MultiplyLow(Vector128<short> left, Vector128<short> right) => MultiplyLow(left, right);
+
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Or(Vector128<byte> left, Vector128<byte> right) => Or(left, right);
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Or(Vector128<sbyte> left, Vector128<sbyte> right) => Or(left, right);
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Or(Vector128<short> left, Vector128<short> right) => Or(left, right);
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Or(Vector128<ushort> left, Vector128<ushort> right) => Or(left, right);
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Or(Vector128<int> left, Vector128<int> right) => Or(left, right);
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Or(Vector128<uint> left, Vector128<uint> right) => Or(left, right);
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> Or(Vector128<long> left, Vector128<long> right) => Or(left, right);
+ /// <summary>
+ /// __m128i _mm_or_si128 (__m128i a, __m128i b)
+ /// POR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> Or(Vector128<ulong> left, Vector128<ulong> right) => Or(left, right);
+ /// <summary>
+ /// __m128d _mm_or_pd (__m128d a, __m128d b)
+ /// ORPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Or(Vector128<double> left, Vector128<double> right) => Or(left, right);
+
+ /// <summary>
+ /// __m128i _mm_packs_epi16 (__m128i a, __m128i b)
+ /// PACKSSWB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> PackSignedSaturate(Vector128<short> left, Vector128<short> right) => PackSignedSaturate(left, right);
+ /// <summary>
+ /// __m128i _mm_packs_epi32 (__m128i a, __m128i b)
+ /// PACKSSDW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> PackSignedSaturate(Vector128<int> left, Vector128<int> right) => PackSignedSaturate(left, right);
+
+ /// <summary>
+ /// __m128i _mm_packus_epi16 (__m128i a, __m128i b)
+ /// PACKUSWB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> PackUnsignedSaturate(Vector128<short> left, Vector128<short> right) => PackUnsignedSaturate(left, right);
+
+ /// <summary>
+ /// __m128i _mm_set1_epi8 (char a)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<byte> SetAllVector128(byte value)
+ {
+ // Zero vector and load value et index 0
+ Vector128<byte> vector1 = Sse.StaticCast<uint, byte>(ConvertScalarToVector128UInt32(value));
+ // Create { -- -- -- -- -- -- -- -- -- -- -- -- -- -- vl vl }
+ Vector128<ushort> tmpVector1 = Sse.StaticCast<byte, ushort>(UnpackLow(vector1, vector1));
+ // Create { -- -- -- -- -- -- -- -- -- -- -- -- vl vl vl vl }
+ Vector128<uint> tmpVector2 = Sse.StaticCast<ushort, uint>(UnpackLow(tmpVector1, tmpVector1));
+ // Create { vl vl vl vl vl vl vl vl vl vl vl vl vl vl vl vl } and return result
+ return Sse.StaticCast<uint, byte>(Shuffle(tmpVector2, 0));
+ }
+ /// <summary>
+ /// __m128i _mm_set1_epi8 (char a)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<sbyte> SetAllVector128(sbyte value)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load value et index 0
+ Vector128<sbyte> vector = Sse.StaticCast<int, sbyte>(ConvertScalarToVector128Int32(value));
+ // Create { -- -- -- -- -- -- -- -- -- -- -- -- -- -- vl vl }
+ Vector128<short> tmpVector1 = Sse.StaticCast<sbyte, short>(UnpackLow(vector, vector));
+ // Create { -- -- -- -- -- -- -- -- -- -- -- -- vl vl vl vl }
+ Vector128<int> tmpVector2 = Sse.StaticCast<short, int>(UnpackLow(tmpVector1, tmpVector1));
+ // Create { vl vl vl vl vl vl vl vl vl vl vl vl vl vl vl vl } and return result
+ return Sse.StaticCast<int, sbyte>(Shuffle(tmpVector2, 0));
+ }
+ /// <summary>
+ /// __m128i _mm_set1_epi16 (short a)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<short> SetAllVector128(short value)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load value et index 0
+ Vector128<short> vector = Sse.StaticCast<int, short>(ConvertScalarToVector128Int32(value));
+ // Create { -- -- -- -- -- -- vl vl }
+ Vector128<int> tmpVector = Sse.StaticCast<short, int>(UnpackLow(vector, vector));
+ // Create { vl vl vl vl vl vl vl vl } and return result
+ return Sse.StaticCast<int, short>(Shuffle(tmpVector, (byte)0));
+ }
+ /// <summary>
+ /// __m128i _mm_set1_epi16 (short a)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<ushort> SetAllVector128(ushort value)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load value et index 0
+ Vector128<ushort> vector = Sse.StaticCast<uint, ushort>(ConvertScalarToVector128UInt32(value));
+ // Create { -- -- -- -- -- -- vl vl }
+ Vector128<uint> tmpVector = Sse.StaticCast<ushort, uint>(UnpackLow(vector, vector));
+ // Create { vl vl vl vl vl vl vl vl } and return result
+ return Sse.StaticCast<uint, ushort>(Shuffle(tmpVector, (byte)0));
+ }
+ /// <summary>
+ /// __m128i _mm_set1_epi32 (int a)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<int> SetAllVector128(int value)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load value et index 0
+ Vector128<int> vector = ConvertScalarToVector128Int32(value);
+ // Create { vl vl vl vl } and return result
+ return Shuffle(vector, 0);
+ }
+ /// <summary>
+ /// __m128i _mm_set1_epi32 (int a)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<uint> SetAllVector128(uint value)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load value et index 0
+ Vector128<uint> vector = ConvertScalarToVector128UInt32(value);
+ // Create { vl vl vl vl } and return result
+ return Shuffle(vector, 0);
+ }
+ /// <summary>
+ /// __m128i _mm_set1_epi64x (long long a)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<long> SetAllVector128(long value)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load value et index 0
+ Vector128<long> vector = ConvertScalarToVector128Int64(value);
+ // Create { vl vl } and return result
+ return UnpackLow(vector, vector);
+ }
+ /// <summary>
+ /// __m128i _mm_set1_epi64x (long long a)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<ulong> SetAllVector128(ulong value)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load value et index 0
+ Vector128<ulong> vector = ConvertScalarToVector128UInt64(value);
+ // Create { vl vl } and return result
+ return UnpackLow(vector, vector);
+ }
+ /// <summary>
+ /// __m128d _mm_set1_pd (double a)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<double> SetAllVector128(double value)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load value et index 0
+ Vector128<double> vector = SetScalarVector128(value);
+ // Create { vl vl } and return result
+ return UnpackLow(vector, vector);
+ }
+
+ /// <summary>
+ /// __m128d _mm_set_sd (double a)
+ /// HELPER
+ /// </summary>
+ public static Vector128<double> SetScalarVector128(double value) => SetScalarVector128(value);
+
+ /// <summary>
+ /// ___m128i _mm_set_epi8 (char e15, char e14, char e13, char e12, char e11, char e10, char e9, char e8, char e7, char e6, char e5, char e4, char e3, char e2, char e1, char e0)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe Vector128<sbyte> SetVector128(sbyte e15, sbyte e14, sbyte e13, sbyte e12, sbyte e11, sbyte e10, sbyte e9, sbyte e8, sbyte e7, sbyte e6, sbyte e5, sbyte e4, sbyte e3, sbyte e2, sbyte e1, sbyte e0)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ sbyte* buffer = stackalloc sbyte[16];
+ buffer[0] = e0;
+ buffer[1] = e1;
+ buffer[2] = e2;
+ buffer[3] = e3;
+ buffer[4] = e4;
+ buffer[5] = e5;
+ buffer[6] = e6;
+ buffer[7] = e7;
+ buffer[8] = e8;
+ buffer[9] = e9;
+ buffer[10] = e10;
+ buffer[11] = e11;
+ buffer[12] = e12;
+ buffer[13] = e13;
+ buffer[14] = e14;
+ buffer[15] = e15;
+
+ // Load 16-byte buffer into Vector
+ return LoadVector128(buffer);
+ }
+ /// <summary>
+ /// ___m128i _mm_set_epi8 (char e15, char e14, char e13, char e12, char e11, char e10, char e9, char e8, char e7, char e6, char e5, char e4, char e3, char e2, char e1, char e0)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe Vector128<byte> SetVector128(byte e15, byte e14, byte e13, byte e12, byte e11, byte e10, byte e9, byte e8, byte e7, byte e6, byte e5, byte e4, byte e3, byte e2, byte e1, byte e0)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ byte* buffer = stackalloc byte[16];
+ buffer[0] = e0;
+ buffer[1] = e1;
+ buffer[2] = e2;
+ buffer[3] = e3;
+ buffer[4] = e4;
+ buffer[5] = e5;
+ buffer[6] = e6;
+ buffer[7] = e7;
+ buffer[8] = e8;
+ buffer[9] = e9;
+ buffer[10] = e10;
+ buffer[11] = e11;
+ buffer[12] = e12;
+ buffer[13] = e13;
+ buffer[14] = e14;
+ buffer[15] = e15;
+
+ // Load 16-byte buffer into Vector
+ return LoadVector128(buffer);
+ }
+ /// <summary>
+ /// __m128i _mm_set_epi16 (short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<short> SetVector128(short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load e0 et index 0
+ Vector128<int> e0Vector = ConvertScalarToVector128Int32(e0);
+ Vector128<short> vector = Sse.StaticCast<int, short>(e0Vector);
+ // Insert e1 ... e7 at corresponding index
+ vector = Insert(vector, e1, (byte)1);
+ vector = Insert(vector, e2, (byte)2);
+ vector = Insert(vector, e3, (byte)3);
+ vector = Insert(vector, e4, (byte)4);
+ vector = Insert(vector, e5, (byte)5);
+ vector = Insert(vector, e6, (byte)6);
+ return Insert(vector, e7, (byte)7);
+ }
+ /// <summary>
+ /// __m128i _mm_set_epi16 (short e7, short e6, short e5, short e4, short e3, short e2, short e1, short e0)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<ushort> SetVector128(ushort e7, ushort e6, ushort e5, ushort e4, ushort e3, ushort e2, ushort e1, ushort e0)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load e0 et index 0
+ Vector128<uint> e0vector = ConvertScalarToVector128UInt32(e0);
+ Vector128<ushort> vector = Sse.StaticCast<uint, ushort>(e0vector);
+ // Insert e1 ... e7 at corresponding index
+ vector = Insert(vector, e1, (byte)1);
+ vector = Insert(vector, e2, (byte)2);
+ vector = Insert(vector, e3, (byte)3);
+ vector = Insert(vector, e4, (byte)4);
+ vector = Insert(vector, e5, (byte)5);
+ vector = Insert(vector, e6, (byte)6);
+ return Insert(vector, e7, (byte)7);
+ }
+ /// <summary>
+ /// __m128i _mm_set_epi32 (int e3, int e2, int e1, int e0)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<int> SetVector128(int e3, int e2, int e1, int e0)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load e2 et index 0
+ Vector128<int> e2Vector = ConvertScalarToVector128Int32(e2);
+ Vector128<int> e1Vector = ConvertScalarToVector128Int32(e1);
+ Vector128<int> e0Vector = ConvertScalarToVector128Int32(e0);
+ // Create { -- -- e2 e0 }
+ e0Vector = UnpackLow(e0Vector, e2Vector);
+ e2Vector = ConvertScalarToVector128Int32(e3);
+ // Create { -- -- e3 e1 }
+ e1Vector = UnpackLow(e1Vector, e2Vector);
+ // Create { e3 e2 e1 e0 } and return result
+ return UnpackLow(e0Vector, e1Vector);
+ }
+ /// <summary>
+ /// __m128i _mm_set_epi32 (int e3, int e2, int e1, int e0)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<uint> SetVector128(uint e3, uint e2, uint e1, uint e0)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load e2 et index 0
+ Vector128<uint> e2Vector = ConvertScalarToVector128UInt32(e2);
+ Vector128<uint> e1Vector = ConvertScalarToVector128UInt32(e1);
+ Vector128<uint> e0Vector = ConvertScalarToVector128UInt32(e0);
+ // Create { -- -- e2 e0 }
+ e0Vector = UnpackLow(e0Vector, e2Vector);
+ e2Vector = ConvertScalarToVector128UInt32(e3);
+ // Create { -- -- e3 e1 }
+ e1Vector = UnpackLow(e1Vector, e2Vector);
+ // Create { e3 e2 e1 e0 } and return result
+ return UnpackLow(e0Vector, e1Vector);
+ }
+ /// <summary>
+ /// __m128i _mm_set_epi64x (__int64 e1, __int64 e0)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<long> SetVector128(long e1, long e0)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load e1 et index 0
+ Vector128<long> e1Vector = ConvertScalarToVector128Int64(e1);
+ Vector128<long> e0vector = ConvertScalarToVector128Int64(e0);
+ // Create { e1 e0 } and return result
+ return UnpackLow(e0vector, e1Vector);
+ }
+ /// <summary>
+ /// __m128i _mm_set_epi64x (__int64 e1, __int64 e0)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector128<ulong> SetVector128(ulong e1, ulong e0)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load e1 et index 0
+ Vector128<ulong> e1vector = ConvertScalarToVector128UInt64(e1);
+ Vector128<ulong> e0Vector = ConvertScalarToVector128UInt64(e0);
+ // Create { e1 e0 } and return result
+ return UnpackLow(e0Vector, e1vector);
+ }
+ /// <summary>
+ /// __m128d _mm_set_pd (double e1, double e0)
+ /// HELPER
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe Vector128<double> SetVector128(double e1, double e0)
+ {
+ // TODO-CQ Optimize algorithm choice based on benchmarks
+
+ // Zero vector and load e1 et index 0
+ Vector128<double> e1Vector = SetScalarVector128(e1);
+ Vector128<double> e0Vector = SetScalarVector128(e0);
+ // Create { e1 e0 } and return result
+ return UnpackLow(e0Vector, e1Vector);
+ }
+
+ /// <summary>
+ /// __m128i _mm_setzero_si128 ()
+ /// HELPER: PXOR
+ /// __m128d _mm_setzero_pd (void)
+ /// HELPER: XORPD
+ /// </summary>
+ public static Vector128<T> SetZeroVector128<T>() where T : struct
+ {
+ return SetZeroVector128<T>();
+ }
+
+ /// <summary>
+ /// __m128i _mm_sad_epu8 (__m128i a, __m128i b)
+ /// PSADBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> SumAbsoluteDifferences(Vector128<byte> left, Vector128<byte> right) => SumAbsoluteDifferences(left, right);
+
+ /// <summary>
+ /// __m128i _mm_shuffle_epi32 (__m128i a, int immediate)
+ /// PSHUFD xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<int> Shuffle(Vector128<int> value, byte control) => Shuffle(value, control);
+ /// <summary>
+ /// __m128i _mm_shuffle_epi32 (__m128i a, int immediate)
+ /// PSHUFD xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<uint> Shuffle(Vector128<uint> value, byte control) => Shuffle(value, control);
+ /// <summary>
+ /// __m128d _mm_shuffle_pd (__m128d a, __m128d b, int immediate)
+ /// SHUFPD xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<double> Shuffle(Vector128<double> left, Vector128<double> right, byte control) => Shuffle(left, right, control);
+
+ /// <summary>
+ /// __m128i _mm_shufflehi_epi16 (__m128i a, int immediate)
+ /// PSHUFHW xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<short> ShuffleHigh(Vector128<short> value, byte control) => ShuffleHigh(value, control);
+ /// <summary>
+ /// __m128i _mm_shufflehi_epi16 (__m128i a, int control)
+ /// PSHUFHW xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> ShuffleHigh(Vector128<ushort> value, byte control) => ShuffleHigh(value, control);
+
+ /// <summary>
+ /// __m128i _mm_shufflelo_epi16 (__m128i a, int control)
+ /// PSHUFLW xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<short> ShuffleLow(Vector128<short> value, byte control) => ShuffleLow(value, control);
+ /// <summary>
+ /// __m128i _mm_shufflelo_epi16 (__m128i a, int control)
+ /// PSHUFLW xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> ShuffleLow(Vector128<ushort> value, byte control) => ShuffleLow(value, control);
+
+ /// <summary>
+ /// __m128i _mm_sll_epi16 (__m128i a, __m128i count)
+ /// PSLLW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> ShiftLeftLogical(Vector128<short> value, Vector128<short> count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_sll_epi16 (__m128i a, __m128i count)
+ /// PSLLW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> ShiftLeftLogical(Vector128<ushort> value, Vector128<ushort> count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_sll_epi32 (__m128i a, __m128i count)
+ /// PSLLD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftLeftLogical(Vector128<int> value, Vector128<int> count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_sll_epi32 (__m128i a, __m128i count)
+ /// PSLLD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> ShiftLeftLogical(Vector128<uint> value, Vector128<uint> count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_sll_epi64 (__m128i a, __m128i count)
+ /// PSLLQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> ShiftLeftLogical(Vector128<long> value, Vector128<long> count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_sll_epi64 (__m128i a, __m128i count)
+ /// PSLLQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> ShiftLeftLogical(Vector128<ulong> value, Vector128<ulong> count) => ShiftLeftLogical(value, count);
+
+ /// <summary>
+ /// __m128i _mm_slli_epi16 (__m128i a, int immediate)
+ /// PSLLW xmm, imm8
+ /// </summary>
+ public static Vector128<short> ShiftLeftLogical(Vector128<short> value, byte count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_slli_epi16 (__m128i a, int immediate)
+ /// PSLLW xmm, imm8
+ /// </summary>
+ public static Vector128<ushort> ShiftLeftLogical(Vector128<ushort> value, byte count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_slli_epi32 (__m128i a, int immediate)
+ /// PSLLD xmm, imm8
+ /// </summary>
+ public static Vector128<int> ShiftLeftLogical(Vector128<int> value, byte count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_slli_epi32 (__m128i a, int immediate)
+ /// PSLLD xmm, imm8
+ /// </summary>
+ public static Vector128<uint> ShiftLeftLogical(Vector128<uint> value, byte count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_slli_epi64 (__m128i a, int immediate)
+ /// PSLLQ xmm, imm8
+ /// </summary>
+ public static Vector128<long> ShiftLeftLogical(Vector128<long> value, byte count) => ShiftLeftLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_slli_epi64 (__m128i a, int immediate)
+ /// PSLLQ xmm, imm8
+ /// </summary>
+ public static Vector128<ulong> ShiftLeftLogical(Vector128<ulong> value, byte count) => ShiftLeftLogical(value, count);
+
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<sbyte> ShiftLeftLogical128BitLane(Vector128<sbyte> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<byte> ShiftLeftLogical128BitLane(Vector128<byte> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<short> ShiftLeftLogical128BitLane(Vector128<short> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<ushort> ShiftLeftLogical128BitLane(Vector128<ushort> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<int> ShiftLeftLogical128BitLane(Vector128<int> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<uint> ShiftLeftLogical128BitLane(Vector128<uint> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<long> ShiftLeftLogical128BitLane(Vector128<long> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bslli_si128 (__m128i a, int imm8)
+ /// PSLLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<ulong> ShiftLeftLogical128BitLane(Vector128<ulong> value, byte numBytes) => ShiftLeftLogical128BitLane(value, numBytes);
+
+ /// <summary>
+ /// __m128i _mm_sra_epi16 (__m128i a, __m128i count)
+ /// PSRAW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> ShiftRightArithmetic(Vector128<short> value, Vector128<short> count) => ShiftRightArithmetic(value, count);
+ /// <summary>
+ /// __m128i _mm_sra_epi32 (__m128i a, __m128i count)
+ /// PSRAD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftRightArithmetic(Vector128<int> value, Vector128<int> count) => ShiftRightArithmetic(value, count);
+
+ /// <summary>
+ /// __m128i _mm_srai_epi16 (__m128i a, int immediate)
+ /// PSRAW xmm, imm8
+ /// </summary>
+ public static Vector128<short> ShiftRightArithmetic(Vector128<short> value, byte count) => ShiftRightArithmetic(value, count);
+ /// <summary>
+ /// __m128i _mm_srai_epi32 (__m128i a, int immediate)
+ /// PSRAD xmm, imm8
+ /// </summary>
+ public static Vector128<int> ShiftRightArithmetic(Vector128<int> value, byte count) => ShiftRightArithmetic(value, count);
+
+ /// <summary>
+ /// __m128i _mm_srl_epi16 (__m128i a, __m128i count)
+ /// PSRLW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> ShiftRightLogical(Vector128<short> value, Vector128<short> count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_srl_epi16 (__m128i a, __m128i count)
+ /// PSRLW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> ShiftRightLogical(Vector128<ushort> value, Vector128<ushort> count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_srl_epi32 (__m128i a, __m128i count)
+ /// PSRLD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> ShiftRightLogical(Vector128<int> value, Vector128<int> count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_srl_epi32 (__m128i a, __m128i count)
+ /// PSRLD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> ShiftRightLogical(Vector128<uint> value, Vector128<uint> count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_srl_epi64 (__m128i a, __m128i count)
+ /// PSRLQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> ShiftRightLogical(Vector128<long> value, Vector128<long> count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_srl_epi64 (__m128i a, __m128i count)
+ /// PSRLQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> ShiftRightLogical(Vector128<ulong> value, Vector128<ulong> count) => ShiftRightLogical(value, count);
+
+ /// <summary>
+ /// __m128i _mm_srli_epi16 (__m128i a, int immediate)
+ /// PSRLW xmm, imm8
+ /// </summary>
+ public static Vector128<short> ShiftRightLogical(Vector128<short> value, byte count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_srli_epi16 (__m128i a, int immediate)
+ /// PSRLW xmm, imm8
+ /// </summary>
+ public static Vector128<ushort> ShiftRightLogical(Vector128<ushort> value, byte count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_srli_epi32 (__m128i a, int immediate)
+ /// PSRLD xmm, imm8
+ /// </summary>
+ public static Vector128<int> ShiftRightLogical(Vector128<int> value, byte count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_srli_epi32 (__m128i a, int immediate)
+ /// PSRLD xmm, imm8
+ /// </summary>
+ public static Vector128<uint> ShiftRightLogical(Vector128<uint> value, byte count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_srli_epi64 (__m128i a, int immediate)
+ /// PSRLQ xmm, imm8
+ /// </summary>
+ public static Vector128<long> ShiftRightLogical(Vector128<long> value, byte count) => ShiftRightLogical(value, count);
+ /// <summary>
+ /// __m128i _mm_srli_epi64 (__m128i a, int immediate)
+ /// PSRLQ xmm, imm8
+ /// </summary>
+ public static Vector128<ulong> ShiftRightLogical(Vector128<ulong> value, byte count) => ShiftRightLogical(value, count);
+
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<sbyte> ShiftRightLogical128BitLane(Vector128<sbyte> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<byte> ShiftRightLogical128BitLane(Vector128<byte> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<short> ShiftRightLogical128BitLane(Vector128<short> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<ushort> ShiftRightLogical128BitLane(Vector128<ushort> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<int> ShiftRightLogical128BitLane(Vector128<int> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<uint> ShiftRightLogical128BitLane(Vector128<uint> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<long> ShiftRightLogical128BitLane(Vector128<long> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+ /// <summary>
+ /// __m128i _mm_bsrli_si128 (__m128i a, int imm8)
+ /// PSRLDQ xmm, imm8
+ /// </summary>
+ public static Vector128<ulong> ShiftRightLogical128BitLane(Vector128<ulong> value, byte numBytes) => ShiftRightLogical128BitLane(value, numBytes);
+
+ /// <summary>
+ /// __m128d _mm_sqrt_pd (__m128d a)
+ /// SQRTPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Sqrt(Vector128<double> value) => Sqrt(value);
+
+ /// <summary>
+ /// __m128d _mm_sqrt_sd (__m128d a)
+ /// SQRTSD xmm, xmm/64
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> SqrtScalar(Vector128<double> value) => SqrtScalar(value);
+
+ /// <summary>
+ /// __m128d _mm_sqrt_sd (__m128d a, __m128d b)
+ /// SQRTSD xmm, xmm/64
+ /// </summary>
+ public static Vector128<double> SqrtScalar(Vector128<double> upper, Vector128<double> value) => SqrtScalar(upper, value);
+
+ /// <summary>
+ /// void _mm_store_sd (double* mem_addr, __m128d a)
+ /// MOVSD m64, xmm
+ /// </summary>
+ public static unsafe void StoreScalar(double* address, Vector128<double> source) => StoreScalar(address, source);
+
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(sbyte* address, Vector128<sbyte> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(byte* address, Vector128<byte> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(short* address, Vector128<short> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(ushort* address, Vector128<ushort> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(int* address, Vector128<int> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(uint* address, Vector128<uint> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(long* address, Vector128<long> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm_store_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQA m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(ulong* address, Vector128<ulong> source) => StoreAligned(address, source);
+ /// <summary>
+ /// void _mm_store_pd (double* mem_addr, __m128d a)
+ /// MOVAPD m128, xmm
+ /// </summary>
+ public static unsafe void StoreAligned(double* address, Vector128<double> source) => StoreAligned(address, source);
+
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(sbyte* address, Vector128<sbyte> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(byte* address, Vector128<byte> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(short* address, Vector128<short> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(ushort* address, Vector128<ushort> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(int* address, Vector128<int> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(uint* address, Vector128<uint> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(long* address, Vector128<long> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm_stream_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVNTDQ m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(ulong* address, Vector128<ulong> source) => StoreAlignedNonTemporal(address, source);
+ /// <summary>
+ /// void _mm_stream_pd (double* mem_addr, __m128d a)
+ /// MOVNTPD m128, xmm
+ /// </summary>
+ public static unsafe void StoreAlignedNonTemporal(double* address, Vector128<double> source) => StoreAlignedNonTemporal(address, source);
+
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(sbyte* address, Vector128<sbyte> source) => Store(address, source);
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(byte* address, Vector128<byte> source) => Store(address, source);
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(short* address, Vector128<short> source) => Store(address, source);
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(ushort* address, Vector128<ushort> source) => Store(address, source);
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(int* address, Vector128<int> source) => Store(address, source);
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(uint* address, Vector128<uint> source) => Store(address, source);
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(long* address, Vector128<long> source) => Store(address, source);
+ /// <summary>
+ /// void _mm_storeu_si128 (__m128i* mem_addr, __m128i a)
+ /// MOVDQU m128, xmm
+ /// </summary>
+ public static unsafe void Store(ulong* address, Vector128<ulong> source) => Store(address, source);
+ /// <summary>
+ /// void _mm_storeu_pd (double* mem_addr, __m128d a)
+ /// MOVUPD m128, xmm
+ /// </summary>
+ public static unsafe void Store(double* address, Vector128<double> source) => Store(address, source);
+
+ /// <summary>
+ /// void _mm_storeh_pd (double* mem_addr, __m128d a)
+ /// MOVHPD m64, xmm
+ /// </summary>
+ public static unsafe void StoreHigh(double* address, Vector128<double> source) => StoreHigh(address, source);
+
+ /// <summary>
+ /// void _mm_storel_epi64 (__m128i* mem_addr, __m128i a)
+ /// MOVQ m64, xmm
+ /// </summary>
+ public static unsafe void StoreLow(long* address, Vector128<long> source) => StoreLow(address, source);
+ /// <summary>
+ /// void _mm_storel_epi64 (__m128i* mem_addr, __m128i a)
+ /// MOVQ m64, xmm
+ /// </summary>
+ public static unsafe void StoreLow(ulong* address, Vector128<ulong> source) => StoreLow(address, source);
+ /// <summary>
+ /// void _mm_storel_pd (double* mem_addr, __m128d a)
+ /// MOVLPD m64, xmm
+ /// </summary>
+ public static unsafe void StoreLow(double* address, Vector128<double> source) => StoreLow(address, source);
+
+ /// <summary>
+ /// void _mm_stream_si32(int *p, int a)
+ /// MOVNTI m32, r32
+ /// </summary>
+ public static unsafe void StoreNonTemporal(int* address, int value) => StoreNonTemporal(address, value);
+ /// <summary>
+ /// void _mm_stream_si32(int *p, int a)
+ /// MOVNTI m32, r32
+ /// </summary>
+ public static unsafe void StoreNonTemporal(uint* address, uint value) => StoreNonTemporal(address, value);
+
+ /// <summary>
+ /// void _mm_stream_si64(__int64 *p, __int64 a)
+ /// MOVNTI m64, r64
+ /// </summary>
+ public static unsafe void StoreNonTemporal(long* address, long value) => StoreNonTemporal(address, value);
+ /// <summary>
+ /// void _mm_stream_si64(__int64 *p, __int64 a)
+ /// MOVNTI m64, r64
+ /// </summary>
+ public static unsafe void StoreNonTemporal(ulong* address, ulong value) => StoreNonTemporal(address, value);
+
+ /// <summary>
+ /// __m128i _mm_sub_epi8 (__m128i a, __m128i b)
+ /// PSUBB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Subtract(Vector128<byte> left, Vector128<byte> right) => Subtract(left, right);
+ /// <summary>
+ /// __m128i _mm_sub_epi8 (__m128i a, __m128i b)
+ /// PSUBB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Subtract(Vector128<sbyte> left, Vector128<sbyte> right) => Subtract(left, right);
+ /// <summary>
+ /// __m128i _mm_sub_epi16 (__m128i a, __m128i b)
+ /// PSUBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Subtract(Vector128<short> left, Vector128<short> right) => Subtract(left, right);
+ /// <summary>
+ /// __m128i _mm_sub_epi16 (__m128i a, __m128i b)
+ /// PSUBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Subtract(Vector128<ushort> left, Vector128<ushort> right) => Subtract(left, right);
+ /// <summary>
+ /// __m128i _mm_sub_epi32 (__m128i a, __m128i b)
+ /// PSUBD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Subtract(Vector128<int> left, Vector128<int> right) => Subtract(left, right);
+ /// <summary>
+ /// __m128i _mm_sub_epi32 (__m128i a, __m128i b)
+ /// PSUBD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Subtract(Vector128<uint> left, Vector128<uint> right) => Subtract(left, right);
+ /// <summary>
+ /// __m128i _mm_sub_epi64 (__m128i a, __m128i b)
+ /// PSUBQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> Subtract(Vector128<long> left, Vector128<long> right) => Subtract(left, right);
+ /// <summary>
+ /// __m128i _mm_sub_epi64 (__m128i a, __m128i b)
+ /// PSUBQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> Subtract(Vector128<ulong> left, Vector128<ulong> right) => Subtract(left, right);
+ /// <summary>
+ /// __m128d _mm_sub_pd (__m128d a, __m128d b)
+ /// SUBPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Subtract(Vector128<double> left, Vector128<double> right) => Subtract(left, right);
+
+ /// <summary>
+ /// __m128d _mm_sub_sd (__m128d a, __m128d b)
+ /// SUBSD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> SubtractScalar(Vector128<double> left, Vector128<double> right) => SubtractScalar(left, right);
+
+ /// <summary>
+ /// __m128i _mm_subs_epi8 (__m128i a, __m128i b)
+ /// PSUBSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> SubtractSaturate(Vector128<sbyte> left, Vector128<sbyte> right) => SubtractSaturate(left, right);
+ /// <summary>
+ /// __m128i _mm_subs_epi16 (__m128i a, __m128i b)
+ /// PSUBSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> SubtractSaturate(Vector128<short> left, Vector128<short> right) => SubtractSaturate(left, right);
+ /// <summary>
+ /// __m128i _mm_subs_epu8 (__m128i a, __m128i b)
+ /// PSUBUSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> SubtractSaturate(Vector128<byte> left, Vector128<byte> right) => SubtractSaturate(left, right);
+ /// <summary>
+ /// __m128i _mm_subs_epu16 (__m128i a, __m128i b)
+ /// PSUBUSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> SubtractSaturate(Vector128<ushort> left, Vector128<ushort> right) => SubtractSaturate(left, right);
+
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi8 (__m128i a, __m128i b)
+ /// PUNPCKHBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> UnpackHigh(Vector128<byte> left, Vector128<byte> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi8 (__m128i a, __m128i b)
+ /// PUNPCKHBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> UnpackHigh(Vector128<sbyte> left, Vector128<sbyte> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi16 (__m128i a, __m128i b)
+ /// PUNPCKHWD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> UnpackHigh(Vector128<short> left, Vector128<short> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi16 (__m128i a, __m128i b)
+ /// PUNPCKHWD xmm, xmm/m128
+ /// </summary
+ public static Vector128<ushort> UnpackHigh(Vector128<ushort> left, Vector128<ushort> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi32 (__m128i a, __m128i b)
+ /// PUNPCKHDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> UnpackHigh(Vector128<int> left, Vector128<int> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi32 (__m128i a, __m128i b)
+ /// PUNPCKHDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> UnpackHigh(Vector128<uint> left, Vector128<uint> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi64 (__m128i a, __m128i b)
+ /// PUNPCKHQDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> UnpackHigh(Vector128<long> left, Vector128<long> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m128i _mm_unpackhi_epi64 (__m128i a, __m128i b)
+ /// PUNPCKHQDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> UnpackHigh(Vector128<ulong> left, Vector128<ulong> right) => UnpackHigh(left, right);
+ /// <summary>
+ /// __m128d _mm_unpackhi_pd (__m128d a, __m128d b)
+ /// UNPCKHPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> UnpackHigh(Vector128<double> left, Vector128<double> right) => UnpackHigh(left, right);
+
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi8 (__m128i a, __m128i b)
+ /// PUNPCKLBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> UnpackLow(Vector128<byte> left, Vector128<byte> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi8 (__m128i a, __m128i b)
+ /// PUNPCKLBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> UnpackLow(Vector128<sbyte> left, Vector128<sbyte> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi16 (__m128i a, __m128i b)
+ /// PUNPCKLWD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> UnpackLow(Vector128<short> left, Vector128<short> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi16 (__m128i a, __m128i b)
+ /// PUNPCKLWD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> UnpackLow(Vector128<ushort> left, Vector128<ushort> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi32 (__m128i a, __m128i b)
+ /// PUNPCKLDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> UnpackLow(Vector128<int> left, Vector128<int> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi32 (__m128i a, __m128i b)
+ /// PUNPCKLDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> UnpackLow(Vector128<uint> left, Vector128<uint> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi64 (__m128i a, __m128i b)
+ /// PUNPCKLQDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> UnpackLow(Vector128<long> left, Vector128<long> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m128i _mm_unpacklo_epi64 (__m128i a, __m128i b)
+ /// PUNPCKLQDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> UnpackLow(Vector128<ulong> left, Vector128<ulong> right) => UnpackLow(left, right);
+ /// <summary>
+ /// __m128d _mm_unpacklo_pd (__m128d a, __m128d b)
+ /// UNPCKLPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> UnpackLow(Vector128<double> left, Vector128<double> right) => UnpackLow(left, right);
+
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Xor(Vector128<byte> left, Vector128<byte> right) => Xor(left, right);
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Xor(Vector128<sbyte> left, Vector128<sbyte> right) => Xor(left, right);
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Xor(Vector128<short> left, Vector128<short> right) => Xor(left, right);
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Xor(Vector128<ushort> left, Vector128<ushort> right) => Xor(left, right);
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Xor(Vector128<int> left, Vector128<int> right) => Xor(left, right);
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Xor(Vector128<uint> left, Vector128<uint> right) => Xor(left, right);
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> Xor(Vector128<long> left, Vector128<long> right) => Xor(left, right);
+ /// <summary>
+ /// __m128i _mm_xor_si128 (__m128i a, __m128i b)
+ /// PXOR xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> Xor(Vector128<ulong> left, Vector128<ulong> right) => Xor(left, right);
+ /// <summary>
+ /// __m128d _mm_xor_pd (__m128d a, __m128d b)
+ /// XORPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> Xor(Vector128<double> left, Vector128<double> right) => Xor(left, right);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse3.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse3.PlatformNotSupported.cs
new file mode 100644
index 000000000..f00426644
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse3.PlatformNotSupported.cs
@@ -0,0 +1,91 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSE3 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Sse3 : Sse2
+ {
+ internal Sse3() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// __m128 _mm_addsub_ps (__m128 a, __m128 b)
+ /// ADDSUBPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> AddSubtract(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_addsub_pd (__m128d a, __m128d b)
+ /// ADDSUBPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> AddSubtract(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_hadd_ps (__m128 a, __m128 b)
+ /// HADDPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> HorizontalAdd(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_hadd_pd (__m128d a, __m128d b)
+ /// HADDPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> HorizontalAdd(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_hsub_ps (__m128 a, __m128 b)
+ /// HSUBPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> HorizontalSubtract(Vector128<float> left, Vector128<float> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_hsub_pd (__m128d a, __m128d b)
+ /// HSUBPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> HorizontalSubtract(Vector128<double> left, Vector128<double> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_loaddup_pd (double const* mem_addr)
+ /// MOVDDUP xmm, m64
+ /// </summary>
+ public static unsafe Vector128<double> LoadAndDuplicateToVector128(double* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_lddqu_si128 (__m128i const* mem_addr)
+ /// LDDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<sbyte> LoadDquVector128(sbyte* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe Vector128<byte> LoadDquVector128(byte* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe Vector128<short> LoadDquVector128(short* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe Vector128<ushort> LoadDquVector128(ushort* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe Vector128<int> LoadDquVector128(int* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe Vector128<uint> LoadDquVector128(uint* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe Vector128<long> LoadDquVector128(long* address) { throw new PlatformNotSupportedException(); }
+ public static unsafe Vector128<ulong> LoadDquVector128(ulong* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_movedup_pd (__m128d a)
+ /// MOVDDUP xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MoveAndDuplicate(Vector128<double> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_movehdup_ps (__m128 a)
+ /// MOVSHDUP xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MoveHighAndDuplicate(Vector128<float> source) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_moveldup_ps (__m128 a)
+ /// MOVSLDUP xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MoveLowAndDuplicate(Vector128<float> source) { throw new PlatformNotSupportedException(); }
+
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse3.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse3.cs
new file mode 100644
index 000000000..7c0eaad05
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse3.cs
@@ -0,0 +1,90 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSE3 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Sse3 : Sse2
+ {
+ internal Sse3() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// __m128 _mm_addsub_ps (__m128 a, __m128 b)
+ /// ADDSUBPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> AddSubtract(Vector128<float> left, Vector128<float> right) => AddSubtract(left, right);
+ /// <summary>
+ /// __m128d _mm_addsub_pd (__m128d a, __m128d b)
+ /// ADDSUBPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> AddSubtract(Vector128<double> left, Vector128<double> right) => AddSubtract(left, right);
+
+ /// <summary>
+ /// __m128 _mm_hadd_ps (__m128 a, __m128 b)
+ /// HADDPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> HorizontalAdd(Vector128<float> left, Vector128<float> right) => HorizontalAdd(left, right);
+ /// <summary>
+ /// __m128d _mm_hadd_pd (__m128d a, __m128d b)
+ /// HADDPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> HorizontalAdd(Vector128<double> left, Vector128<double> right) => HorizontalAdd(left, right);
+
+ /// <summary>
+ /// __m128 _mm_hsub_ps (__m128 a, __m128 b)
+ /// HSUBPS xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> HorizontalSubtract(Vector128<float> left, Vector128<float> right) => HorizontalSubtract(left, right);
+ /// <summary>
+ /// __m128d _mm_hsub_pd (__m128d a, __m128d b)
+ /// HSUBPD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<double> HorizontalSubtract(Vector128<double> left, Vector128<double> right) => HorizontalSubtract(left, right);
+
+ /// <summary>
+ /// __m128d _mm_loaddup_pd (double const* mem_addr)
+ /// MOVDDUP xmm, m64
+ /// </summary>
+ public static unsafe Vector128<double> LoadAndDuplicateToVector128(double* address) => LoadAndDuplicateToVector128(address);
+
+ /// <summary>
+ /// __m128i _mm_lddqu_si128 (__m128i const* mem_addr)
+ /// LDDQU xmm, m128
+ /// </summary>
+ public static unsafe Vector128<sbyte> LoadDquVector128(sbyte* address) => LoadDquVector128(address);
+ public static unsafe Vector128<byte> LoadDquVector128(byte* address) => LoadDquVector128(address);
+ public static unsafe Vector128<short> LoadDquVector128(short* address) => LoadDquVector128(address);
+ public static unsafe Vector128<ushort> LoadDquVector128(ushort* address) => LoadDquVector128(address);
+ public static unsafe Vector128<int> LoadDquVector128(int* address) => LoadDquVector128(address);
+ public static unsafe Vector128<uint> LoadDquVector128(uint* address) => LoadDquVector128(address);
+ public static unsafe Vector128<long> LoadDquVector128(long* address) => LoadDquVector128(address);
+ public static unsafe Vector128<ulong> LoadDquVector128(ulong* address) => LoadDquVector128(address);
+
+ /// <summary>
+ /// __m128d _mm_movedup_pd (__m128d a)
+ /// MOVDDUP xmm, xmm/m64
+ /// </summary>
+ public static Vector128<double> MoveAndDuplicate(Vector128<double> source) => MoveAndDuplicate(source);
+
+ /// <summary>
+ /// __m128 _mm_movehdup_ps (__m128 a)
+ /// MOVSHDUP xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MoveHighAndDuplicate(Vector128<float> source) => MoveHighAndDuplicate(source);
+
+ /// <summary>
+ /// __m128 _mm_moveldup_ps (__m128 a)
+ /// MOVSLDUP xmm, xmm/m128
+ /// </summary>
+ public static Vector128<float> MoveLowAndDuplicate(Vector128<float> source) => MoveLowAndDuplicate(source);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.PlatformNotSupported.cs
new file mode 100644
index 000000000..58d06fa14
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.PlatformNotSupported.cs
@@ -0,0 +1,636 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSE4.1 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Sse41 : Ssse3
+ {
+ internal Sse41() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// __m128i _mm_blend_epi16 (__m128i a, __m128i b, const int imm8)
+ /// PBLENDW xmm, xmm/m128 imm8
+ /// </summary>
+ public static Vector128<short> Blend(Vector128<short> left, Vector128<short> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_blend_epi16 (__m128i a, __m128i b, const int imm8)
+ /// PBLENDW xmm, xmm/m128 imm8
+ /// </summary>
+ public static Vector128<ushort> Blend(Vector128<ushort> left, Vector128<ushort> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_blend_ps (__m128 a, __m128 b, const int imm8)
+ /// BLENDPS xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<float> Blend(Vector128<float> left, Vector128<float> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_blend_pd (__m128d a, __m128d b, const int imm8)
+ /// BLENDPD xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<double> Blend(Vector128<double> left, Vector128<double> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_blendv_epi8 (__m128i a, __m128i b, __m128i mask)
+ /// PBLENDVB xmm, xmm/m128, xmm
+ /// </summary>
+ public static Vector128<sbyte> BlendVariable(Vector128<sbyte> left, Vector128<sbyte> right, Vector128<sbyte> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_blendv_epi8 (__m128i a, __m128i b, __m128i mask)
+ /// PBLENDVB xmm, xmm/m128, xmm
+ /// </summary>
+ public static Vector128<byte> BlendVariable(Vector128<byte> left, Vector128<byte> right, Vector128<byte> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_blendv_ps (__m128 a, __m128 b, __m128 mask)
+ /// BLENDVPS xmm, xmm/m128, xmm0
+ /// </summary>
+ public static Vector128<float> BlendVariable(Vector128<float> left, Vector128<float> right, Vector128<float> mask) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_blendv_pd (__m128d a, __m128d b, __m128d mask)
+ /// BLENDVPD xmm, xmm/m128, xmm0
+ /// </summary>
+ public static Vector128<double> BlendVariable(Vector128<double> left, Vector128<double> right, Vector128<double> mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_ceil_ps (__m128 a)
+ /// ROUNDPS xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<float> Ceiling(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_ceil_pd (__m128d a)
+ /// ROUNDPD xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<double> Ceiling(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_ceil_sd (__m128d a)
+ /// ROUNDSD xmm, xmm/m128, imm8(10)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> CeilingScalar(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_ceil_ss (__m128 a)
+ /// ROUNDSD xmm, xmm/m128, imm8(10)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> CeilingScalar(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_ceil_sd (__m128d a, __m128d b)
+ /// ROUNDSD xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<double> CeilingScalar(Vector128<double> upper, Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_ceil_ss (__m128 a, __m128 b)
+ /// ROUNDSS xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<float> CeilingScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi64 (__m128i a, __m128i b)
+ /// PCMPEQQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> CompareEqual(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi64 (__m128i a, __m128i b)
+ /// PCMPEQQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> CompareEqual(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cvtepi8_epi16 (__m128i a)
+ /// PMOVSXBW xmm, xmm/m64
+ /// </summary>
+ public static Vector128<short> ConvertToVector128Int16(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepu8_epi16 (__m128i a)
+ /// PMOVZXBW xmm, xmm/m64
+ /// </summary>
+ public static Vector128<short> ConvertToVector128Int16(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepi8_epi32 (__m128i a)
+ /// PMOVSXBD xmm, xmm/m32
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepu8_epi32 (__m128i a)
+ /// PMOVZXBD xmm, xmm/m32
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepi16_epi32 (__m128i a)
+ /// PMOVSXWD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepu16_epi32 (__m128i a)
+ /// PMOVZXWD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<ushort> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepi8_epi64 (__m128i a)
+ /// PMOVSXBQ xmm, xmm/m16
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepu8_epi64 (__m128i a)
+ /// PMOVZXBQ xmm, xmm/m16
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepi16_epi64 (__m128i a)
+ /// PMOVSXWQ xmm, xmm/m32
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepu16_epi64 (__m128i a)
+ /// PMOVZXWQ xmm, xmm/m32
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<ushort> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepi32_epi64 (__m128i a)
+ /// PMOVSXDQ xmm, xmm/m64
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_cvtepu32_epi64 (__m128i a)
+ /// PMOVZXDQ xmm, xmm/m64
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<uint> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_dp_ps (__m128 a, __m128 b, const int imm8)
+ /// DPPS xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<float> DotProduct(Vector128<float> left, Vector128<float> right, byte control) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_dp_pd (__m128d a, __m128d b, const int imm8)
+ /// DPPD xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<double> DotProduct(Vector128<double> left, Vector128<double> right, byte control) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_extract_epi8 (__m128i a, const int imm8)
+ /// PEXTRB reg/m8, xmm, imm8
+ /// </summary>
+ public static byte Extract(Vector128<byte> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_extract_epi32 (__m128i a, const int imm8)
+ /// PEXTRD reg/m32, xmm, imm8
+ /// </summary>
+ public static int Extract(Vector128<int> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_extract_epi32 (__m128i a, const int imm8)
+ /// PEXTRD reg/m32, xmm, imm8
+ /// </summary>
+ public static uint Extract(Vector128<uint> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm_extract_epi64 (__m128i a, const int imm8)
+ /// PEXTRQ reg/m64, xmm, imm8
+ /// </summary>
+ public static long Extract(Vector128<long> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __int64 _mm_extract_epi64 (__m128i a, const int imm8)
+ /// PEXTRQ reg/m64, xmm, imm8
+ /// </summary>
+ public static ulong Extract(Vector128<ulong> value, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// int _mm_extract_ps (__m128 a, const int imm8)
+ /// EXTRACTPS xmm, xmm/m32, imm8
+ /// </summary>
+ public static float Extract(Vector128<float> value, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_floor_ps (__m128 a)
+ /// ROUNDPS xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<float> Floor(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_floor_pd (__m128d a)
+ /// ROUNDPD xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<double> Floor(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_floor_sd (__m128d a)
+ /// ROUNDSD xmm, xmm/m128, imm8(9)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> FloorScalar(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_floor_ss (__m128 a)
+ /// ROUNDSS xmm, xmm/m128, imm8(9)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> FloorScalar(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_floor_sd (__m128d a, __m128d b)
+ /// ROUNDSD xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<double> FloorScalar(Vector128<double> upper, Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_floor_ss (__m128 a, __m128 b)
+ /// ROUNDSS xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<float> FloorScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_insert_epi8 (__m128i a, int i, const int imm8)
+ /// PINSRB xmm, reg/m8, imm8
+ /// </summary>
+ public static Vector128<sbyte> Insert(Vector128<sbyte> value, sbyte data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_insert_epi8 (__m128i a, int i, const int imm8)
+ /// PINSRB xmm, reg/m8, imm8
+ /// </summary>
+ public static Vector128<byte> Insert(Vector128<byte> value, byte data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_insert_epi32 (__m128i a, int i, const int imm8)
+ /// PINSRD xmm, reg/m32, imm8
+ /// </summary>
+ public static Vector128<int> Insert(Vector128<int> value, int data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_insert_epi32 (__m128i a, int i, const int imm8)
+ /// PINSRD xmm, reg/m32, imm8
+ /// </summary>
+ public static Vector128<uint> Insert(Vector128<uint> value, uint data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_insert_epi64 (__m128i a, __int64 i, const int imm8)
+ /// PINSRQ xmm, reg/m64, imm8
+ /// </summary>
+ public static Vector128<long> Insert(Vector128<long> value, long data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_insert_epi64 (__m128i a, __int64 i, const int imm8)
+ /// PINSRQ xmm, reg/m64, imm8
+ /// </summary>
+ public static Vector128<ulong> Insert(Vector128<ulong> value, ulong data, byte index) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_insert_ps (__m128 a, __m128 b, const int imm8)
+ /// INSERTPS xmm, xmm/m32, imm8
+ /// </summary>
+ public static Vector128<float> Insert(Vector128<float> value, Vector128<float> data, byte index) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_max_epi8 (__m128i a, __m128i b)
+ /// PMAXSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Max(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_max_epu16 (__m128i a, __m128i b)
+ /// PMAXUW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Max(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_max_epi32 (__m128i a, __m128i b)
+ /// PMAXSD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Max(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_max_epu32 (__m128i a, __m128i b)
+ /// PMAXUD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Max(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_min_epi8 (__m128i a, __m128i b)
+ /// PMINSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Min(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_min_epu16 (__m128i a, __m128i b)
+ /// PMINUW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Min(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_min_epi32 (__m128i a, __m128i b)
+ /// PMINSD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Min(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_min_epu32 (__m128i a, __m128i b)
+ /// PMINUD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Min(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_minpos_epu16 (__m128i a)
+ /// PHMINPOSUW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> MinHorizontal(Vector128<ushort> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_mpsadbw_epu8 (__m128i a, __m128i b, const int imm8)
+ /// MPSADBW xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> MultipleSumAbsoluteDifferences(Vector128<byte> left, Vector128<byte> right, byte mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_mul_epi32 (__m128i a, __m128i b)
+ /// PMULDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> Multiply(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_mullo_epi32 (__m128i a, __m128i b)
+ /// PMULLD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> MultiplyLow(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_packus_epi32 (__m128i a, __m128i b)
+ /// PACKUSDW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> PackUnsignedSaturate(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_round_ps (__m128 a, int rounding)
+ /// ROUNDPS xmm, xmm/m128, imm8(8)
+ /// _MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC
+ /// </summary>
+ public static Vector128<float> RoundToNearestInteger(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// _MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC; ROUNDPS xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<float> RoundToNegativeInfinity(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// _MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC; ROUNDPS xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<float> RoundToPositiveInfinity(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// _MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC; ROUNDPS xmm, xmm/m128, imm8(11)
+ /// </summary>
+ public static Vector128<float> RoundToZero(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// _MM_FROUND_CUR_DIRECTION; ROUNDPS xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<float> RoundCurrentDirection(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_round_pd (__m128d a, int rounding)
+ /// ROUNDPD xmm, xmm/m128, imm8(8)
+ /// _MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC
+ /// </summary>
+ public static Vector128<double> RoundToNearestInteger(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// _MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC; ROUNDPD xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<double> RoundToNegativeInfinity(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// _MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC; ROUNDPD xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<double> RoundToPositiveInfinity(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// _MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC; ROUNDPD xmm, xmm/m128, imm8(11)
+ /// </summary>
+ public static Vector128<double> RoundToZero(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// _MM_FROUND_CUR_DIRECTION; ROUNDPD xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<double> RoundCurrentDirection(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, _MM_FROUND_CUR_DIRECTION)
+ /// ROUNDSD xmm, xmm/m128, imm8(4)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> RoundCurrentDirectionScalar(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, _MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(8)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> RoundToNearestIntegerScalar(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, _MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(9)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> RoundToNegativeInfinityScalar(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, _MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(10)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> RoundToPositiveInfinityScalar(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, _MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(11)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> RoundToZeroScalar(Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, __m128d b, _MM_FROUND_CUR_DIRECTION)
+ /// ROUNDSD xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<double> RoundCurrentDirectionScalar(Vector128<double> upper, Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, __m128d b, _MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(8)
+ /// </summary>
+ public static Vector128<double> RoundToNearestIntegerScalar(Vector128<double> upper, Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, __m128d b, _MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<double> RoundToNegativeInfinityScalar(Vector128<double> upper, Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, __m128d b, _MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<double> RoundToPositiveInfinityScalar(Vector128<double> upper, Vector128<double> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, __m128d b, _MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(11)
+ /// </summary>
+ public static Vector128<double> RoundToZeroScalar(Vector128<double> upper, Vector128<double> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, _MM_FROUND_CUR_DIRECTION)
+ /// ROUNDSS xmm, xmm/m128, imm8(4)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> RoundCurrentDirectionScalar(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(8)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> RoundToNearestIntegerScalar(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(9)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> RoundToNegativeInfinityScalar(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(10)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> RoundToPositiveInfinityScalar(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(11)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> RoundToZeroScalar(Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, __m128 b, _MM_FROUND_CUR_DIRECTION)
+ /// ROUNDSS xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<float> RoundCurrentDirectionScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, __m128 b, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(8)
+ /// </summary>
+ public static Vector128<float> RoundToNearestIntegerScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, __m128 b, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<float> RoundToNegativeInfinityScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, __m128 b, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<float> RoundToPositiveInfinityScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, __m128 b, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(11)
+ /// </summary>
+ public static Vector128<float> RoundToZeroScalar(Vector128<float> upper, Vector128<float> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<sbyte> LoadAlignedVector128NonTemporal(sbyte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<byte> LoadAlignedVector128NonTemporal(byte* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<short> LoadAlignedVector128NonTemporal(short* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ushort> LoadAlignedVector128NonTemporal(ushort* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<int> LoadAlignedVector128NonTemporal(int* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<uint> LoadAlignedVector128NonTemporal(uint* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<long> LoadAlignedVector128NonTemporal(long* address) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ulong> LoadAlignedVector128NonTemporal(ulong* address) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_test_all_ones (__m128i a)
+ /// HELPER
+ /// </summary>
+ public static bool TestAllOnes(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllOnes(Vector128<byte> value) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllOnes(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllOnes(Vector128<ushort> value) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllOnes(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllOnes(Vector128<uint> value) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllOnes(Vector128<long> value) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllOnes(Vector128<ulong> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_test_all_zeros (__m128i a, __m128i mask)
+ /// PTEST xmm, xmm/m128
+ /// </summary>
+ public static bool TestAllZeros(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllZeros(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllZeros(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllZeros(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllZeros(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllZeros(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllZeros(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestAllZeros(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_testc_si128 (__m128i a, __m128i b)
+ /// PTEST xmm, xmm/m128
+ /// </summary>
+ public static bool TestC(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestC(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestC(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestC(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestC(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestC(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestC(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestC(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_test_mix_ones_zeros (__m128i a, __m128i mask)
+ /// PTEST xmm, xmm/m128
+ /// </summary>
+ public static bool TestMixOnesZeros(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestMixOnesZeros(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestMixOnesZeros(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestMixOnesZeros(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestMixOnesZeros(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestMixOnesZeros(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestMixOnesZeros(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestMixOnesZeros(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_testnzc_si128 (__m128i a, __m128i b)
+ /// PTEST xmm, xmm/m128
+ /// </summary>
+ public static bool TestNotZAndNotC(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestNotZAndNotC(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestNotZAndNotC(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestNotZAndNotC(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestNotZAndNotC(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestNotZAndNotC(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestNotZAndNotC(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestNotZAndNotC(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_testz_si128 (__m128i a, __m128i b)
+ /// PTEST xmm, xmm/m128
+ /// </summary>
+ public static bool TestZ(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestZ(Vector128<byte> left, Vector128<byte> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestZ(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestZ(Vector128<ushort> left, Vector128<ushort> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestZ(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestZ(Vector128<uint> left, Vector128<uint> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestZ(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+ public static bool TestZ(Vector128<ulong> left, Vector128<ulong> right) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.cs
new file mode 100644
index 000000000..2547e41db
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse41.cs
@@ -0,0 +1,636 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSE4.1 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Sse41 : Ssse3
+ {
+ internal Sse41() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// __m128i _mm_blend_epi16 (__m128i a, __m128i b, const int imm8)
+ /// PBLENDW xmm, xmm/m128 imm8
+ /// </summary>
+ public static Vector128<short> Blend(Vector128<short> left, Vector128<short> right, byte control) => Blend(left, right, control);
+
+ /// <summary>
+ /// __m128i _mm_blend_epi16 (__m128i a, __m128i b, const int imm8)
+ /// PBLENDW xmm, xmm/m128 imm8
+ /// </summary>
+ public static Vector128<ushort> Blend(Vector128<ushort> left, Vector128<ushort> right, byte control) => Blend(left, right, control);
+
+ /// <summary>
+ /// __m128 _mm_blend_ps (__m128 a, __m128 b, const int imm8)
+ /// BLENDPS xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<float> Blend(Vector128<float> left, Vector128<float> right, byte control) => Blend(left, right, control);
+
+ /// <summary>
+ /// __m128d _mm_blend_pd (__m128d a, __m128d b, const int imm8)
+ /// BLENDPD xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<double> Blend(Vector128<double> left, Vector128<double> right, byte control) => Blend(left, right, control);
+
+ /// <summary>
+ /// __m128i _mm_blendv_epi8 (__m128i a, __m128i b, __m128i mask)
+ /// PBLENDVB xmm, xmm/m128, xmm
+ /// </summary>
+ public static Vector128<sbyte> BlendVariable(Vector128<sbyte> left, Vector128<sbyte> right, Vector128<sbyte> mask) => BlendVariable(left, right, mask);
+ /// <summary>
+ /// __m128i _mm_blendv_epi8 (__m128i a, __m128i b, __m128i mask)
+ /// PBLENDVB xmm, xmm/m128, xmm
+ /// </summary>
+ public static Vector128<byte> BlendVariable(Vector128<byte> left, Vector128<byte> right, Vector128<byte> mask) => BlendVariable(left, right, mask);
+ /// <summary>
+ /// __m128 _mm_blendv_ps (__m128 a, __m128 b, __m128 mask)
+ /// BLENDVPS xmm, xmm/m128, xmm0
+ /// </summary>
+ public static Vector128<float> BlendVariable(Vector128<float> left, Vector128<float> right, Vector128<float> mask) => BlendVariable(left, right, mask);
+ /// <summary>
+ /// __m128d _mm_blendv_pd (__m128d a, __m128d b, __m128d mask)
+ /// BLENDVPD xmm, xmm/m128, xmm0
+ /// </summary>
+ public static Vector128<double> BlendVariable(Vector128<double> left, Vector128<double> right, Vector128<double> mask) => BlendVariable(left, right, mask);
+
+ /// <summary>
+ /// __m128 _mm_ceil_ps (__m128 a)
+ /// ROUNDPS xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<float> Ceiling(Vector128<float> value) => Ceiling(value);
+ /// <summary>
+ /// __m128d _mm_ceil_pd (__m128d a)
+ /// ROUNDPD xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<double> Ceiling(Vector128<double> value) => Ceiling(value);
+
+ /// <summary>
+ /// __m128d _mm_ceil_sd (__m128d a)
+ /// ROUNDSD xmm, xmm/m128, imm8(10)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> CeilingScalar(Vector128<double> value) => CeilingScalar(value);
+ /// <summary>
+ /// __m128 _mm_ceil_ss (__m128 a)
+ /// ROUNDSD xmm, xmm/m128, imm8(10)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> CeilingScalar(Vector128<float> value) => CeilingScalar(value);
+
+ /// <summary>
+ /// __m128d _mm_ceil_sd (__m128d a, __m128d b)
+ /// ROUNDSD xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<double> CeilingScalar(Vector128<double> upper, Vector128<double> value) => CeilingScalar(upper, value);
+ /// <summary>
+ /// __m128 _mm_ceil_ss (__m128 a, __m128 b)
+ /// ROUNDSS xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<float> CeilingScalar(Vector128<float> upper, Vector128<float> value) => CeilingScalar(upper, value);
+
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi64 (__m128i a, __m128i b)
+ /// PCMPEQQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> CompareEqual(Vector128<long> left, Vector128<long> right) => CompareEqual(left, right);
+ /// <summary>
+ /// __m128i _mm_cmpeq_epi64 (__m128i a, __m128i b)
+ /// PCMPEQQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ulong> CompareEqual(Vector128<ulong> left, Vector128<ulong> right) => CompareEqual(left, right);
+
+ /// <summary>
+ /// __m128i _mm_cvtepi8_epi16 (__m128i a)
+ /// PMOVSXBW xmm, xmm/m64
+ /// </summary>
+ public static Vector128<short> ConvertToVector128Int16(Vector128<sbyte> value) => ConvertToVector128Int16(value);
+ /// <summary>
+ /// __m128i _mm_cvtepu8_epi16 (__m128i a)
+ /// PMOVZXBW xmm, xmm/m64
+ /// </summary>
+ public static Vector128<short> ConvertToVector128Int16(Vector128<byte> value) => ConvertToVector128Int16(value);
+ /// <summary>
+ /// __m128i _mm_cvtepi8_epi32 (__m128i a)
+ /// PMOVSXBD xmm, xmm/m32
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<sbyte> value) => ConvertToVector128Int32(value);
+ /// <summary>
+ /// __m128i _mm_cvtepu8_epi32 (__m128i a)
+ /// PMOVZXBD xmm, xmm/m32
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<byte> value) => ConvertToVector128Int32(value);
+ /// <summary>
+ /// __m128i _mm_cvtepi16_epi32 (__m128i a)
+ /// PMOVSXWD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<short> value) => ConvertToVector128Int32(value);
+ /// <summary>
+ /// __m128i _mm_cvtepu16_epi32 (__m128i a)
+ /// PMOVZXWD xmm, xmm/m64
+ /// </summary>
+ public static Vector128<int> ConvertToVector128Int32(Vector128<ushort> value) => ConvertToVector128Int32(value);
+ /// <summary>
+ /// __m128i _mm_cvtepi8_epi64 (__m128i a)
+ /// PMOVSXBQ xmm, xmm/m16
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<sbyte> value) => ConvertToVector128Int64(value);
+ /// <summary>
+ /// __m128i _mm_cvtepu8_epi64 (__m128i a)
+ /// PMOVZXBQ xmm, xmm/m16
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<byte> value) => ConvertToVector128Int64(value);
+ /// <summary>
+ /// __m128i _mm_cvtepi16_epi64 (__m128i a)
+ /// PMOVSXWQ xmm, xmm/m32
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<short> value) => ConvertToVector128Int64(value);
+ /// <summary>
+ /// __m128i _mm_cvtepu16_epi64 (__m128i a)
+ /// PMOVZXWQ xmm, xmm/m32
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<ushort> value) => ConvertToVector128Int64(value);
+ /// <summary>
+ /// __m128i _mm_cvtepi32_epi64 (__m128i a)
+ /// PMOVSXDQ xmm, xmm/m64
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<int> value) => ConvertToVector128Int64(value);
+ /// <summary>
+ /// __m128i _mm_cvtepu32_epi64 (__m128i a)
+ /// PMOVZXDQ xmm, xmm/m64
+ /// </summary>
+ public static Vector128<long> ConvertToVector128Int64(Vector128<uint> value) => ConvertToVector128Int64(value);
+
+ /// <summary>
+ /// __m128 _mm_dp_ps (__m128 a, __m128 b, const int imm8)
+ /// DPPS xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<float> DotProduct(Vector128<float> left, Vector128<float> right, byte control) => DotProduct(left, right, control);
+ /// <summary>
+ /// __m128d _mm_dp_pd (__m128d a, __m128d b, const int imm8)
+ /// DPPD xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<double> DotProduct(Vector128<double> left, Vector128<double> right, byte control) => DotProduct(left, right, control);
+
+ /// <summary>
+ /// int _mm_extract_epi8 (__m128i a, const int imm8)
+ /// PEXTRB reg/m8, xmm, imm8
+ /// </summary>
+ public static byte Extract(Vector128<byte> value, byte index) => Extract(value, index);
+ /// <summary>
+ /// int _mm_extract_epi32 (__m128i a, const int imm8)
+ /// PEXTRD reg/m32, xmm, imm8
+ /// </summary>
+ public static int Extract(Vector128<int> value, byte index) => Extract(value, index);
+ /// <summary>
+ /// int _mm_extract_epi32 (__m128i a, const int imm8)
+ /// PEXTRD reg/m32, xmm, imm8
+ /// </summary>
+ public static uint Extract(Vector128<uint> value, byte index) => Extract(value, index);
+ /// <summary>
+ /// __int64 _mm_extract_epi64 (__m128i a, const int imm8)
+ /// PEXTRQ reg/m64, xmm, imm8
+ /// </summary>
+ public static long Extract(Vector128<long> value, byte index) => Extract(value, index);
+ /// <summary>
+ /// __int64 _mm_extract_epi64 (__m128i a, const int imm8)
+ /// PEXTRQ reg/m64, xmm, imm8
+ /// </summary>
+ public static ulong Extract(Vector128<ulong> value, byte index) => Extract(value, index);
+ /// <summary>
+ /// int _mm_extract_ps (__m128 a, const int imm8)
+ /// EXTRACTPS xmm, xmm/m32, imm8
+ /// </summary>
+ public static float Extract(Vector128<float> value, byte index) => Extract(value, index);
+
+ /// <summary>
+ /// __m128 _mm_floor_ps (__m128 a)
+ /// ROUNDPS xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<float> Floor(Vector128<float> value) => Floor(value);
+ /// <summary>
+ /// __m128d _mm_floor_pd (__m128d a)
+ /// ROUNDPD xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<double> Floor(Vector128<double> value) => Floor(value);
+
+ /// <summary>
+ /// __m128d _mm_floor_sd (__m128d a)
+ /// ROUNDSD xmm, xmm/m128, imm8(9)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> FloorScalar(Vector128<double> value) => FloorScalar(value);
+ /// <summary>
+ /// __m128 _mm_floor_ss (__m128 a)
+ /// ROUNDSS xmm, xmm/m128, imm8(9)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> FloorScalar(Vector128<float> value) => FloorScalar(value);
+
+ /// <summary>
+ /// __m128d _mm_floor_sd (__m128d a, __m128d b)
+ /// ROUNDSD xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<double> FloorScalar(Vector128<double> upper, Vector128<double> value) => FloorScalar(upper, value);
+ /// <summary>
+ /// __m128 _mm_floor_ss (__m128 a, __m128 b)
+ /// ROUNDSS xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<float> FloorScalar(Vector128<float> upper, Vector128<float> value) => FloorScalar(upper, value);
+
+ /// <summary>
+ /// __m128i _mm_insert_epi8 (__m128i a, int i, const int imm8)
+ /// PINSRB xmm, reg/m8, imm8
+ /// </summary>
+ public static Vector128<sbyte> Insert(Vector128<sbyte> value, sbyte data, byte index) => Insert(value, data, index);
+ /// <summary>
+ /// __m128i _mm_insert_epi8 (__m128i a, int i, const int imm8)
+ /// PINSRB xmm, reg/m8, imm8
+ /// </summary>
+ public static Vector128<byte> Insert(Vector128<byte> value, byte data, byte index) => Insert(value, data, index);
+ /// <summary>
+ /// __m128i _mm_insert_epi32 (__m128i a, int i, const int imm8)
+ /// PINSRD xmm, reg/m32, imm8
+ /// </summary>
+ public static Vector128<int> Insert(Vector128<int> value, int data, byte index) => Insert(value, data, index);
+ /// <summary>
+ /// __m128i _mm_insert_epi32 (__m128i a, int i, const int imm8)
+ /// PINSRD xmm, reg/m32, imm8
+ /// </summary>
+ public static Vector128<uint> Insert(Vector128<uint> value, uint data, byte index) => Insert(value, data, index);
+ /// <summary>
+ /// __m128i _mm_insert_epi64 (__m128i a, __int64 i, const int imm8)
+ /// PINSRQ xmm, reg/m64, imm8
+ /// </summary>
+ public static Vector128<long> Insert(Vector128<long> value, long data, byte index) => Insert(value, data, index);
+ /// <summary>
+ /// __m128i _mm_insert_epi64 (__m128i a, __int64 i, const int imm8)
+ /// PINSRQ xmm, reg/m64, imm8
+ /// </summary>
+ public static Vector128<ulong> Insert(Vector128<ulong> value, ulong data, byte index) => Insert(value, data, index);
+ /// <summary>
+ /// __m128 _mm_insert_ps (__m128 a, __m128 b, const int imm8)
+ /// INSERTPS xmm, xmm/m32, imm8
+ /// </summary>
+ public static Vector128<float> Insert(Vector128<float> value, Vector128<float> data, byte index) => Insert(value, data, index);
+
+ /// <summary>
+ /// __m128i _mm_max_epi8 (__m128i a, __m128i b)
+ /// PMAXSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Max(Vector128<sbyte> left, Vector128<sbyte> right) => Max(left, right);
+ /// <summary>
+ /// __m128i _mm_max_epu16 (__m128i a, __m128i b)
+ /// PMAXUW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Max(Vector128<ushort> left, Vector128<ushort> right) => Max(left, right);
+ /// <summary>
+ /// __m128i _mm_max_epi32 (__m128i a, __m128i b)
+ /// PMAXSD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Max(Vector128<int> left, Vector128<int> right) => Max(left, right);
+ /// <summary>
+ /// __m128i _mm_max_epu32 (__m128i a, __m128i b)
+ /// PMAXUD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Max(Vector128<uint> left, Vector128<uint> right) => Max(left, right);
+
+ /// <summary>
+ /// __m128i _mm_min_epi8 (__m128i a, __m128i b)
+ /// PMINSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Min(Vector128<sbyte> left, Vector128<sbyte> right) => Min(left, right);
+ /// <summary>
+ /// __m128i _mm_min_epu16 (__m128i a, __m128i b)
+ /// PMINUW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Min(Vector128<ushort> left, Vector128<ushort> right) => Min(left, right);
+ /// <summary>
+ /// __m128i _mm_min_epi32 (__m128i a, __m128i b)
+ /// PMINSD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Min(Vector128<int> left, Vector128<int> right) => Min(left, right);
+ /// <summary>
+ /// __m128i _mm_min_epu32 (__m128i a, __m128i b)
+ /// PMINUD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Min(Vector128<uint> left, Vector128<uint> right) => Min(left, right);
+
+ /// <summary>
+ /// __m128i _mm_minpos_epu16 (__m128i a)
+ /// PHMINPOSUW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> MinHorizontal(Vector128<ushort> value) => MinHorizontal(value);
+
+ /// <summary>
+ /// __m128i _mm_mpsadbw_epu8 (__m128i a, __m128i b, const int imm8)
+ /// MPSADBW xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> MultipleSumAbsoluteDifferences(Vector128<byte> left, Vector128<byte> right, byte mask) => MultipleSumAbsoluteDifferences(left, right, mask);
+
+ /// <summary>
+ /// __m128i _mm_mul_epi32 (__m128i a, __m128i b)
+ /// PMULDQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> Multiply(Vector128<int> left, Vector128<int> right) => Multiply(left, right);
+
+ /// <summary>
+ /// __m128i _mm_mullo_epi32 (__m128i a, __m128i b)
+ /// PMULLD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> MultiplyLow(Vector128<int> left, Vector128<int> right) => MultiplyLow(left, right);
+
+ /// <summary>
+ /// __m128i _mm_packus_epi32 (__m128i a, __m128i b)
+ /// PACKUSDW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> PackUnsignedSaturate(Vector128<int> left, Vector128<int> right) => PackUnsignedSaturate(left, right);
+
+ /// <summary>
+ /// __m128 _mm_round_ps (__m128 a, int rounding)
+ /// ROUNDPS xmm, xmm/m128, imm8(8)
+ /// _MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC
+ /// </summary>
+ public static Vector128<float> RoundToNearestInteger(Vector128<float> value) => RoundToNearestInteger(value);
+ /// <summary>
+ /// _MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC; ROUNDPS xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<float> RoundToNegativeInfinity(Vector128<float> value) => RoundToNegativeInfinity(value);
+ /// <summary>
+ /// _MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC; ROUNDPS xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<float> RoundToPositiveInfinity(Vector128<float> value) => RoundToPositiveInfinity(value);
+ /// <summary>
+ /// _MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC; ROUNDPS xmm, xmm/m128, imm8(11)
+ /// </summary>
+ public static Vector128<float> RoundToZero(Vector128<float> value) => RoundToZero(value);
+ /// <summary>
+ /// _MM_FROUND_CUR_DIRECTION; ROUNDPS xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<float> RoundCurrentDirection(Vector128<float> value) => RoundCurrentDirection(value);
+
+ /// <summary>
+ /// __m128d _mm_round_pd (__m128d a, int rounding)
+ /// ROUNDPD xmm, xmm/m128, imm8(8)
+ /// _MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC
+ /// </summary>
+ public static Vector128<double> RoundToNearestInteger(Vector128<double> value) => RoundToNearestInteger(value);
+ /// <summary>
+ /// _MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC; ROUNDPD xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<double> RoundToNegativeInfinity(Vector128<double> value) => RoundToNegativeInfinity(value);
+ /// <summary>
+ /// _MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC; ROUNDPD xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<double> RoundToPositiveInfinity(Vector128<double> value) => RoundToPositiveInfinity(value);
+ /// <summary>
+ /// _MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC; ROUNDPD xmm, xmm/m128, imm8(11)
+ /// </summary>
+ public static Vector128<double> RoundToZero(Vector128<double> value) => RoundToZero(value);
+ /// <summary>
+ /// _MM_FROUND_CUR_DIRECTION; ROUNDPD xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<double> RoundCurrentDirection(Vector128<double> value) => RoundCurrentDirection(value);
+
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, _MM_FROUND_CUR_DIRECTION)
+ /// ROUNDSD xmm, xmm/m128, imm8(4)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> RoundCurrentDirectionScalar(Vector128<double> value) => RoundCurrentDirectionScalar(value);
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, _MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(8)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> RoundToNearestIntegerScalar(Vector128<double> value) => RoundToNearestIntegerScalar(value);
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, _MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(9)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> RoundToNegativeInfinityScalar(Vector128<double> value) => RoundToNegativeInfinityScalar(value);
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, _MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(10)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> RoundToPositiveInfinityScalar(Vector128<double> value) => RoundToPositiveInfinityScalar(value);
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, _MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(11)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<double> RoundToZeroScalar(Vector128<double> value) => RoundToZeroScalar(value);
+
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, __m128d b, _MM_FROUND_CUR_DIRECTION)
+ /// ROUNDSD xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<double> RoundCurrentDirectionScalar(Vector128<double> upper, Vector128<double> value) => RoundCurrentDirectionScalar(upper, value);
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, __m128d b, _MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(8)
+ /// </summary>
+ public static Vector128<double> RoundToNearestIntegerScalar(Vector128<double> upper, Vector128<double> value) => RoundToNearestIntegerScalar(upper, value);
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, __m128d b, _MM_FROUND_TO_NEG_INF |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<double> RoundToNegativeInfinityScalar(Vector128<double> upper, Vector128<double> value) => RoundToNegativeInfinityScalar(upper, value);
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, __m128d b, _MM_FROUND_TO_POS_INF |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<double> RoundToPositiveInfinityScalar(Vector128<double> upper, Vector128<double> value) => RoundToPositiveInfinityScalar(upper, value);
+ /// <summary>
+ /// __m128d _mm_round_sd (__m128d a, __m128d b, _MM_FROUND_TO_ZERO |_MM_FROUND_NO_EXC)
+ /// ROUNDSD xmm, xmm/m128, imm8(11)
+ /// </summary>
+ public static Vector128<double> RoundToZeroScalar(Vector128<double> upper, Vector128<double> value) => RoundToZeroScalar(upper, value);
+
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, _MM_FROUND_CUR_DIRECTION)
+ /// ROUNDSS xmm, xmm/m128, imm8(4)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> RoundCurrentDirectionScalar(Vector128<float> value) => RoundCurrentDirectionScalar(value);
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(8)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> RoundToNearestIntegerScalar(Vector128<float> value) => RoundToNearestIntegerScalar(value);
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(9)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> RoundToNegativeInfinityScalar(Vector128<float> value) => RoundToNegativeInfinityScalar(value);
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(10)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> RoundToPositiveInfinityScalar(Vector128<float> value) => RoundToPositiveInfinityScalar(value);
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(11)
+ /// The above native signature does not exist. We provide this additional overload for the recommended use case of this intrinsic.
+ /// </summary>
+ public static Vector128<float> RoundToZeroScalar(Vector128<float> value) => RoundToZeroScalar(value);
+
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, __m128 b, _MM_FROUND_CUR_DIRECTION)
+ /// ROUNDSS xmm, xmm/m128, imm8(4)
+ /// </summary>
+ public static Vector128<float> RoundCurrentDirectionScalar(Vector128<float> upper, Vector128<float> value) => RoundCurrentDirectionScalar(upper, value);
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, __m128 b, _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(8)
+ /// </summary>
+ public static Vector128<float> RoundToNearestIntegerScalar(Vector128<float> upper, Vector128<float> value) => RoundToNearestIntegerScalar(upper, value);
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, __m128 b, _MM_FROUND_TO_NEG_INF | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(9)
+ /// </summary>
+ public static Vector128<float> RoundToNegativeInfinityScalar(Vector128<float> upper, Vector128<float> value) => RoundToNegativeInfinityScalar(upper, value);
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, __m128 b, _MM_FROUND_TO_POS_INF | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(10)
+ /// </summary>
+ public static Vector128<float> RoundToPositiveInfinityScalar(Vector128<float> upper, Vector128<float> value) => RoundToPositiveInfinityScalar(upper, value);
+ /// <summary>
+ /// __m128 _mm_round_ss (__m128 a, __m128 b, _MM_FROUND_TO_ZERO | _MM_FROUND_NO_EXC)
+ /// ROUNDSS xmm, xmm/m128, imm8(11)
+ /// </summary>
+ public static Vector128<float> RoundToZeroScalar(Vector128<float> upper, Vector128<float> value) => RoundToZeroScalar(upper, value);
+
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<sbyte> LoadAlignedVector128NonTemporal(sbyte* address) => LoadAlignedVector128NonTemporal(address);
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<byte> LoadAlignedVector128NonTemporal(byte* address) => LoadAlignedVector128NonTemporal(address);
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<short> LoadAlignedVector128NonTemporal(short* address) => LoadAlignedVector128NonTemporal(address);
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ushort> LoadAlignedVector128NonTemporal(ushort* address) => LoadAlignedVector128NonTemporal(address);
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<int> LoadAlignedVector128NonTemporal(int* address) => LoadAlignedVector128NonTemporal(address);
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<uint> LoadAlignedVector128NonTemporal(uint* address) => LoadAlignedVector128NonTemporal(address);
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<long> LoadAlignedVector128NonTemporal(long* address) => LoadAlignedVector128NonTemporal(address);
+ /// <summary>
+ /// __m128i _mm_stream_load_si128 (const __m128i* mem_addr)
+ /// MOVNTDQA xmm, m128
+ /// </summary>
+ public static unsafe Vector128<ulong> LoadAlignedVector128NonTemporal(ulong* address) => LoadAlignedVector128NonTemporal(address);
+
+ /// <summary>
+ /// int _mm_test_all_ones (__m128i a)
+ /// HELPER
+ /// </summary>
+ public static bool TestAllOnes(Vector128<sbyte> value) => TestAllOnes(value);
+ public static bool TestAllOnes(Vector128<byte> value) => TestAllOnes(value);
+ public static bool TestAllOnes(Vector128<short> value) => TestAllOnes(value);
+ public static bool TestAllOnes(Vector128<ushort> value) => TestAllOnes(value);
+ public static bool TestAllOnes(Vector128<int> value) => TestAllOnes(value);
+ public static bool TestAllOnes(Vector128<uint> value) => TestAllOnes(value);
+ public static bool TestAllOnes(Vector128<long> value) => TestAllOnes(value);
+ public static bool TestAllOnes(Vector128<ulong> value) => TestAllOnes(value);
+
+ /// <summary>
+ /// int _mm_test_all_zeros (__m128i a, __m128i mask)
+ /// PTEST xmm, xmm/m128
+ /// </summary>
+ public static bool TestAllZeros(Vector128<sbyte> left, Vector128<sbyte> right) => TestAllZeros(left, right);
+ public static bool TestAllZeros(Vector128<byte> left, Vector128<byte> right) => TestAllZeros(left, right);
+ public static bool TestAllZeros(Vector128<short> left, Vector128<short> right) => TestAllZeros(left, right);
+ public static bool TestAllZeros(Vector128<ushort> left, Vector128<ushort> right) => TestAllZeros(left, right);
+ public static bool TestAllZeros(Vector128<int> left, Vector128<int> right) => TestAllZeros(left, right);
+ public static bool TestAllZeros(Vector128<uint> left, Vector128<uint> right) => TestAllZeros(left, right);
+ public static bool TestAllZeros(Vector128<long> left, Vector128<long> right) => TestAllZeros(left, right);
+ public static bool TestAllZeros(Vector128<ulong> left, Vector128<ulong> right) => TestAllZeros(left, right);
+
+ /// <summary>
+ /// int _mm_testc_si128 (__m128i a, __m128i b)
+ /// PTEST xmm, xmm/m128
+ /// </summary>
+ public static bool TestC(Vector128<sbyte> left, Vector128<sbyte> right) => TestC(left, right);
+ public static bool TestC(Vector128<byte> left, Vector128<byte> right) => TestC(left, right);
+ public static bool TestC(Vector128<short> left, Vector128<short> right) => TestC(left, right);
+ public static bool TestC(Vector128<ushort> left, Vector128<ushort> right) => TestC(left, right);
+ public static bool TestC(Vector128<int> left, Vector128<int> right) => TestC(left, right);
+ public static bool TestC(Vector128<uint> left, Vector128<uint> right) => TestC(left, right);
+ public static bool TestC(Vector128<long> left, Vector128<long> right) => TestC(left, right);
+ public static bool TestC(Vector128<ulong> left, Vector128<ulong> right) => TestC(left, right);
+
+ /// <summary>
+ /// int _mm_test_mix_ones_zeros (__m128i a, __m128i mask)
+ /// PTEST xmm, xmm/m128
+ /// </summary>
+ public static bool TestMixOnesZeros(Vector128<sbyte> left, Vector128<sbyte> right) => TestMixOnesZeros(left, right);
+ public static bool TestMixOnesZeros(Vector128<byte> left, Vector128<byte> right) => TestMixOnesZeros(left, right);
+ public static bool TestMixOnesZeros(Vector128<short> left, Vector128<short> right) => TestMixOnesZeros(left, right);
+ public static bool TestMixOnesZeros(Vector128<ushort> left, Vector128<ushort> right) => TestMixOnesZeros(left, right);
+ public static bool TestMixOnesZeros(Vector128<int> left, Vector128<int> right) => TestMixOnesZeros(left, right);
+ public static bool TestMixOnesZeros(Vector128<uint> left, Vector128<uint> right) => TestMixOnesZeros(left, right);
+ public static bool TestMixOnesZeros(Vector128<long> left, Vector128<long> right) => TestMixOnesZeros(left, right);
+ public static bool TestMixOnesZeros(Vector128<ulong> left, Vector128<ulong> right) => TestMixOnesZeros(left, right);
+
+ /// <summary>
+ /// int _mm_testnzc_si128 (__m128i a, __m128i b)
+ /// PTEST xmm, xmm/m128
+ /// </summary>
+ public static bool TestNotZAndNotC(Vector128<sbyte> left, Vector128<sbyte> right) => TestNotZAndNotC(left, right);
+ public static bool TestNotZAndNotC(Vector128<byte> left, Vector128<byte> right) => TestNotZAndNotC(left, right);
+ public static bool TestNotZAndNotC(Vector128<short> left, Vector128<short> right) => TestNotZAndNotC(left, right);
+ public static bool TestNotZAndNotC(Vector128<ushort> left, Vector128<ushort> right) => TestNotZAndNotC(left, right);
+ public static bool TestNotZAndNotC(Vector128<int> left, Vector128<int> right) => TestNotZAndNotC(left, right);
+ public static bool TestNotZAndNotC(Vector128<uint> left, Vector128<uint> right) => TestNotZAndNotC(left, right);
+ public static bool TestNotZAndNotC(Vector128<long> left, Vector128<long> right) => TestNotZAndNotC(left, right);
+ public static bool TestNotZAndNotC(Vector128<ulong> left, Vector128<ulong> right) => TestNotZAndNotC(left, right);
+
+ /// <summary>
+ /// int _mm_testz_si128 (__m128i a, __m128i b)
+ /// PTEST xmm, xmm/m128
+ /// </summary>
+ public static bool TestZ(Vector128<sbyte> left, Vector128<sbyte> right) => TestZ(left, right);
+ public static bool TestZ(Vector128<byte> left, Vector128<byte> right) => TestZ(left, right);
+ public static bool TestZ(Vector128<short> left, Vector128<short> right) => TestZ(left, right);
+ public static bool TestZ(Vector128<ushort> left, Vector128<ushort> right) => TestZ(left, right);
+ public static bool TestZ(Vector128<int> left, Vector128<int> right) => TestZ(left, right);
+ public static bool TestZ(Vector128<uint> left, Vector128<uint> right) => TestZ(left, right);
+ public static bool TestZ(Vector128<long> left, Vector128<long> right) => TestZ(left, right);
+ public static bool TestZ(Vector128<ulong> left, Vector128<ulong> right) => TestZ(left, right);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse42.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse42.PlatformNotSupported.cs
new file mode 100644
index 000000000..8ea2d6f07
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse42.PlatformNotSupported.cs
@@ -0,0 +1,304 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSE4.2 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Sse42 : Sse41
+ {
+ internal Sse42() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// int _mm_cmpistra (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrc (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistro (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrs (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrz (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareImplicitLength(Vector128<sbyte> left, Vector128<sbyte> right, ResultsFlag flag, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpistra (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrc (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistro (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrs (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrz (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareImplicitLength(Vector128<byte> left, Vector128<byte> right, ResultsFlag flag, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpistra (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrc (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistro (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrs (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrz (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareImplicitLength(Vector128<short> left, Vector128<short> right, ResultsFlag flag, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+
+ /// <summary>
+ /// int _mm_cmpistra (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrc (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistro (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrs (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrz (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareImplicitLength(Vector128<ushort> left, Vector128<ushort> right, ResultsFlag flag, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpestra (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrc (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestro (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrs (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrz (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareExplicitLength(Vector128<sbyte> left, byte leftLength, Vector128<sbyte> right, byte rightLength, ResultsFlag flag, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpestra (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrc (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestro (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrs (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrz (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareExplicitLength(Vector128<byte> left, byte leftLength, Vector128<byte> right, byte rightLength, ResultsFlag flag, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpestra (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrc (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestro (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrs (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrz (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareExplicitLength(Vector128<short> left, byte leftLength, Vector128<short> right, byte rightLength, ResultsFlag flag, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpestra (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrc (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestro (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrs (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrz (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareExplicitLength(Vector128<ushort> left, byte leftLength, Vector128<ushort> right, byte rightLength, ResultsFlag flag, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpistri (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareImplicitLengthIndex(Vector128<sbyte> left, Vector128<sbyte> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpistri (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareImplicitLengthIndex(Vector128<byte> left, Vector128<byte> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpistri (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareImplicitLengthIndex(Vector128<short> left, Vector128<short> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpistri (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareImplicitLengthIndex(Vector128<ushort> left, Vector128<ushort> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpestri (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareExplicitLengthIndex(Vector128<sbyte> left, byte leftLength, Vector128<sbyte> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpestri (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareExplicitLengthIndex(Vector128<byte> left, byte leftLength, Vector128<byte> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpestri (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareExplicitLengthIndex(Vector128<short> left, byte leftLength, Vector128<short> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// int _mm_cmpestri (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareExplicitLengthIndex(Vector128<ushort> left, byte leftLength, Vector128<ushort> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareImplicitLengthBitMask(Vector128<sbyte> left, Vector128<sbyte> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareImplicitLengthBitMask(Vector128<byte> left, Vector128<byte> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareImplicitLengthBitMask(Vector128<short> left, Vector128<short> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareImplicitLengthBitMask(Vector128<ushort> left, Vector128<ushort> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareImplicitLengthUnitMask(Vector128<sbyte> left, Vector128<sbyte> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareImplicitLengthUnitMask(Vector128<byte> left, Vector128<byte> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareImplicitLengthUnitMask(Vector128<short> left, Vector128<short> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareImplicitLengthUnitMask(Vector128<ushort> left, Vector128<ushort> right, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareExplicitLengthBitMask(Vector128<sbyte> left, byte leftLength, Vector128<sbyte> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareExplicitLengthBitMask(Vector128<byte> left, byte leftLength, Vector128<byte> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareExplicitLengthBitMask(Vector128<short> left, byte leftLength, Vector128<short> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareExplicitLengthBitMask(Vector128<ushort> left, byte leftLength, Vector128<ushort> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareExplicitLengthUnitMask(Vector128<sbyte> left, byte leftLength, Vector128<sbyte> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareExplicitLengthUnitMask(Vector128<byte> left, byte leftLength, Vector128<byte> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareExplicitLengthUnitMask(Vector128<short> left, byte leftLength, Vector128<short> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareExplicitLengthUnitMask(Vector128<ushort> left, byte leftLength, Vector128<ushort> right, byte rightLength, StringComparisonMode mode) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_cmpgt_epi64 (__m128i a, __m128i b)
+ /// PCMPGTQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> CompareGreaterThan(Vector128<long> left, Vector128<long> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// unsigned int _mm_crc32_u8 (unsigned int crc, unsigned char v)
+ /// CRC32 reg, reg/m8
+ /// </summary>
+ public static uint Crc32(uint crc, byte data) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned int _mm_crc32_u16 (unsigned int crc, unsigned short v)
+ /// CRC32 reg, reg/m16
+ /// </summary>
+ public static uint Crc32(uint crc, ushort data) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned int _mm_crc32_u32 (unsigned int crc, unsigned int v)
+ /// CRC32 reg, reg/m32
+ /// </summary>
+ public static uint Crc32(uint crc, uint data) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// unsigned __int64 _mm_crc32_u64 (unsigned __int64 crc, unsigned __int64 v)
+ /// CRC32 reg, reg/m64
+ /// </summary>
+ public static ulong Crc32(ulong crc, ulong data) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse42.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse42.cs
new file mode 100644
index 000000000..a7353382b
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Sse42.cs
@@ -0,0 +1,304 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSE4.2 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Sse42 : Sse41
+ {
+ internal Sse42() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// int _mm_cmpistra (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrc (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistro (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrs (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrz (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareImplicitLength(Vector128<sbyte> left, Vector128<sbyte> right, ResultsFlag flag, StringComparisonMode mode) => CompareImplicitLength(left, right, flag, mode);
+
+ /// <summary>
+ /// int _mm_cmpistra (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrc (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistro (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrs (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrz (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareImplicitLength(Vector128<byte> left, Vector128<byte> right, ResultsFlag flag, StringComparisonMode mode) => CompareImplicitLength(left, right, flag, mode);
+
+ /// <summary>
+ /// int _mm_cmpistra (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrc (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistro (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrs (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrz (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareImplicitLength(Vector128<short> left, Vector128<short> right, ResultsFlag flag, StringComparisonMode mode) => CompareImplicitLength(left, right, flag, mode);
+
+
+ /// <summary>
+ /// int _mm_cmpistra (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrc (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistro (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrs (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpistrz (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareImplicitLength(Vector128<ushort> left, Vector128<ushort> right, ResultsFlag flag, StringComparisonMode mode) => CompareImplicitLength(left, right, flag, mode);
+
+ /// <summary>
+ /// int _mm_cmpestra (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrc (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestro (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrs (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrz (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareExplicitLength(Vector128<sbyte> left, byte leftLength, Vector128<sbyte> right, byte rightLength, ResultsFlag flag, StringComparisonMode mode) => CompareExplicitLength(left, leftLength, right, rightLength, flag, mode);
+
+ /// <summary>
+ /// int _mm_cmpestra (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrc (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestro (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrs (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrz (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareExplicitLength(Vector128<byte> left, byte leftLength, Vector128<byte> right, byte rightLength, ResultsFlag flag, StringComparisonMode mode) => CompareExplicitLength(left, leftLength, right, rightLength, flag, mode);
+
+ /// <summary>
+ /// int _mm_cmpestra (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrc (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestro (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrs (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrz (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareExplicitLength(Vector128<short> left, byte leftLength, Vector128<short> right, byte rightLength, ResultsFlag flag, StringComparisonMode mode) => CompareExplicitLength(left, leftLength, right, rightLength, flag, mode);
+
+ /// <summary>
+ /// int _mm_cmpestra (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrc (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestro (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrs (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// int _mm_cmpestrz (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static bool CompareExplicitLength(Vector128<ushort> left, byte leftLength, Vector128<ushort> right, byte rightLength, ResultsFlag flag, StringComparisonMode mode) => CompareExplicitLength(left, leftLength, right, rightLength, flag, mode);
+
+ /// <summary>
+ /// int _mm_cmpistri (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareImplicitLengthIndex(Vector128<sbyte> left, Vector128<sbyte> right, StringComparisonMode mode) => CompareImplicitLengthIndex(left, right, mode);
+
+ /// <summary>
+ /// int _mm_cmpistri (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareImplicitLengthIndex(Vector128<byte> left, Vector128<byte> right, StringComparisonMode mode) => CompareImplicitLengthIndex(left, right, mode);
+
+ /// <summary>
+ /// int _mm_cmpistri (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareImplicitLengthIndex(Vector128<short> left, Vector128<short> right, StringComparisonMode mode) => CompareImplicitLengthIndex(left, right, mode);
+
+ /// <summary>
+ /// int _mm_cmpistri (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareImplicitLengthIndex(Vector128<ushort> left, Vector128<ushort> right, StringComparisonMode mode) => CompareImplicitLengthIndex(left, right, mode);
+
+ /// <summary>
+ /// int _mm_cmpestri (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareExplicitLengthIndex(Vector128<sbyte> left, byte leftLength, Vector128<sbyte> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthIndex(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// int _mm_cmpestri (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareExplicitLengthIndex(Vector128<byte> left, byte leftLength, Vector128<byte> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthIndex(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// int _mm_cmpestri (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareExplicitLengthIndex(Vector128<short> left, byte leftLength, Vector128<short> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthIndex(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// int _mm_cmpestri (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRI xmm, xmm/m128, imm8
+ /// </summary>
+ public static int CompareExplicitLengthIndex(Vector128<ushort> left, byte leftLength, Vector128<ushort> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthIndex(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareImplicitLengthBitMask(Vector128<sbyte> left, Vector128<sbyte> right, StringComparisonMode mode) => CompareImplicitLengthBitMask(left, right, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareImplicitLengthBitMask(Vector128<byte> left, Vector128<byte> right, StringComparisonMode mode) => CompareImplicitLengthBitMask(left, right, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareImplicitLengthBitMask(Vector128<short> left, Vector128<short> right, StringComparisonMode mode) => CompareImplicitLengthBitMask(left, right, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareImplicitLengthBitMask(Vector128<ushort> left, Vector128<ushort> right, StringComparisonMode mode) => CompareImplicitLengthBitMask(left, right, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareImplicitLengthUnitMask(Vector128<sbyte> left, Vector128<sbyte> right, StringComparisonMode mode) => CompareImplicitLengthUnitMask(left, right, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareImplicitLengthUnitMask(Vector128<byte> left, Vector128<byte> right, StringComparisonMode mode) => CompareImplicitLengthUnitMask(left, right, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareImplicitLengthUnitMask(Vector128<short> left, Vector128<short> right, StringComparisonMode mode) => CompareImplicitLengthUnitMask(left, right, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpistrm (__m128i a, __m128i b, const int imm8)
+ /// PCMPISTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareImplicitLengthUnitMask(Vector128<ushort> left, Vector128<ushort> right, StringComparisonMode mode) => CompareImplicitLengthUnitMask(left, right, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareExplicitLengthBitMask(Vector128<sbyte> left, byte leftLength, Vector128<sbyte> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthBitMask(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareExplicitLengthBitMask(Vector128<byte> left, byte leftLength, Vector128<byte> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthBitMask(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareExplicitLengthBitMask(Vector128<short> left, byte leftLength, Vector128<short> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthBitMask(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareExplicitLengthBitMask(Vector128<ushort> left, byte leftLength, Vector128<ushort> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthBitMask(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareExplicitLengthUnitMask(Vector128<sbyte> left, byte leftLength, Vector128<sbyte> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthUnitMask(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<byte> CompareExplicitLengthUnitMask(Vector128<byte> left, byte leftLength, Vector128<byte> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthUnitMask(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareExplicitLengthUnitMask(Vector128<short> left, byte leftLength, Vector128<short> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthUnitMask(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpestrm (__m128i a, int la, __m128i b, int lb, const int imm8)
+ /// PCMPESTRM xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<ushort> CompareExplicitLengthUnitMask(Vector128<ushort> left, byte leftLength, Vector128<ushort> right, byte rightLength, StringComparisonMode mode) => CompareExplicitLengthUnitMask(left, leftLength, right, rightLength, mode);
+
+ /// <summary>
+ /// __m128i _mm_cmpgt_epi64 (__m128i a, __m128i b)
+ /// PCMPGTQ xmm, xmm/m128
+ /// </summary>
+ public static Vector128<long> CompareGreaterThan(Vector128<long> left, Vector128<long> right) => CompareGreaterThan(left, right);
+
+ /// <summary>
+ /// unsigned int _mm_crc32_u8 (unsigned int crc, unsigned char v)
+ /// CRC32 reg, reg/m8
+ /// </summary>
+ public static uint Crc32(uint crc, byte data) => Crc32(crc, data);
+ /// <summary>
+ /// unsigned int _mm_crc32_u16 (unsigned int crc, unsigned short v)
+ /// CRC32 reg, reg/m16
+ /// </summary>
+ public static uint Crc32(uint crc, ushort data) => Crc32(crc, data);
+ /// <summary>
+ /// unsigned int _mm_crc32_u32 (unsigned int crc, unsigned int v)
+ /// CRC32 reg, reg/m32
+ /// </summary>
+ public static uint Crc32(uint crc, uint data) => Crc32(crc, data);
+ /// <summary>
+ /// unsigned __int64 _mm_crc32_u64 (unsigned __int64 crc, unsigned __int64 v)
+ /// CRC32 reg, reg/m64
+ /// </summary>
+ public static ulong Crc32(ulong crc, ulong data) => Crc32(crc, data);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Ssse3.PlatformNotSupported.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Ssse3.PlatformNotSupported.cs
new file mode 100644
index 000000000..a99f7f6a6
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Ssse3.PlatformNotSupported.cs
@@ -0,0 +1,116 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSSE3 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Ssse3 : Sse3
+ {
+ internal Ssse3() { }
+
+ public new static bool IsSupported { get { return false; } }
+
+ /// <summary>
+ /// __m128i _mm_abs_epi8 (__m128i a)
+ /// PABSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Abs(Vector128<sbyte> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_abs_epi16 (__m128i a)
+ /// PABSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Abs(Vector128<short> value) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_abs_epi32 (__m128i a)
+ /// PABSD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Abs(Vector128<int> value) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_alignr_epi8 (__m128i a, __m128i b, int count)
+ /// PALIGNR xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<sbyte> AlignRight(Vector128<sbyte> left, Vector128<sbyte> right, byte mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_hadd_epi16 (__m128i a, __m128i b)
+ /// PHADDW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> HorizontalAdd(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_hadd_epi32 (__m128i a, __m128i b)
+ /// PHADDD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> HorizontalAdd(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_hadds_epi16 (__m128i a, __m128i b)
+ /// PHADDSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> HorizontalAddSaturate(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_hsub_epi16 (__m128i a, __m128i b)
+ /// PHSUBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> HorizontalSubtract(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_hsub_epi32 (__m128i a, __m128i b)
+ /// PHSUBD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> HorizontalSubtract(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_hsubs_epi16 (__m128i a, __m128i b)
+ /// PHSUBSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> HorizontalSubtractSaturate(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_maddubs_epi16 (__m128i a, __m128i b)
+ /// PMADDUBSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> MultiplyAddAdjacent(Vector128<byte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_mulhrs_epi16 (__m128i a, __m128i b)
+ /// PMULHRSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> MultiplyHighRoundScale(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_shuffle_epi8 (__m128i a, __m128i b)
+ /// PSHUFB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Shuffle(Vector128<sbyte> value, Vector128<sbyte> mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_shuffle_epi8 (__m128i a, __m128i b)
+ /// PSHUFB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Shuffle(Vector128<byte> value, Vector128<byte> mask) { throw new PlatformNotSupportedException(); }
+
+ /// <summary>
+ /// __m128i _mm_sign_epi8 (__m128i a, __m128i b)
+ /// PSIGNB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Sign(Vector128<sbyte> left, Vector128<sbyte> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sign_epi16 (__m128i a, __m128i b)
+ /// PSIGNW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Sign(Vector128<short> left, Vector128<short> right) { throw new PlatformNotSupportedException(); }
+ /// <summary>
+ /// __m128i _mm_sign_epi32 (__m128i a, __m128i b)
+ /// PSIGND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Sign(Vector128<int> left, Vector128<int> right) { throw new PlatformNotSupportedException(); }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Ssse3.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Ssse3.cs
new file mode 100644
index 000000000..6fd777887
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/X86/Ssse3.cs
@@ -0,0 +1,116 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Intrinsics;
+
+namespace System.Runtime.Intrinsics.X86
+{
+ /// <summary>
+ /// This class provides access to Intel SSSE3 hardware instructions via intrinsics
+ /// </summary>
+ [CLSCompliant(false)]
+ public abstract class Ssse3 : Sse3
+ {
+ internal Ssse3() { }
+
+ public new static bool IsSupported { get => IsSupported; }
+
+ /// <summary>
+ /// __m128i _mm_abs_epi8 (__m128i a)
+ /// PABSB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Abs(Vector128<sbyte> value) => Abs(value);
+ /// <summary>
+ /// __m128i _mm_abs_epi16 (__m128i a)
+ /// PABSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<ushort> Abs(Vector128<short> value) => Abs(value);
+ /// <summary>
+ /// __m128i _mm_abs_epi32 (__m128i a)
+ /// PABSD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<uint> Abs(Vector128<int> value) => Abs(value);
+
+ /// <summary>
+ /// __m128i _mm_alignr_epi8 (__m128i a, __m128i b, int count)
+ /// PALIGNR xmm, xmm/m128, imm8
+ /// </summary>
+ public static Vector128<sbyte> AlignRight(Vector128<sbyte> left, Vector128<sbyte> right, byte mask) => AlignRight(left, right, mask);
+
+ /// <summary>
+ /// __m128i _mm_hadd_epi16 (__m128i a, __m128i b)
+ /// PHADDW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> HorizontalAdd(Vector128<short> left, Vector128<short> right) => HorizontalAdd(left, right);
+ /// <summary>
+ /// __m128i _mm_hadd_epi32 (__m128i a, __m128i b)
+ /// PHADDD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> HorizontalAdd(Vector128<int> left, Vector128<int> right) => HorizontalAdd(left, right);
+
+ /// <summary>
+ /// __m128i _mm_hadds_epi16 (__m128i a, __m128i b)
+ /// PHADDSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> HorizontalAddSaturate(Vector128<short> left, Vector128<short> right) => HorizontalAddSaturate(left, right);
+
+ /// <summary>
+ /// __m128i _mm_hsub_epi16 (__m128i a, __m128i b)
+ /// PHSUBW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> HorizontalSubtract(Vector128<short> left, Vector128<short> right) => HorizontalSubtract(left, right);
+ /// <summary>
+ /// __m128i _mm_hsub_epi32 (__m128i a, __m128i b)
+ /// PHSUBD xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> HorizontalSubtract(Vector128<int> left, Vector128<int> right) => HorizontalSubtract(left, right);
+
+ /// <summary>
+ /// __m128i _mm_hsubs_epi16 (__m128i a, __m128i b)
+ /// PHSUBSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> HorizontalSubtractSaturate(Vector128<short> left, Vector128<short> right) => HorizontalSubtractSaturate(left, right);
+
+ /// <summary>
+ /// __m128i _mm_maddubs_epi16 (__m128i a, __m128i b)
+ /// PMADDUBSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> MultiplyAddAdjacent(Vector128<byte> left, Vector128<sbyte> right) => MultiplyAddAdjacent(left, right);
+
+ /// <summary>
+ /// __m128i _mm_mulhrs_epi16 (__m128i a, __m128i b)
+ /// PMULHRSW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> MultiplyHighRoundScale(Vector128<short> left, Vector128<short> right) => MultiplyHighRoundScale(left, right);
+
+ /// <summary>
+ /// __m128i _mm_shuffle_epi8 (__m128i a, __m128i b)
+ /// PSHUFB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Shuffle(Vector128<sbyte> value, Vector128<sbyte> mask) => Shuffle(value, mask);
+
+ /// <summary>
+ /// __m128i _mm_shuffle_epi8 (__m128i a, __m128i b)
+ /// PSHUFB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<byte> Shuffle(Vector128<byte> value, Vector128<byte> mask) => Shuffle(value, mask);
+
+ /// <summary>
+ /// __m128i _mm_sign_epi8 (__m128i a, __m128i b)
+ /// PSIGNB xmm, xmm/m128
+ /// </summary>
+ public static Vector128<sbyte> Sign(Vector128<sbyte> left, Vector128<sbyte> right) => Sign(left, right);
+ /// <summary>
+ /// __m128i _mm_sign_epi16 (__m128i a, __m128i b)
+ /// PSIGNW xmm, xmm/m128
+ /// </summary>
+ public static Vector128<short> Sign(Vector128<short> left, Vector128<short> right) => Sign(left, right);
+ /// <summary>
+ /// __m128i _mm_sign_epi32 (__m128i a, __m128i b)
+ /// PSIGND xmm, xmm/m128
+ /// </summary>
+ public static Vector128<int> Sign(Vector128<int> left, Vector128<int> right) => Sign(left, right);
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Remoting/ObjectHandle.cs b/src/System.Private.CoreLib/shared/System/Runtime/Remoting/ObjectHandle.cs
new file mode 100644
index 000000000..a47aaf9ca
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Remoting/ObjectHandle.cs
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.Remoting
+{
+ public class ObjectHandle : MarshalByRefObject
+ {
+ private object _wrappedObject;
+
+ private ObjectHandle()
+ {
+ }
+
+ public ObjectHandle(object o)
+ {
+ _wrappedObject = o;
+ }
+
+ public object Unwrap()
+ {
+ return _wrappedObject;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationException.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationException.cs
index 1c9c21eab..92c01ee30 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationException.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationException.cs
@@ -10,7 +10,7 @@ namespace System.Runtime.Serialization
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public class SerializationException : SystemException
{
- private static String s_nullMessage = SR.SerializationException;
+ private static string s_nullMessage = SR.SerializationException;
// Creates a new SerializationException with its message
// string set to a default message.
@@ -20,13 +20,13 @@ namespace System.Runtime.Serialization
HResult = HResults.COR_E_SERIALIZATION;
}
- public SerializationException(String message)
+ public SerializationException(string message)
: base(message)
{
HResult = HResults.COR_E_SERIALIZATION;
}
- public SerializationException(String message, Exception innerException)
+ public SerializationException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_SERIALIZATION;
diff --git a/src/System.Private.CoreLib/src/System/Runtime/Serialization/SerializationInfo.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfo.cs
index 7bb19995b..a97418963 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/Serialization/SerializationInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfo.cs
@@ -1,13 +1,13 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Diagnostics;
-using System.Reflection;
namespace System.Runtime.Serialization
{
+ /// <summary>The structure for holding all of the data needed for object serialization and deserialization.</summary>
public sealed class SerializationInfo
{
private const int DefaultSize = 4;
@@ -19,19 +19,19 @@ namespace System.Runtime.Serialization
private Type[] _types;
private int _count;
private Dictionary<string, int> _nameToIndex;
-
private IFormatterConverter _converter;
private string _rootTypeName;
private string _rootTypeAssemblyName;
private Type _rootType;
[CLSCompliant(false)]
- public SerializationInfo(Type type, IFormatterConverter converter)
+ public SerializationInfo(Type type, IFormatterConverter converter)
{
- if (type == null)
+ if ((object)type == null)
{
throw new ArgumentNullException(nameof(type));
}
+
if (converter == null)
{
throw new ArgumentNullException(nameof(converter));
@@ -44,7 +44,9 @@ namespace System.Runtime.Serialization
_names = new string[DefaultSize];
_values = new object[DefaultSize];
_types = new Type[DefaultSize];
+
_nameToIndex = new Dictionary<string, int>();
+
_converter = converter;
}
@@ -79,7 +81,6 @@ namespace System.Runtime.Serialization
{
throw new ArgumentNullException(nameof(value));
}
-
_rootTypeAssemblyName = value;
IsAssemblyNameSetExplicit = true;
}
@@ -91,7 +92,7 @@ namespace System.Runtime.Serialization
public void SetType(Type type)
{
- if (type == null)
+ if ((object)type == null)
{
throw new ArgumentNullException(nameof(type));
}
@@ -115,7 +116,7 @@ namespace System.Runtime.Serialization
private void ExpandArrays()
{
int newSize;
- Debug.Assert(_names.Length == _count);
+ Debug.Assert(_names.Length == _count, "[SerializationInfo.ExpandArrays]_names.Length == _count");
newSize = (_count * 2);
@@ -129,38 +130,18 @@ namespace System.Runtime.Serialization
}
// Allocate more space and copy the data
-
string[] newMembers = new string[newSize];
- Array.Copy(_names, 0, newMembers, 0, _count);
- _names = newMembers;
-
object[] newData = new object[newSize];
- Array.Copy(_values, 0, newData, 0, _count);
- _values = newData;
-
Type[] newTypes = new Type[newSize];
- Array.Copy(_types, 0, newTypes, 0, _count);
- _types = newTypes;
- }
- // This isn't a public API, but it gets invoked dynamically by
- // BinaryFormatter
- public void UpdateValue(string name, object value, Type type)
- {
- Debug.Assert(null != name, "[SerializationInfo.UpdateValue]name!=null");
- Debug.Assert(null != value, "[SerializationInfo.UpdateValue]value!=null");
- Debug.Assert(null != type, "[SerializationInfo.UpdateValue]type!=null");
+ Array.Copy(_names, newMembers, _count);
+ Array.Copy(_values, newData, _count);
+ Array.Copy(_types, newTypes, _count);
- int index = FindElement(name);
- if (index < 0)
- {
- AddValueInternal(name, value, type);
- }
- else
- {
- _values[index] = value;
- _types[index] = type;
- }
+ // Assign the new arrays back to the member vars.
+ _names = newMembers;
+ _values = newData;
+ _types = newTypes;
}
public void AddValue(string name, object value, Type type)
@@ -170,7 +151,7 @@ namespace System.Runtime.Serialization
throw new ArgumentNullException(nameof(name));
}
- if (type == null)
+ if ((object)type == null)
{
throw new ArgumentNullException(nameof(type));
}
@@ -192,76 +173,76 @@ namespace System.Runtime.Serialization
public void AddValue(string name, bool value)
{
- AddValue(name, value, typeof(bool));
+ AddValue(name, (object)value, typeof(bool));
}
public void AddValue(string name, char value)
{
- AddValue(name, value, typeof(char));
+ AddValue(name, (object)value, typeof(char));
}
[CLSCompliant(false)]
public void AddValue(string name, sbyte value)
{
- AddValue(name, value, typeof(sbyte));
+ AddValue(name, (object)value, typeof(sbyte));
}
public void AddValue(string name, byte value)
{
- AddValue(name, value, typeof(byte));
+ AddValue(name, (object)value, typeof(byte));
}
public void AddValue(string name, short value)
{
- AddValue(name, value, typeof(short));
+ AddValue(name, (object)value, typeof(short));
}
[CLSCompliant(false)]
public void AddValue(string name, ushort value)
{
- AddValue(name, value, typeof(ushort));
+ AddValue(name, (object)value, typeof(ushort));
}
public void AddValue(string name, int value)
{
- AddValue(name, value, typeof(int));
+ AddValue(name, (object)value, typeof(int));
}
[CLSCompliant(false)]
public void AddValue(string name, uint value)
{
- AddValue(name, value, typeof(uint));
+ AddValue(name, (object)value, typeof(uint));
}
public void AddValue(string name, long value)
{
- AddValue(name, value, typeof(long));
+ AddValue(name, (object)value, typeof(long));
}
[CLSCompliant(false)]
public void AddValue(string name, ulong value)
{
- AddValue(name, value, typeof(ulong));
+ AddValue(name, (object)value, typeof(ulong));
}
public void AddValue(string name, float value)
{
- AddValue(name, value, typeof(float));
+ AddValue(name, (object)value, typeof(float));
}
public void AddValue(string name, double value)
{
- AddValue(name, value, typeof(double));
+ AddValue(name, (object)value, typeof(double));
}
public void AddValue(string name, decimal value)
{
- AddValue(name, value, typeof(decimal));
+ AddValue(name, (object)value, typeof(decimal));
}
public void AddValue(string name, DateTime value)
{
- AddValue(name, value, typeof(DateTime));
+ AddValue(name, (object)value, typeof(DateTime));
}
internal void AddValueInternal(string name, object value, Type type)
@@ -285,13 +266,48 @@ namespace System.Runtime.Serialization
_count++;
}
+ /// <summary>
+ /// Finds the value if it exists in the current data. If it does, we replace
+ /// the values, if not, we append it to the end. This is useful to the
+ /// ObjectManager when it's performing fixups.
+ ///
+ /// All error checking is done with asserts. Although public in coreclr,
+ /// it's not exposed in a contract and is only meant to be used by corefx.
+ ///
+ /// This isn't a public API, but it gets invoked dynamically by
+ /// BinaryFormatter
+ ///
+ /// This should not be used by clients: exposing out this functionality would allow children
+ /// to overwrite their parent's values. It is public in order to give corefx access to it for
+ /// its ObjectManager implementation, but it should not be exposed out of a contract.
+ /// </summary>
+ /// <param name="name"> The name of the data to be updated.</param>
+ /// <param name="value"> The new value.</param>
+ /// <param name="type"> The type of the data being added.</param>
+ public void UpdateValue(string name, object value, Type type)
+ {
+ Debug.Assert(null != name, "[SerializationInfo.UpdateValue]name!=null");
+ Debug.Assert(null != value, "[SerializationInfo.UpdateValue]value!=null");
+ Debug.Assert(null != (object)type, "[SerializationInfo.UpdateValue]type!=null");
+
+ int index = FindElement(name);
+ if (index < 0)
+ {
+ AddValueInternal(name, value, type);
+ }
+ else
+ {
+ _values[index] = value;
+ _types[index] = type;
+ }
+ }
+
private int FindElement(string name)
{
if (null == name)
{
throw new ArgumentNullException(nameof(name));
}
-
int index;
if (_nameToIndex.TryGetValue(name, out index))
{
@@ -300,6 +316,14 @@ namespace System.Runtime.Serialization
return -1;
}
+ /// <summary>
+ /// Gets the location of a particular member and then returns
+ /// the value of the element at that location. The type of the member is
+ /// returned in the foundType field.
+ /// </summary>
+ /// <param name="name"> The name of the element to find.</param>
+ /// <param name="foundType"> The type of the element associated with the given name.</param>
+ /// <returns>The value of the element at the position associated with name.</returns>
private object GetElement(string name, out Type foundType)
{
int index = FindElement(name);
@@ -308,11 +332,11 @@ namespace System.Runtime.Serialization
throw new SerializationException(SR.Format(SR.Serialization_NotFound, name));
}
- Debug.Assert(index < _values.Length);
- Debug.Assert(index < _types.Length);
+ Debug.Assert(index < _values.Length, "[SerializationInfo.GetElement]index<_values.Length");
+ Debug.Assert(index < _types.Length, "[SerializationInfo.GetElement]index<_types.Length");
foundType = _types[index];
- Debug.Assert(foundType != null);
+ Debug.Assert((object)foundType != null, "[SerializationInfo.GetElement]foundType!=null");
return _values[index];
}
@@ -325,40 +349,46 @@ namespace System.Runtime.Serialization
return null;
}
- Debug.Assert(index < _values.Length, "[SerializationInfo.GetElement]index<m_data.Length");
- Debug.Assert(index < _types.Length, "[SerializationInfo.GetElement]index<m_types.Length");
+ Debug.Assert(index < _values.Length, "[SerializationInfo.GetElement]index<_values.Length");
+ Debug.Assert(index < _types.Length, "[SerializationInfo.GetElement]index<_types.Length");
foundType = _types[index];
- Debug.Assert(foundType != null, "[SerializationInfo.GetElement]foundType!=null");
+ Debug.Assert((object)foundType != null, "[SerializationInfo.GetElement]foundType!=null");
return _values[index];
}
public object GetValue(string name, Type type)
{
- if (type == null)
+ if ((object)type == null)
{
throw new ArgumentNullException(nameof(type));
}
+ if (!type.IsRuntimeImplemented())
+ throw new ArgumentException(SR.Argument_MustBeRuntimeType);
Type foundType;
object value;
value = GetElement(name, out foundType);
+
if (ReferenceEquals(foundType, type) || type.IsAssignableFrom(foundType) || value == null)
{
return value;
}
- Debug.Assert(_converter != null);
+ Debug.Assert(_converter != null, "[SerializationInfo.GetValue]_converter!=null");
return _converter.Convert(value, type);
}
internal object GetValueNoThrow(string name, Type type)
{
- Debug.Assert(type != null, "[SerializationInfo.GetValue]type ==null");
-
Type foundType;
- object value = GetElementNoThrow(name, out foundType);
+ object value;
+
+ Debug.Assert((object)type != null, "[SerializationInfo.GetValue]type ==null");
+ Debug.Assert(type.IsRuntimeImplemented(), "[SerializationInfo.GetValue]type is not a runtime type");
+
+ value = GetElementNoThrow(name, out foundType);
if (value == null)
return null;
@@ -367,7 +397,8 @@ namespace System.Runtime.Serialization
return value;
}
- Debug.Assert(_converter != null, "[SerializationInfo.GetValue]m_converter!=null");
+ Debug.Assert(_converter != null, "[SerializationInfo.GetValue]_converter!=null");
+
return _converter.Convert(value, type);
}
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfoEnumerator.cs b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfoEnumerator.cs
index 639951073..ba84e6542 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfoEnumerator.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Serialization/SerializationInfoEnumerator.cs
@@ -7,11 +7,11 @@ using System.Diagnostics;
namespace System.Runtime.Serialization
{
- public struct SerializationEntry
+ public readonly struct SerializationEntry
{
- private string _name;
- private object _value;
- private Type _type;
+ private readonly string _name;
+ private readonly object _value;
+ private readonly Type _type;
internal SerializationEntry(string entryName, object entryValue, Type entryType)
{
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Versioning/TargetFrameworkAttribute.cs b/src/System.Private.CoreLib/shared/System/Runtime/Versioning/TargetFrameworkAttribute.cs
index a81906638..dcb14f0ef 100644
--- a/src/System.Private.CoreLib/shared/System/Runtime/Versioning/TargetFrameworkAttribute.cs
+++ b/src/System.Private.CoreLib/shared/System/Runtime/Versioning/TargetFrameworkAttribute.cs
@@ -19,11 +19,11 @@ namespace System.Runtime.Versioning
[AttributeUsageAttribute(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)]
public sealed class TargetFrameworkAttribute : Attribute
{
- private String _frameworkName; // A target framework moniker
- private String _frameworkDisplayName;
+ private string _frameworkName; // A target framework moniker
+ private string _frameworkDisplayName;
// The frameworkName parameter is intended to be the string form of a FrameworkName instance.
- public TargetFrameworkAttribute(String frameworkName)
+ public TargetFrameworkAttribute(string frameworkName)
{
if (frameworkName == null)
throw new ArgumentNullException(nameof(frameworkName));
@@ -32,12 +32,12 @@ namespace System.Runtime.Versioning
// The target framework moniker that this assembly was compiled against.
// Use the FrameworkName class to interpret target framework monikers.
- public String FrameworkName
+ public string FrameworkName
{
get { return _frameworkName; }
}
- public String FrameworkDisplayName
+ public string FrameworkDisplayName
{
get { return _frameworkDisplayName; }
set { _frameworkDisplayName = value; }
diff --git a/src/System.Private.CoreLib/shared/System/SByte.cs b/src/System.Private.CoreLib/shared/System/SByte.cs
index c7cee2adc..e347e3b32 100644
--- a/src/System.Private.CoreLib/shared/System/SByte.cs
+++ b/src/System.Private.CoreLib/shared/System/SByte.cs
@@ -12,9 +12,9 @@ namespace System
[Serializable]
[CLSCompliant(false)] [StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct SByte : IComparable, IConvertible, IFormattable, IComparable<SByte>, IEquatable<SByte>, ISpanFormattable
+ public readonly struct SByte : IComparable, IConvertible, IFormattable, IComparable<sbyte>, IEquatable<sbyte>, ISpanFormattable
{
- private sbyte m_value; // Do not rename (binary serialization)
+ private readonly sbyte m_value; // Do not rename (binary serialization)
// The maximum value that a Byte may represent: 127.
public const sbyte MaxValue = (sbyte)0x7F;
@@ -29,36 +29,36 @@ namespace System
// null is considered to be less than any instance.
// If object is not of type SByte, this method throws an ArgumentException.
//
- public int CompareTo(Object obj)
+ public int CompareTo(object obj)
{
if (obj == null)
{
return 1;
}
- if (!(obj is SByte))
+ if (!(obj is sbyte))
{
throw new ArgumentException(SR.Arg_MustBeSByte);
}
- return m_value - ((SByte)obj).m_value;
+ return m_value - ((sbyte)obj).m_value;
}
- public int CompareTo(SByte value)
+ public int CompareTo(sbyte value)
{
return m_value - value;
}
// Determines whether two Byte objects are equal.
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is SByte))
+ if (!(obj is sbyte))
{
return false;
}
- return m_value == ((SByte)obj).m_value;
+ return m_value == ((sbyte)obj).m_value;
}
[NonVersionable]
- public bool Equals(SByte obj)
+ public bool Equals(sbyte obj)
{
return m_value == obj;
}
@@ -71,22 +71,22 @@ namespace System
// Provides a string representation of a byte.
- public override String ToString()
+ public override string ToString()
{
return Number.FormatInt32(m_value, null, null);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return Number.FormatInt32(m_value, null, provider);
}
- public String ToString(String format)
+ public string ToString(string format)
{
return ToString(format, null);
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
if (m_value < 0 && format != null && format.Length > 0 && (format[0] == 'X' || format[0] == 'x'))
{
@@ -107,14 +107,14 @@ namespace System
}
[CLSCompliant(false)]
- public static sbyte Parse(String s)
+ public static sbyte Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}
[CLSCompliant(false)]
- public static sbyte Parse(String s, NumberStyles style)
+ public static sbyte Parse(string s, NumberStyles style)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -122,7 +122,7 @@ namespace System
}
[CLSCompliant(false)]
- public static sbyte Parse(String s, IFormatProvider provider)
+ public static sbyte Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
@@ -133,7 +133,7 @@ namespace System
// NumberFormatInfo is assumed.
//
[CLSCompliant(false)]
- public static sbyte Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static sbyte Parse(string s, NumberStyles style, IFormatProvider provider)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -147,7 +147,7 @@ namespace System
return Parse(s, style, NumberFormatInfo.GetInstance(provider));
}
- private static sbyte Parse(String s, NumberStyles style, NumberFormatInfo info)
+ private static sbyte Parse(string s, NumberStyles style, NumberFormatInfo info)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, style, info);
@@ -167,7 +167,7 @@ namespace System
if ((style & NumberStyles.AllowHexSpecifier) != 0)
{ // We are parsing a hexadecimal number
- if ((i < 0) || i > Byte.MaxValue)
+ if ((i < 0) || i > byte.MaxValue)
{
throw new OverflowException(SR.Overflow_SByte);
}
@@ -179,7 +179,7 @@ namespace System
}
[CLSCompliant(false)]
- public static bool TryParse(String s, out SByte result)
+ public static bool TryParse(string s, out sbyte result)
{
if (s == null)
{
@@ -197,7 +197,7 @@ namespace System
}
[CLSCompliant(false)]
- public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out SByte result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out sbyte result)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
@@ -217,7 +217,7 @@ namespace System
return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
}
- private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out SByte result)
+ private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out sbyte result)
{
result = 0;
int i;
@@ -228,7 +228,7 @@ namespace System
if ((style & NumberStyles.AllowHexSpecifier) != 0)
{ // We are parsing a hexadecimal number
- if ((i < 0) || i > Byte.MaxValue)
+ if ((i < 0) || i > byte.MaxValue)
{
return false;
}
@@ -314,7 +314,7 @@ namespace System
return Convert.ToDouble(m_value);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -324,7 +324,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "SByte", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/Security/AccessControl/RegistryRights.cs b/src/System.Private.CoreLib/shared/System/Security/AccessControl/RegistryRights.cs
new file mode 100644
index 000000000..729e2f6b5
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Security/AccessControl/RegistryRights.cs
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Win32;
+
+namespace System.Security.AccessControl
+{
+ // We derived this enum from the definitions of KEY_READ and such from
+ // winnt.h and from MSDN, plus some experimental validation with regedit.
+ // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/registry_key_security_and_access_rights.asp
+ [Flags]
+#if REGISTRY_ASSEMBLY
+ public
+#else
+ internal
+#endif
+ enum RegistryRights
+ {
+ // No None field - An ACE with the value 0 cannot grant nor deny.
+ QueryValues = Interop.Advapi32.RegistryOperations.KEY_QUERY_VALUE, // 0x0001 query the values of a registry key
+ SetValue = Interop.Advapi32.RegistryOperations.KEY_SET_VALUE, // 0x0002 create, delete, or set a registry value
+ CreateSubKey = Interop.Advapi32.RegistryOperations.KEY_CREATE_SUB_KEY, // 0x0004 required to create a subkey of a specific key
+ EnumerateSubKeys = Interop.Advapi32.RegistryOperations.KEY_ENUMERATE_SUB_KEYS, // 0x0008 required to enumerate sub keys of a key
+ Notify = Interop.Advapi32.RegistryOperations.KEY_NOTIFY, // 0x0010 needed to request change notifications
+ CreateLink = Interop.Advapi32.RegistryOperations.KEY_CREATE_LINK, // 0x0020 reserved for system use
+ ///
+ /// The Windows Kernel team agrees that it was a bad design to expose the WOW64_n options as permissions.
+ /// in the .NET Framework these options are exposed via the RegistryView enum
+ ///
+ /// Reg64 = Interop.Advapi32.RegistryOptions.KEY_WOW64_64KEY, // 0x0100 operate on the 64-bit registry view
+ /// Reg32 = Interop.Advapi32.RegistryOptions.KEY_WOW64_32KEY, // 0x0200 operate on the 32-bit registry view
+ ExecuteKey = ReadKey,
+ ReadKey = Interop.Advapi32.RegistryOperations.STANDARD_RIGHTS_READ | QueryValues | EnumerateSubKeys | Notify,
+ WriteKey = Interop.Advapi32.RegistryOperations.STANDARD_RIGHTS_WRITE | SetValue | CreateSubKey,
+ Delete = 0x10000,
+ ReadPermissions = 0x20000,
+ ChangePermissions = 0x40000,
+ TakeOwnership = 0x80000,
+ FullControl = 0xF003F | Interop.Advapi32.RegistryOperations.STANDARD_RIGHTS_READ | Interop.Advapi32.RegistryOperations.STANDARD_RIGHTS_WRITE
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Security/SafeBSTRHandle.cs b/src/System.Private.CoreLib/shared/System/Security/SafeBSTRHandle.cs
index 227fed3fc..bc93fecef 100644
--- a/src/System.Private.CoreLib/shared/System/Security/SafeBSTRHandle.cs
+++ b/src/System.Private.CoreLib/shared/System/Security/SafeBSTRHandle.cs
@@ -50,7 +50,7 @@ namespace System.Security
internal unsafe uint Length => Interop.OleAut32.SysStringLen(this);
- internal unsafe static void Copy(SafeBSTRHandle source, SafeBSTRHandle target, uint bytesToCopy)
+ internal static unsafe void Copy(SafeBSTRHandle source, SafeBSTRHandle target, uint bytesToCopy)
{
if (bytesToCopy == 0)
{
diff --git a/src/System.Private.CoreLib/shared/System/Security/SecureString.Unix.cs b/src/System.Private.CoreLib/shared/System/Security/SecureString.Unix.cs
index cfeebc1da..ad14bcd29 100644
--- a/src/System.Private.CoreLib/shared/System/Security/SecureString.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/Security/SecureString.Unix.cs
@@ -70,14 +70,6 @@ namespace System.Security
}
}
- private void EnsureNotDisposed()
- {
- if (_buffer == null)
- {
- throw new ObjectDisposedException(GetType().Name);
- }
- }
-
private void ClearCore()
{
_decryptedLength = 0;
@@ -143,7 +135,7 @@ namespace System.Security
_buffer.Write((ulong)(index * sizeof(char)), c);
}
- internal unsafe IntPtr MarshalToBSTR()
+ internal unsafe IntPtr MarshalToBSTRCore()
{
int length = _decryptedLength;
IntPtr ptr = IntPtr.Zero;
diff --git a/src/System.Private.CoreLib/shared/System/Security/SecureString.Windows.cs b/src/System.Private.CoreLib/shared/System/Security/SecureString.Windows.cs
index 2a8008191..a78fbc222 100644
--- a/src/System.Private.CoreLib/shared/System/Security/SecureString.Windows.cs
+++ b/src/System.Private.CoreLib/shared/System/Security/SecureString.Windows.cs
@@ -6,7 +6,6 @@ using System.Diagnostics;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
-using Microsoft.Win32;
namespace System.Security
{
@@ -145,7 +144,7 @@ namespace System.Security
}
}
- internal unsafe IntPtr MarshalToBSTR()
+ internal unsafe IntPtr MarshalToBSTRCore()
{
int length = _decryptedLength;
IntPtr ptr = IntPtr.Zero;
@@ -232,14 +231,6 @@ namespace System.Security
return result;
}
- private void EnsureNotDisposed()
- {
- if (_buffer == null)
- {
- throw new ObjectDisposedException(GetType().Name);
- }
- }
-
// -----------------------------
// ---- PAL layer ends here ----
// -----------------------------
diff --git a/src/System.Private.CoreLib/shared/System/Security/SecureString.cs b/src/System.Private.CoreLib/shared/System/Security/SecureString.cs
index 22f15acca..cdee9c907 100644
--- a/src/System.Private.CoreLib/shared/System/Security/SecureString.cs
+++ b/src/System.Private.CoreLib/shared/System/Security/SecureString.cs
@@ -139,7 +139,7 @@ namespace System.Security
{
throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_IndexString);
}
- Debug.Assert(index <= Int32.MaxValue / sizeof(char));
+ Debug.Assert(index <= int.MaxValue / sizeof(char));
EnsureNotDisposed();
EnsureNotReadOnly();
@@ -156,6 +156,23 @@ namespace System.Security
}
}
+ private void EnsureNotDisposed()
+ {
+ if (_buffer == null)
+ {
+ throw new ObjectDisposedException(GetType().Name);
+ }
+ }
+
+ internal IntPtr MarshalToBSTR()
+ {
+ lock (_methodLock)
+ {
+ EnsureNotDisposed();
+ return MarshalToBSTRCore();
+ }
+ }
+
internal unsafe IntPtr MarshalToString(bool globalAlloc, bool unicode)
{
lock (_methodLock)
diff --git a/src/System.Private.CoreLib/shared/System/Single.cs b/src/System.Private.CoreLib/shared/System/Single.cs
index 7bffa1ac7..8d1788f73 100644
--- a/src/System.Private.CoreLib/shared/System/Single.cs
+++ b/src/System.Private.CoreLib/shared/System/Single.cs
@@ -23,9 +23,9 @@ namespace System
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct Single : IComparable, IConvertible, IFormattable, IComparable<Single>, IEquatable<Single>, ISpanFormattable
+ public readonly struct Single : IComparable, IConvertible, IFormattable, IComparable<float>, IEquatable<float>, ISpanFormattable
{
- private float m_value; // Do not rename (binary serialization)
+ private readonly float m_value; // Do not rename (binary serialization)
//
// Public constants
@@ -52,7 +52,7 @@ namespace System
/// <summary>Determines whether the specified value is infinite.</summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe static bool IsInfinity(float f)
+ public static unsafe bool IsInfinity(float f)
{
var bits = BitConverter.SingleToInt32Bits(f);
return (bits & 0x7FFFFFFF) == 0x7F800000;
@@ -61,7 +61,7 @@ namespace System
/// <summary>Determines whether the specified value is NaN.</summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe static bool IsNaN(float f)
+ public static unsafe bool IsNaN(float f)
{
var bits = BitConverter.SingleToInt32Bits(f);
return (bits & 0x7FFFFFFF) > 0x7F800000;
@@ -70,16 +70,15 @@ namespace System
/// <summary>Determines whether the specified value is negative.</summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe static bool IsNegative(float f)
+ public static unsafe bool IsNegative(float f)
{
- var bits = unchecked((uint)BitConverter.SingleToInt32Bits(f));
- return (bits & 0x80000000) == 0x80000000;
+ return BitConverter.SingleToInt32Bits(f) < 0;
}
/// <summary>Determines whether the specified value is negative infinity.</summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe static bool IsNegativeInfinity(float f)
+ public static unsafe bool IsNegativeInfinity(float f)
{
return (f == float.NegativeInfinity);
}
@@ -87,7 +86,7 @@ namespace System
/// <summary>Determines whether the specified value is normal.</summary>
[NonVersionable]
// This is probably not worth inlining, it has branches and should be rarely called
- public unsafe static bool IsNormal(float f)
+ public static unsafe bool IsNormal(float f)
{
var bits = BitConverter.SingleToInt32Bits(f);
bits &= 0x7FFFFFFF;
@@ -97,7 +96,7 @@ namespace System
/// <summary>Determines whether the specified value is positive infinity.</summary>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public unsafe static bool IsPositiveInfinity(float f)
+ public static unsafe bool IsPositiveInfinity(float f)
{
return (f == float.PositiveInfinity);
}
@@ -105,7 +104,7 @@ namespace System
/// <summary>Determines whether the specified value is subnormal.</summary>
[NonVersionable]
// This is probably not worth inlining, it has branches and should be rarely called
- public unsafe static bool IsSubnormal(float f)
+ public static unsafe bool IsSubnormal(float f)
{
var bits = BitConverter.SingleToInt32Bits(f);
bits &= 0x7FFFFFFF;
@@ -118,13 +117,13 @@ namespace System
// null is considered to be less than any instance.
// If object is not of type Single, this method throws an ArgumentException.
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
- if (value is Single)
+ if (value is float)
{
float f = (float)value;
if (m_value < f) return -1;
@@ -141,7 +140,7 @@ namespace System
}
- public int CompareTo(Single value)
+ public int CompareTo(float value)
{
if (m_value < value) return -1;
if (m_value > value) return 1;
@@ -155,48 +154,48 @@ namespace System
}
[NonVersionable]
- public static bool operator ==(Single left, Single right)
+ public static bool operator ==(float left, float right)
{
return left == right;
}
[NonVersionable]
- public static bool operator !=(Single left, Single right)
+ public static bool operator !=(float left, float right)
{
return left != right;
}
[NonVersionable]
- public static bool operator <(Single left, Single right)
+ public static bool operator <(float left, float right)
{
return left < right;
}
[NonVersionable]
- public static bool operator >(Single left, Single right)
+ public static bool operator >(float left, float right)
{
return left > right;
}
[NonVersionable]
- public static bool operator <=(Single left, Single right)
+ public static bool operator <=(float left, float right)
{
return left <= right;
}
[NonVersionable]
- public static bool operator >=(Single left, Single right)
+ public static bool operator >=(float left, float right)
{
return left >= right;
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is Single))
+ if (!(obj is float))
{
return false;
}
- float temp = ((Single)obj).m_value;
+ float temp = ((float)obj).m_value;
if (temp == m_value)
{
return true;
@@ -205,7 +204,7 @@ namespace System
return IsNaN(temp) && IsNaN(m_value);
}
- public bool Equals(Single obj)
+ public bool Equals(float obj)
{
if (obj == m_value)
{
@@ -217,7 +216,7 @@ namespace System
public override int GetHashCode()
{
- var bits = Unsafe.As<float, int>(ref m_value);
+ var bits = Unsafe.As<float, int>(ref Unsafe.AsRef(in m_value));
// Optimized check for IsNan() || IsZero()
if (((bits - 1) & 0x7FFFFFFF) >= 0x7F800000)
@@ -229,22 +228,22 @@ namespace System
return bits;
}
- public override String ToString()
+ public override string ToString()
{
return Number.FormatSingle(m_value, null, NumberFormatInfo.CurrentInfo);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return Number.FormatSingle(m_value, null, NumberFormatInfo.GetInstance(provider));
}
- public String ToString(String format)
+ public string ToString(string format)
{
return Number.FormatSingle(m_value, format, NumberFormatInfo.CurrentInfo);
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
return Number.FormatSingle(m_value, format, NumberFormatInfo.GetInstance(provider));
}
@@ -262,39 +261,39 @@ namespace System
// PositiveInfinity or NegativeInfinity for a number that is too
// large or too small.
//
- public static float Parse(String s)
+ public static float Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseSingle(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo);
}
- public static float Parse(String s, NumberStyles style)
+ public static float Parse(string s, NumberStyles style)
{
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseSingle(s, style, NumberFormatInfo.CurrentInfo);
}
- public static float Parse(String s, IFormatProvider provider)
+ public static float Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseSingle(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.GetInstance(provider));
}
- public static float Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static float Parse(string s, NumberStyles style, IFormatProvider provider)
{
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseSingle(s, style, NumberFormatInfo.GetInstance(provider));
}
- public static float Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Integer, IFormatProvider provider = null)
+ public static float Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Float | NumberStyles.AllowThousands, IFormatProvider provider = null)
{
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
return Number.ParseSingle(s, style, NumberFormatInfo.GetInstance(provider));
}
- public static Boolean TryParse(String s, out Single result)
+ public static bool TryParse(string s, out float result)
{
if (s == null)
{
@@ -310,7 +309,7 @@ namespace System
return TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo, out result);
}
- public static Boolean TryParse(String s, NumberStyles style, IFormatProvider provider, out Single result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out float result)
{
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
@@ -329,21 +328,21 @@ namespace System
return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
}
- private static Boolean TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out Single result)
+ private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out float result)
{
bool success = Number.TryParseSingle(s, style, info, out result);
if (!success)
{
ReadOnlySpan<char> sTrim = s.Trim();
- if (StringSpanHelpers.Equals(sTrim, info.PositiveInfinitySymbol))
+ if (sTrim.EqualsOrdinal(info.PositiveInfinitySymbol))
{
result = PositiveInfinity;
}
- else if (StringSpanHelpers.Equals(sTrim, info.NegativeInfinitySymbol))
+ else if (sTrim.EqualsOrdinal(info.NegativeInfinitySymbol))
{
result = NegativeInfinity;
}
- else if (StringSpanHelpers.Equals(sTrim, info.NaNSymbol))
+ else if (sTrim.EqualsOrdinal(info.NaNSymbol))
{
result = NaN;
}
@@ -425,7 +424,7 @@ namespace System
return Convert.ToDouble(m_value);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -435,7 +434,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Single", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/Span.Fast.cs b/src/System.Private.CoreLib/shared/System/Span.Fast.cs
index 0ae1922fd..b3cfc8daf 100644
--- a/src/System.Private.CoreLib/shared/System/Span.Fast.cs
+++ b/src/System.Private.CoreLib/shared/System/Span.Fast.cs
@@ -2,10 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
+using EditorBrowsableAttribute = System.ComponentModel.EditorBrowsableAttribute;
+using EditorBrowsableState = System.ComponentModel.EditorBrowsableState;
using Internal.Runtime.CompilerServices;
#pragma warning disable 0809 //warning CS0809: Obsolete member 'Span<T>.Equals(object)' overrides non-obsolete member 'object.Equals(object)'
@@ -22,8 +23,6 @@ namespace System
/// Span represents a contiguous region of arbitrary memory. Unlike arrays, it can point to either managed
/// or native memory, or to memory allocated on the stack. It is type- and memory-safe.
/// </summary>
- [DebuggerTypeProxy(typeof(SpanDebugView<>))]
- [DebuggerDisplay("{ToString(),raw}")]
[NonVersionable]
public readonly ref partial struct Span<T>
{
@@ -155,6 +154,13 @@ namespace System
}
/// <summary>
+ /// Returns a reference to the 0th element of the Span. If the Span is empty, returns null reference.
+ /// It can be used for pinning and is required to support the use of span within a fixed statement.
+ /// </summary>
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public unsafe ref T GetPinnableReference() => ref (_length != 0) ? ref _pointer.Value : ref Unsafe.AsRef<T>(null);
+
+ /// <summary>
/// Clears the contents of this span.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -232,6 +238,7 @@ namespace System
/// <exception cref="System.ArgumentException">
/// Thrown when the destination Span is shorter than the source Span.
/// </exception>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void CopyTo(Span<T> destination)
{
// Using "if (!TryCopyTo(...))" results in two branches: one for the length
@@ -283,7 +290,7 @@ namespace System
/// <summary>
/// For <see cref="Span{Char}"/>, returns a new instance of string that represents the characters pointed to by the span.
- /// Otherwise, returns a <see cref="String"/> with the name of the type and the number of elements.
+ /// Otherwise, returns a <see cref="string"/> with the name of the type and the number of elements.
/// </summary>
public override string ToString()
{
diff --git a/src/System.Private.CoreLib/shared/System/Span.cs b/src/System.Private.CoreLib/shared/System/Span.cs
index 78733515c..185042fb5 100644
--- a/src/System.Private.CoreLib/shared/System/Span.cs
+++ b/src/System.Private.CoreLib/shared/System/Span.cs
@@ -5,9 +5,8 @@
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
-#if !FEATURE_PORTABLE_SPAN
+
using System.Runtime.Versioning;
-#endif // !FEATURE_PORTABLE_SPAN
#pragma warning disable 0809 //warning CS0809: Obsolete member 'Span<T>.Equals(object)' overrides non-obsolete member 'object.Equals(object)'
@@ -26,9 +25,7 @@ namespace System
/// </summary>
public int Length
{
-#if !FEATURE_PORTABLE_SPAN
[NonVersionable]
-#endif // !FEATURE_PORTABLE_SPAN
get
{
return _length;
@@ -40,12 +37,11 @@ namespace System
/// </summary>
public bool IsEmpty
{
-#if !FEATURE_PORTABLE_SPAN
[NonVersionable]
-#endif // !FEATURE_PORTABLE_SPAN
get
{
- return _length == 0;
+ // Workaround for https://github.com/dotnet/coreclr/issues/19620
+ return 0 >= (uint)_length;
}
}
@@ -89,13 +85,13 @@ namespace System
/// <summary>
/// Defines an implicit conversion of a <see cref="ArraySegment{T}"/> to a <see cref="Span{T}"/>
/// </summary>
- public static implicit operator Span<T>(ArraySegment<T> arraySegment)
- => new Span<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
+ public static implicit operator Span<T>(ArraySegment<T> segment)
+ => new Span<T>(segment.Array, segment.Offset, segment.Count);
/// <summary>
/// Returns an empty <see cref="Span{T}"/>
/// </summary>
- public static Span<T> Empty => default(Span<T>);
+ public static Span<T> Empty => default;
/// <summary>Gets an enumerator for this span.</summary>
public Enumerator GetEnumerator() => new Enumerator(this);
diff --git a/src/System.Private.CoreLib/shared/System/SpanDebugView.cs b/src/System.Private.CoreLib/shared/System/SpanDebugView.cs
index caa12ef9e..f79c67306 100644
--- a/src/System.Private.CoreLib/shared/System/SpanDebugView.cs
+++ b/src/System.Private.CoreLib/shared/System/SpanDebugView.cs
@@ -3,8 +3,6 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
-using System.Reflection;
-using System.Runtime.CompilerServices;
namespace System
{
@@ -14,7 +12,7 @@ namespace System
public SpanDebugView(Span<T> span)
{
- _array = span.ToArray();
+ _array = span.ToArray();
}
public SpanDebugView(ReadOnlySpan<T> span)
diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.BinarySearch.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.BinarySearch.cs
index 656b864e2..2aec70409 100644
--- a/src/System.Private.CoreLib/shared/System/SpanHelpers.BinarySearch.cs
+++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.BinarySearch.cs
@@ -6,9 +6,7 @@ using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-#if !netstandard
using Internal.Runtime.CompilerServices;
-#endif
namespace System
{
@@ -26,7 +24,7 @@ namespace System
}
public static int BinarySearch<T, TComparable>(
- ref T spanStart, int length, TComparable comparable)
+ ref T spanStart, int length, TComparable comparable)
where TComparable : IComparable<T>
{
int lo = 0;
@@ -64,11 +62,11 @@ namespace System
}
// Helper to allow sharing all code via IComparable<T> inlineable
- internal struct ComparerComparable<T, TComparer> : IComparable<T>
+ internal readonly struct ComparerComparable<T, TComparer> : IComparable<T>
where TComparer : IComparer<T>
{
- readonly T _value;
- readonly TComparer _comparer;
+ private readonly T _value;
+ private readonly TComparer _comparer;
public ComparerComparable(T value, TComparer comparer)
{
diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs
index 860b2efa0..373065363 100644
--- a/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs
+++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.Byte.cs
@@ -4,18 +4,19 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
+using System.Numerics;
-#if !netstandard
using Internal.Runtime.CompilerServices;
-#endif
-#if !netstandard11
-using System.Numerics;
-#endif
+#if BIT64
+using nuint = System.UInt64;
+#else
+using nuint = System.UInt32;
+#endif // BIT64
namespace System
{
- internal static partial class SpanHelpers
+ internal static partial class SpanHelpers // .Byte
{
public static int IndexOf(ref byte searchSpace, int searchSpaceLength, ref byte value, int valueLength)
{
@@ -70,7 +71,8 @@ namespace System
// Reduce space for search, cause we don't care if we find the search value after the index of a previously found value
searchSpaceLength = tempIndex;
- if (index == 0) break;
+ if (index == 0)
+ break;
}
}
return index;
@@ -88,48 +90,137 @@ namespace System
for (int i = 0; i < valueLength; i++)
{
var tempIndex = LastIndexOf(ref searchSpace, Unsafe.Add(ref value, i), searchSpaceLength);
- if (tempIndex > index) index = tempIndex;
+ if (tempIndex > index)
+ index = tempIndex;
}
return index;
}
- public static unsafe int IndexOf(ref byte searchSpace, byte value, int length)
+ // Adapted from IndexOf(...)
+ public static unsafe bool Contains(ref byte searchSpace, byte value, int length)
{
Debug.Assert(length >= 0);
-
+
uint uValue = value; // Use uint for comparisons to avoid unnecessary 8->32 extensions
- IntPtr index = (IntPtr)0; // Use UIntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr nLength = (IntPtr)(uint)length;
-#if !netstandard11
+ IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
{
- unchecked
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
+ }
+
+ SequentialScan:
+ while ((byte*)nLength >= (byte*)8)
+ {
+ nLength -= 8;
+
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 0) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 1) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 2) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 3) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 4) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 5) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 6) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 7))
+ {
+ goto Found;
+ }
+
+ index += 8;
+ }
+
+ if ((byte*)nLength >= (byte*)4)
+ {
+ nLength -= 4;
+
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 0) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 1) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 2) ||
+ uValue == Unsafe.AddByteOffset(ref searchSpace, index + 3))
+ {
+ goto Found;
+ }
+
+ index += 4;
+ }
+
+ while ((byte*)nLength > (byte*)0)
+ {
+ nLength -= 1;
+
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
+ goto Found;
+
+ index += 1;
+ }
+
+ if (Vector.IsHardwareAccelerated && ((int)(byte*)index < length))
+ {
+ nLength = (IntPtr)((length - (int)(byte*)index) & ~(Vector<byte>.Count - 1));
+
+ // Get comparison Vector
+ Vector<byte> vComparison = new Vector<byte>(value);
+
+ while ((byte*)nLength > (byte*)index)
{
- int unaligned = (int)(byte*)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
- nLength = (IntPtr)(uint)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
+ var vMatches = Vector.Equals(vComparison, Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref searchSpace, index)));
+ if (Vector<byte>.Zero.Equals(vMatches))
+ {
+ index += Vector<byte>.Count;
+ continue;
+ }
+
+ goto Found;
+ }
+
+ if ((int)(byte*)index < length)
+ {
+ nLength = (IntPtr)(length - (int)(byte*)index);
+ goto SequentialScan;
}
}
+
+ return false;
+
+ Found:
+ return true;
+ }
+
+ public static unsafe int IndexOf(ref byte searchSpace, byte value, int length)
+ {
+ Debug.Assert(length >= 0);
+
+ uint uValue = value; // Use uint for comparisons to avoid unnecessary 8->32 extensions
+ IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
+ if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
+ {
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
+ }
SequentialScan:
-#endif
while ((byte*)nLength >= (byte*)8)
{
nLength -= 8;
- if (uValue == Unsafe.Add(ref searchSpace, index))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
goto Found;
- if (uValue == Unsafe.Add(ref searchSpace, index + 1))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 1))
goto Found1;
- if (uValue == Unsafe.Add(ref searchSpace, index + 2))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 2))
goto Found2;
- if (uValue == Unsafe.Add(ref searchSpace, index + 3))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 3))
goto Found3;
- if (uValue == Unsafe.Add(ref searchSpace, index + 4))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 4))
goto Found4;
- if (uValue == Unsafe.Add(ref searchSpace, index + 5))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 5))
goto Found5;
- if (uValue == Unsafe.Add(ref searchSpace, index + 6))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 6))
goto Found6;
- if (uValue == Unsafe.Add(ref searchSpace, index + 7))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 7))
goto Found7;
index += 8;
@@ -139,13 +230,13 @@ namespace System
{
nLength -= 4;
- if (uValue == Unsafe.Add(ref searchSpace, index))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
goto Found;
- if (uValue == Unsafe.Add(ref searchSpace, index + 1))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 1))
goto Found1;
- if (uValue == Unsafe.Add(ref searchSpace, index + 2))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 2))
goto Found2;
- if (uValue == Unsafe.Add(ref searchSpace, index + 3))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 3))
goto Found3;
index += 4;
@@ -155,17 +246,19 @@ namespace System
{
nLength -= 1;
- if (uValue == Unsafe.Add(ref searchSpace, index))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
goto Found;
index += 1;
}
-#if !netstandard11
+
if (Vector.IsHardwareAccelerated && ((int)(byte*)index < length))
{
- nLength = (IntPtr)(uint)((length - (uint)index) & ~(Vector<byte>.Count - 1));
+ nLength = (IntPtr)((length - (int)(byte*)index) & ~(Vector<byte>.Count - 1));
+
// Get comparison Vector
- Vector<byte> vComparison = GetVector(value);
+ Vector<byte> vComparison = new Vector<byte>(value);
+
while ((byte*)nLength > (byte*)index)
{
var vMatches = Vector.Equals(vComparison, Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref searchSpace, index)));
@@ -180,14 +273,10 @@ namespace System
if ((int)(byte*)index < length)
{
- unchecked
- {
- nLength = (IntPtr)(length - (int)(byte*)index);
- }
+ nLength = (IntPtr)(length - (int)(byte*)index);
goto SequentialScan;
}
}
-#endif
return -1;
Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return (int)(byte*)index;
@@ -246,39 +335,35 @@ namespace System
Debug.Assert(length >= 0);
uint uValue = value; // Use uint for comparisons to avoid unnecessary 8->32 extensions
- IntPtr index = (IntPtr)(uint)length; // Use UIntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr nLength = (IntPtr)(uint)length;
-#if !netstandard11
+ IntPtr index = (IntPtr)length; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
{
- unchecked
- {
- int unaligned = (int)(byte*)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
- nLength = (IntPtr)(((length & (Vector<byte>.Count - 1)) + unaligned) & (Vector<byte>.Count - 1));
- }
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)(((length & (Vector<byte>.Count - 1)) + unaligned) & (Vector<byte>.Count - 1));
}
SequentialScan:
-#endif
while ((byte*)nLength >= (byte*)8)
{
nLength -= 8;
index -= 8;
- if (uValue == Unsafe.Add(ref searchSpace, index + 7))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 7))
goto Found7;
- if (uValue == Unsafe.Add(ref searchSpace, index + 6))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 6))
goto Found6;
- if (uValue == Unsafe.Add(ref searchSpace, index + 5))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 5))
goto Found5;
- if (uValue == Unsafe.Add(ref searchSpace, index + 4))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 4))
goto Found4;
- if (uValue == Unsafe.Add(ref searchSpace, index + 3))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 3))
goto Found3;
- if (uValue == Unsafe.Add(ref searchSpace, index + 2))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 2))
goto Found2;
- if (uValue == Unsafe.Add(ref searchSpace, index + 1))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 1))
goto Found1;
- if (uValue == Unsafe.Add(ref searchSpace, index))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
goto Found;
}
@@ -287,13 +372,13 @@ namespace System
nLength -= 4;
index -= 4;
- if (uValue == Unsafe.Add(ref searchSpace, index + 3))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 3))
goto Found3;
- if (uValue == Unsafe.Add(ref searchSpace, index + 2))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 2))
goto Found2;
- if (uValue == Unsafe.Add(ref searchSpace, index + 1))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index + 1))
goto Found1;
- if (uValue == Unsafe.Add(ref searchSpace, index))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
goto Found;
}
@@ -302,16 +387,17 @@ namespace System
nLength -= 1;
index -= 1;
- if (uValue == Unsafe.Add(ref searchSpace, index))
+ if (uValue == Unsafe.AddByteOffset(ref searchSpace, index))
goto Found;
}
-#if !netstandard11
- if (Vector.IsHardwareAccelerated && ((int)(byte*)index > 0))
+
+ if (Vector.IsHardwareAccelerated && ((byte*)index > (byte*)0))
{
- nLength = (IntPtr)(uint)((uint)index & ~(Vector<byte>.Count - 1));
+ nLength = (IntPtr)((int)(byte*)index & ~(Vector<byte>.Count - 1));
// Get comparison Vector
- Vector<byte> vComparison = GetVector(value);
+ Vector<byte> vComparison = new Vector<byte>(value);
+
while ((byte*)nLength > (byte*)(Vector<byte>.Count - 1))
{
var vMatches = Vector.Equals(vComparison, Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref searchSpace, index - Vector<byte>.Count)));
@@ -322,15 +408,14 @@ namespace System
continue;
}
// Find offset of first match
- return (int)(byte*)(index) - Vector<byte>.Count + LocateLastFoundByte(vMatches);
+ return (int)(index) - Vector<byte>.Count + LocateLastFoundByte(vMatches);
}
- if ((int)(byte*)index > 0)
+ if ((byte*)index > (byte*)0)
{
nLength = index;
goto SequentialScan;
}
}
-#endif
return -1;
Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return (int)(byte*)index;
@@ -356,46 +441,42 @@ namespace System
uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions
uint uValue1 = value1; // Use uint for comparisons to avoid unnecessary 8->32 extensions
- IntPtr index = (IntPtr)0; // Use UIntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr nLength = (IntPtr)(uint)length;
-#if !netstandard11
+ IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
{
- unchecked
- {
- int unaligned = (int)(byte*)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
- nLength = (IntPtr)(uint)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
- }
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
}
SequentialScan:
-#endif
uint lookUp;
while ((byte*)nLength >= (byte*)8)
{
nLength -= 8;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found3;
- lookUp = Unsafe.Add(ref searchSpace, index + 4);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 4);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found4;
- lookUp = Unsafe.Add(ref searchSpace, index + 5);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 5);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found5;
- lookUp = Unsafe.Add(ref searchSpace, index + 6);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 6);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found6;
- lookUp = Unsafe.Add(ref searchSpace, index + 7);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 7);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found7;
@@ -406,16 +487,16 @@ namespace System
{
nLength -= 4;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found3;
@@ -426,19 +507,20 @@ namespace System
{
nLength -= 1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found;
index += 1;
}
-#if !netstandard11
+
if (Vector.IsHardwareAccelerated && ((int)(byte*)index < length))
{
- nLength = (IntPtr)(uint)((length - (uint)index) & ~(Vector<byte>.Count - 1));
+ nLength = (IntPtr)((length - (int)(byte*)index) & ~(Vector<byte>.Count - 1));
+
// Get comparison Vector
- Vector<byte> values0 = GetVector(value0);
- Vector<byte> values1 = GetVector(value1);
+ Vector<byte> values0 = new Vector<byte>(value0);
+ Vector<byte> values1 = new Vector<byte>(value1);
while ((byte*)nLength > (byte*)index)
{
@@ -457,14 +539,10 @@ namespace System
if ((int)(byte*)index < length)
{
- unchecked
- {
- nLength = (IntPtr)(length - (int)(byte*)index);
- }
+ nLength = (IntPtr)(length - (int)(byte*)index);
goto SequentialScan;
}
}
-#endif
return -1;
Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return (int)(byte*)index;
@@ -491,46 +569,42 @@ namespace System
uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions
uint uValue1 = value1; // Use uint for comparisons to avoid unnecessary 8->32 extensions
uint uValue2 = value2; // Use uint for comparisons to avoid unnecessary 8->32 extensions
- IntPtr index = (IntPtr)0; // Use UIntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr nLength = (IntPtr)(uint)length;
-#if !netstandard11
+ IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
{
- unchecked
- {
- int unaligned = (int)(byte*)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
- nLength = (IntPtr)(uint)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
- }
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)((Vector<byte>.Count - unaligned) & (Vector<byte>.Count - 1));
}
SequentialScan:
-#endif
uint lookUp;
while ((byte*)nLength >= (byte*)8)
{
nLength -= 8;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found3;
- lookUp = Unsafe.Add(ref searchSpace, index + 4);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 4);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found4;
- lookUp = Unsafe.Add(ref searchSpace, index + 5);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 5);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found5;
- lookUp = Unsafe.Add(ref searchSpace, index + 6);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 6);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found6;
- lookUp = Unsafe.Add(ref searchSpace, index + 7);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 7);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found7;
@@ -541,16 +615,16 @@ namespace System
{
nLength -= 4;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found3;
@@ -561,20 +635,22 @@ namespace System
{
nLength -= 1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found;
index += 1;
}
-#if !netstandard11
+
if (Vector.IsHardwareAccelerated && ((int)(byte*)index < length))
{
- nLength = (IntPtr)(uint)((length - (uint)index) & ~(Vector<byte>.Count - 1));
+ nLength = (IntPtr)((length - (int)(byte*)index) & ~(Vector<byte>.Count - 1));
+
// Get comparison Vector
- Vector<byte> values0 = GetVector(value0);
- Vector<byte> values1 = GetVector(value1);
- Vector<byte> values2 = GetVector(value2);
+ Vector<byte> values0 = new Vector<byte>(value0);
+ Vector<byte> values1 = new Vector<byte>(value1);
+ Vector<byte> values2 = new Vector<byte>(value2);
+
while ((byte*)nLength > (byte*)index)
{
Vector<byte> vData = Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref searchSpace, index));
@@ -596,14 +672,10 @@ namespace System
if ((int)(byte*)index < length)
{
- unchecked
- {
- nLength = (IntPtr)(length - (int)(byte*)index);
- }
+ nLength = (IntPtr)(length - (int)(byte*)index);
goto SequentialScan;
}
}
-#endif
return -1;
Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return (int)(byte*)index;
@@ -629,47 +701,43 @@ namespace System
uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions
uint uValue1 = value1; // Use uint for comparisons to avoid unnecessary 8->32 extensions
- IntPtr index = (IntPtr)(uint)length; // Use UIntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr nLength = (IntPtr)(uint)length;
-#if !netstandard11
+ IntPtr index = (IntPtr)length; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
{
- unchecked
- {
- int unaligned = (int)(byte*)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
- nLength = (IntPtr)(((length & (Vector<byte>.Count - 1)) + unaligned) & (Vector<byte>.Count - 1));
- }
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)(((length & (Vector<byte>.Count - 1)) + unaligned) & (Vector<byte>.Count - 1));
}
SequentialScan:
-#endif
uint lookUp;
while ((byte*)nLength >= (byte*)8)
{
nLength -= 8;
index -= 8;
- lookUp = Unsafe.Add(ref searchSpace, index + 7);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 7);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found7;
- lookUp = Unsafe.Add(ref searchSpace, index + 6);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 6);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found6;
- lookUp = Unsafe.Add(ref searchSpace, index + 5);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 5);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found5;
- lookUp = Unsafe.Add(ref searchSpace, index + 4);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 4);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found4;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found3;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found;
}
@@ -679,16 +747,16 @@ namespace System
nLength -= 4;
index -= 4;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found3;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found;
}
@@ -698,17 +766,18 @@ namespace System
nLength -= 1;
index -= 1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp)
goto Found;
}
-#if !netstandard11
- if (Vector.IsHardwareAccelerated && ((int)(byte*)index > 0))
+
+ if (Vector.IsHardwareAccelerated && ((byte*)index > (byte*)0))
{
- nLength = (IntPtr)(uint)((uint)index & ~(Vector<byte>.Count - 1));
+ nLength = (IntPtr)((int)(byte*)index & ~(Vector<byte>.Count - 1));
+
// Get comparison Vector
- Vector<byte> values0 = GetVector(value0);
- Vector<byte> values1 = GetVector(value1);
+ Vector<byte> values0 = new Vector<byte>(value0);
+ Vector<byte> values1 = new Vector<byte>(value1);
while ((byte*)nLength > (byte*)(Vector<byte>.Count - 1))
{
@@ -723,16 +792,15 @@ namespace System
continue;
}
// Find offset of first match
- return (int)(byte*)(index) - Vector<byte>.Count + LocateLastFoundByte(vMatches);
+ return (int)(index) - Vector<byte>.Count + LocateLastFoundByte(vMatches);
}
- if ((int)(byte*)index > 0)
+ if ((byte*)index > (byte*)0)
{
nLength = index;
goto SequentialScan;
}
}
-#endif
return -1;
Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return (int)(byte*)index;
@@ -759,47 +827,43 @@ namespace System
uint uValue0 = value0; // Use uint for comparisons to avoid unnecessary 8->32 extensions
uint uValue1 = value1; // Use uint for comparisons to avoid unnecessary 8->32 extensions
uint uValue2 = value2; // Use uint for comparisons to avoid unnecessary 8->32 extensions
- IntPtr index = (IntPtr)(uint)length; // Use UIntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr nLength = (IntPtr)(uint)length;
-#if !netstandard11
+ IntPtr index = (IntPtr)length; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr nLength = (IntPtr)length;
+
if (Vector.IsHardwareAccelerated && length >= Vector<byte>.Count * 2)
{
- unchecked
- {
- int unaligned = (int)(byte*)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
- nLength = (IntPtr)(((length & (Vector<byte>.Count - 1)) + unaligned) & (Vector<byte>.Count - 1));
- }
+ int unaligned = (int)Unsafe.AsPointer(ref searchSpace) & (Vector<byte>.Count - 1);
+ nLength = (IntPtr)(((length & (Vector<byte>.Count - 1)) + unaligned) & (Vector<byte>.Count - 1));
}
SequentialScan:
-#endif
uint lookUp;
while ((byte*)nLength >= (byte*)8)
{
nLength -= 8;
index -= 8;
- lookUp = Unsafe.Add(ref searchSpace, index + 7);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 7);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found7;
- lookUp = Unsafe.Add(ref searchSpace, index + 6);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 6);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found6;
- lookUp = Unsafe.Add(ref searchSpace, index + 5);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 5);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found5;
- lookUp = Unsafe.Add(ref searchSpace, index + 4);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 4);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found4;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found3;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found;
}
@@ -809,16 +873,16 @@ namespace System
nLength -= 4;
index -= 4;
- lookUp = Unsafe.Add(ref searchSpace, index + 3);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 3);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found3;
- lookUp = Unsafe.Add(ref searchSpace, index + 2);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 2);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found2;
- lookUp = Unsafe.Add(ref searchSpace, index + 1);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index + 1);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found;
}
@@ -828,18 +892,20 @@ namespace System
nLength -= 1;
index -= 1;
- lookUp = Unsafe.Add(ref searchSpace, index);
+ lookUp = Unsafe.AddByteOffset(ref searchSpace, index);
if (uValue0 == lookUp || uValue1 == lookUp || uValue2 == lookUp)
goto Found;
}
-#if !netstandard11
- if (Vector.IsHardwareAccelerated && ((int)(byte*)index > 0))
+
+ if (Vector.IsHardwareAccelerated && ((byte*)index > (byte*)0))
{
- nLength = (IntPtr)(uint)((uint)index & ~(Vector<byte>.Count - 1));
+ nLength = (IntPtr)((int)(byte*)index & ~(Vector<byte>.Count - 1));
+
// Get comparison Vector
- Vector<byte> values0 = GetVector(value0);
- Vector<byte> values1 = GetVector(value1);
- Vector<byte> values2 = GetVector(value2);
+ Vector<byte> values0 = new Vector<byte>(value0);
+ Vector<byte> values1 = new Vector<byte>(value1);
+ Vector<byte> values2 = new Vector<byte>(value2);
+
while ((byte*)nLength > (byte*)(Vector<byte>.Count - 1))
{
Vector<byte> vData = Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref searchSpace, index - Vector<byte>.Count));
@@ -857,16 +923,15 @@ namespace System
continue;
}
// Find offset of first match
- return (int)(byte*)(index) - Vector<byte>.Count + LocateLastFoundByte(vMatches);
+ return (int)(index) - Vector<byte>.Count + LocateLastFoundByte(vMatches);
}
- if ((int)(byte*)index > 0)
+ if ((byte*)index > (byte*)0)
{
nLength = index;
goto SequentialScan;
}
}
-#endif
return -1;
Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return (int)(byte*)index;
@@ -886,17 +951,16 @@ namespace System
return (int)(byte*)(index + 7);
}
- public static unsafe bool SequenceEqual(ref byte first, ref byte second, int length)
+ // Optimized byte-based SequenceEquals. The "length" parameter for this one is declared a nuint rather than int as we also use it for types other than byte
+ // where the length can exceed 2Gb once scaled by sizeof(T).
+ public static unsafe bool SequenceEqual(ref byte first, ref byte second, nuint length)
{
- Debug.Assert(length >= 0);
-
if (Unsafe.AreSame(ref first, ref second))
goto Equal;
- IntPtr i = (IntPtr)0; // Use IntPtr and byte* for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr n = (IntPtr)length;
+ IntPtr i = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr n = (IntPtr)(void*)length;
-#if !netstandard11
if (Vector.IsHardwareAccelerated && (byte*)n >= (byte*)Vector<byte>.Count)
{
n -= Vector<byte>.Count;
@@ -912,7 +976,6 @@ namespace System
return Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref first, n)) ==
Unsafe.ReadUnaligned<Vector<byte>>(ref Unsafe.AddByteOffset(ref second, n));
}
-#endif
if ((byte*)n >= (byte*)sizeof(UIntPtr))
{
@@ -944,7 +1007,6 @@ namespace System
return false;
}
-#if !netstandard11
// Vector sub-search adapted from https://github.com/aspnet/KestrelHttpServer/pull/1138
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int LocateFirstFoundByte(Vector<byte> match)
@@ -965,7 +1027,6 @@ namespace System
// Single LEA instruction with jitted const (using function result)
return i * 8 + LocateFirstFoundByte(candidate);
}
-#endif
public static unsafe int SequenceCompareTo(ref byte first, int firstLength, ref byte second, int secondLength)
{
@@ -975,13 +1036,11 @@ namespace System
if (Unsafe.AreSame(ref first, ref second))
goto Equal;
- var minLength = firstLength;
- if (minLength > secondLength) minLength = secondLength;
+ IntPtr minLength = (IntPtr)((firstLength < secondLength) ? firstLength : secondLength);
- IntPtr i = (IntPtr)0; // Use IntPtr and byte* for arithmetic to avoid unnecessary 64->32->64 truncations
- IntPtr n = (IntPtr)minLength;
+ IntPtr i = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ IntPtr n = (IntPtr)(void*)minLength;
-#if !netstandard11
if (Vector.IsHardwareAccelerated && (byte*)n > (byte*)Vector<byte>.Count)
{
n -= Vector<byte>.Count;
@@ -996,7 +1055,6 @@ namespace System
}
goto NotEqual;
}
-#endif
if ((byte*)n > (byte*)sizeof(UIntPtr))
{
@@ -1013,10 +1071,11 @@ namespace System
}
NotEqual: // Workaround for https://github.com/dotnet/coreclr/issues/13549
- while((byte*)minLength > (byte*)i)
+ while ((byte*)minLength > (byte*)i)
{
int result = Unsafe.AddByteOffset(ref first, i).CompareTo(Unsafe.AddByteOffset(ref second, i));
- if (result != 0) return result;
+ if (result != 0)
+ return result;
i += 1;
}
@@ -1024,7 +1083,6 @@ namespace System
return firstLength - secondLength;
}
-#if !netstandard11
// Vector sub-search adapted from https://github.com/aspnet/KestrelHttpServer/pull/1138
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int LocateLastFoundByte(Vector<byte> match)
@@ -1045,23 +1103,16 @@ namespace System
// Single LEA instruction with jitted const (using function result)
return i * 8 + LocateLastFoundByte(candidate);
}
-#endif
-#if !netstandard11
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int LocateFirstFoundByte(ulong match)
{
- unchecked
- {
- // Flag least significant power of two bit
- var powerOfTwoFlag = match ^ (match - 1);
- // Shift all powers of two into the high byte and extract
- return (int)((powerOfTwoFlag * XorPowerOfTwoToHighByte) >> 57);
- }
+ // Flag least significant power of two bit
+ var powerOfTwoFlag = match ^ (match - 1);
+ // Shift all powers of two into the high byte and extract
+ return (int)((powerOfTwoFlag * XorPowerOfTwoToHighByte) >> 57);
}
-#endif
-#if !netstandard11
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int LocateLastFoundByte(ulong match)
{
@@ -1074,24 +1125,7 @@ namespace System
}
return index;
}
-#endif
-
-#if !netstandard11
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static Vector<byte> GetVector(byte vectorByte)
- {
-#if !netcoreapp
- // Vector<byte> .ctor doesn't become an intrinsic due to detection issue
- // However this does cause it to become an intrinsic (with additional multiply and reg->reg copy)
- // https://github.com/dotnet/coreclr/issues/7459#issuecomment-253965670
- return Vector.AsVectorByte(new Vector<uint>(vectorByte * 0x01010101u));
-#else
- return new Vector<byte>(vectorByte);
-#endif
- }
-#endif
-#if !netstandard11
private const ulong XorPowerOfTwoToHighByte = (0x07ul |
0x06ul << 8 |
0x05ul << 16 |
@@ -1099,6 +1133,5 @@ namespace System
0x03ul << 32 |
0x02ul << 40 |
0x01ul << 48) + 1;
-#endif
}
}
diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs
new file mode 100644
index 000000000..02df69feb
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.Char.cs
@@ -0,0 +1,420 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Numerics;
+
+#if !netstandard
+using Internal.Runtime.CompilerServices;
+#endif
+
+namespace System
+{
+ internal static partial class SpanHelpers // .Char
+ {
+ public static unsafe int SequenceCompareTo(ref char first, int firstLength, ref char second, int secondLength)
+ {
+ Debug.Assert(firstLength >= 0);
+ Debug.Assert(secondLength >= 0);
+
+ int lengthDelta = firstLength - secondLength;
+
+ if (Unsafe.AreSame(ref first, ref second))
+ goto Equal;
+
+ IntPtr minLength = (IntPtr)((firstLength < secondLength) ? firstLength : secondLength);
+ IntPtr i = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+
+ if ((byte*)minLength >= (byte*)(sizeof(UIntPtr) / sizeof(char)))
+ {
+ if (Vector.IsHardwareAccelerated && (byte*)minLength >= (byte*)Vector<ushort>.Count)
+ {
+ IntPtr nLength = minLength - Vector<ushort>.Count;
+ do
+ {
+ if (Unsafe.ReadUnaligned<Vector<ushort>>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref first, i))) !=
+ Unsafe.ReadUnaligned<Vector<ushort>>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref second, i))))
+ {
+ break;
+ }
+ i += Vector<ushort>.Count;
+ }
+ while ((byte*)nLength >= (byte*)i);
+ }
+
+ while ((byte*)minLength >= (byte*)(i + sizeof(UIntPtr) / sizeof(char)))
+ {
+ if (Unsafe.ReadUnaligned<UIntPtr>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref first, i))) !=
+ Unsafe.ReadUnaligned<UIntPtr>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref second, i))))
+ {
+ break;
+ }
+ i += sizeof(UIntPtr) / sizeof(char);
+ }
+ }
+
+ if (sizeof(UIntPtr) > sizeof(int) && (byte*)minLength >= (byte*)(i + sizeof(int) / sizeof(char)))
+ {
+ if (Unsafe.ReadUnaligned<int>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref first, i))) ==
+ Unsafe.ReadUnaligned<int>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref second, i))))
+ {
+ i += sizeof(int) / sizeof(char);
+ }
+ }
+
+ while ((byte*)i < (byte*)minLength)
+ {
+ int result = Unsafe.Add(ref first, i).CompareTo(Unsafe.Add(ref second, i));
+ if (result != 0)
+ return result;
+ i += 1;
+ }
+
+ Equal:
+ return lengthDelta;
+ }
+
+ // Adapted from IndexOf(...)
+ public static unsafe bool Contains(ref char searchSpace, char value, int length)
+ {
+ Debug.Assert(length >= 0);
+
+ fixed (char* pChars = &searchSpace)
+ {
+ char* pCh = pChars;
+ char* pEndCh = pCh + length;
+
+ if (Vector.IsHardwareAccelerated && length >= Vector<ushort>.Count * 2)
+ {
+ // Figure out how many characters to read sequentially until we are vector aligned
+ // This is equivalent to:
+ // unaligned = ((int)pCh % Unsafe.SizeOf<Vector<ushort>>()) / elementsPerByte
+ // length = (Vector<ushort>.Count - unaligned) % Vector<ushort>.Count
+ const int elementsPerByte = sizeof(ushort) / sizeof(byte);
+ int unaligned = ((int)pCh & (Unsafe.SizeOf<Vector<ushort>>() - 1)) / elementsPerByte;
+ length = (Vector<ushort>.Count - unaligned) & (Vector<ushort>.Count - 1);
+ }
+
+ SequentialScan:
+ while (length >= 4)
+ {
+ length -= 4;
+
+ if (value == *pCh ||
+ value == *(pCh + 1) ||
+ value == *(pCh + 2) ||
+ value == *(pCh + 3))
+ {
+ goto Found;
+ }
+
+ pCh += 4;
+ }
+
+ while (length > 0)
+ {
+ length -= 1;
+
+ if (value == *pCh)
+ goto Found;
+
+ pCh += 1;
+ }
+
+ // We get past SequentialScan only if IsHardwareAccelerated is true. However, we still have the redundant check to allow
+ // the JIT to see that the code is unreachable and eliminate it when the platform does not have hardware accelerated.
+ if (Vector.IsHardwareAccelerated && pCh < pEndCh)
+ {
+ // Get the highest multiple of Vector<ushort>.Count that is within the search space.
+ // That will be how many times we iterate in the loop below.
+ // This is equivalent to: length = Vector<ushort>.Count * ((int)(pEndCh - pCh) / Vector<ushort>.Count)
+ length = (int)((pEndCh - pCh) & ~(Vector<ushort>.Count - 1));
+
+ // Get comparison Vector
+ Vector<ushort> vComparison = new Vector<ushort>(value);
+
+ while (length > 0)
+ {
+ // Using Unsafe.Read instead of ReadUnaligned since the search space is pinned and pCh is always vector aligned
+ Debug.Assert(((int)pCh & (Unsafe.SizeOf<Vector<ushort>>() - 1)) == 0);
+ Vector<ushort> vMatches = Vector.Equals(vComparison, Unsafe.Read<Vector<ushort>>(pCh));
+ if (Vector<ushort>.Zero.Equals(vMatches))
+ {
+ pCh += Vector<ushort>.Count;
+ length -= Vector<ushort>.Count;
+ continue;
+ }
+
+ goto Found;
+ }
+
+ if (pCh < pEndCh)
+ {
+ length = (int)(pEndCh - pCh);
+ goto SequentialScan;
+ }
+ }
+
+ return false;
+
+ Found:
+ return true;
+ }
+ }
+
+ public static unsafe int IndexOf(ref char searchSpace, char value, int length)
+ {
+ Debug.Assert(length >= 0);
+
+ fixed (char* pChars = &searchSpace)
+ {
+ char* pCh = pChars;
+ char* pEndCh = pCh + length;
+
+ if (Vector.IsHardwareAccelerated && length >= Vector<ushort>.Count * 2)
+ {
+ // Figure out how many characters to read sequentially until we are vector aligned
+ // This is equivalent to:
+ // unaligned = ((int)pCh % Unsafe.SizeOf<Vector<ushort>>()) / elementsPerByte
+ // length = (Vector<ushort>.Count - unaligned) % Vector<ushort>.Count
+ const int elementsPerByte = sizeof(ushort) / sizeof(byte);
+ int unaligned = ((int)pCh & (Unsafe.SizeOf<Vector<ushort>>() - 1)) / elementsPerByte;
+ length = (Vector<ushort>.Count - unaligned) & (Vector<ushort>.Count - 1);
+ }
+
+ SequentialScan:
+ while (length >= 4)
+ {
+ length -= 4;
+
+ if (*pCh == value)
+ goto Found;
+ if (*(pCh + 1) == value)
+ goto Found1;
+ if (*(pCh + 2) == value)
+ goto Found2;
+ if (*(pCh + 3) == value)
+ goto Found3;
+
+ pCh += 4;
+ }
+
+ while (length > 0)
+ {
+ length -= 1;
+
+ if (*pCh == value)
+ goto Found;
+
+ pCh += 1;
+ }
+
+ // We get past SequentialScan only if IsHardwareAccelerated is true. However, we still have the redundant check to allow
+ // the JIT to see that the code is unreachable and eliminate it when the platform does not have hardware accelerated.
+ if (Vector.IsHardwareAccelerated && pCh < pEndCh)
+ {
+ // Get the highest multiple of Vector<ushort>.Count that is within the search space.
+ // That will be how many times we iterate in the loop below.
+ // This is equivalent to: length = Vector<ushort>.Count * ((int)(pEndCh - pCh) / Vector<ushort>.Count)
+ length = (int)((pEndCh - pCh) & ~(Vector<ushort>.Count - 1));
+
+ // Get comparison Vector
+ Vector<ushort> vComparison = new Vector<ushort>(value);
+
+ while (length > 0)
+ {
+ // Using Unsafe.Read instead of ReadUnaligned since the search space is pinned and pCh is always vector aligned
+ Debug.Assert(((int)pCh & (Unsafe.SizeOf<Vector<ushort>>() - 1)) == 0);
+ Vector<ushort> vMatches = Vector.Equals(vComparison, Unsafe.Read<Vector<ushort>>(pCh));
+ if (Vector<ushort>.Zero.Equals(vMatches))
+ {
+ pCh += Vector<ushort>.Count;
+ length -= Vector<ushort>.Count;
+ continue;
+ }
+ // Find offset of first match
+ return (int)(pCh - pChars) + LocateFirstFoundChar(vMatches);
+ }
+
+ if (pCh < pEndCh)
+ {
+ length = (int)(pEndCh - pCh);
+ goto SequentialScan;
+ }
+ }
+
+ return -1;
+ Found3:
+ pCh++;
+ Found2:
+ pCh++;
+ Found1:
+ pCh++;
+ Found:
+ return (int)(pCh - pChars);
+ }
+ }
+
+ public static unsafe int LastIndexOf(ref char searchSpace, char value, int length)
+ {
+ Debug.Assert(length >= 0);
+
+ fixed (char* pChars = &searchSpace)
+ {
+ char* pCh = pChars + length;
+ char* pEndCh = pChars;
+
+ if (Vector.IsHardwareAccelerated && length >= Vector<ushort>.Count * 2)
+ {
+ // Figure out how many characters to read sequentially from the end until we are vector aligned
+ // This is equivalent to: length = ((int)pCh % Unsafe.SizeOf<Vector<ushort>>()) / elementsPerByte
+ const int elementsPerByte = sizeof(ushort) / sizeof(byte);
+ length = ((int)pCh & (Unsafe.SizeOf<Vector<ushort>>() - 1)) / elementsPerByte;
+ }
+
+ SequentialScan:
+ while (length >= 4)
+ {
+ length -= 4;
+ pCh -= 4;
+
+ if (*(pCh + 3) == value)
+ goto Found3;
+ if (*(pCh + 2) == value)
+ goto Found2;
+ if (*(pCh + 1) == value)
+ goto Found1;
+ if (*pCh == value)
+ goto Found;
+ }
+
+ while (length > 0)
+ {
+ length -= 1;
+ pCh -= 1;
+
+ if (*pCh == value)
+ goto Found;
+ }
+
+ // We get past SequentialScan only if IsHardwareAccelerated is true. However, we still have the redundant check to allow
+ // the JIT to see that the code is unreachable and eliminate it when the platform does not have hardware accelerated.
+ if (Vector.IsHardwareAccelerated && pCh > pEndCh)
+ {
+ // Get the highest multiple of Vector<ushort>.Count that is within the search space.
+ // That will be how many times we iterate in the loop below.
+ // This is equivalent to: length = Vector<ushort>.Count * ((int)(pCh - pEndCh) / Vector<ushort>.Count)
+ length = (int)((pCh - pEndCh) & ~(Vector<ushort>.Count - 1));
+
+ // Get comparison Vector
+ Vector<ushort> vComparison = new Vector<ushort>(value);
+
+ while (length > 0)
+ {
+ char* pStart = pCh - Vector<ushort>.Count;
+ // Using Unsafe.Read instead of ReadUnaligned since the search space is pinned and pCh (and hence pSart) is always vector aligned
+ Debug.Assert(((int)pStart & (Unsafe.SizeOf<Vector<ushort>>() - 1)) == 0);
+ Vector<ushort> vMatches = Vector.Equals(vComparison, Unsafe.Read<Vector<ushort>>(pStart));
+ if (Vector<ushort>.Zero.Equals(vMatches))
+ {
+ pCh -= Vector<ushort>.Count;
+ length -= Vector<ushort>.Count;
+ continue;
+ }
+ // Find offset of last match
+ return (int)(pStart - pEndCh) + LocateLastFoundChar(vMatches);
+ }
+
+ if (pCh > pEndCh)
+ {
+ length = (int)(pCh - pEndCh);
+ goto SequentialScan;
+ }
+ }
+
+ return -1;
+ Found:
+ return (int)(pCh - pEndCh);
+ Found1:
+ return (int)(pCh - pEndCh) + 1;
+ Found2:
+ return (int)(pCh - pEndCh) + 2;
+ Found3:
+ return (int)(pCh - pEndCh) + 3;
+ }
+ }
+
+ // Vector sub-search adapted from https://github.com/aspnet/KestrelHttpServer/pull/1138
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static int LocateFirstFoundChar(Vector<ushort> match)
+ {
+ var vector64 = Vector.AsVectorUInt64(match);
+ ulong candidate = 0;
+ int i = 0;
+ // Pattern unrolled by jit https://github.com/dotnet/coreclr/pull/8001
+ for (; i < Vector<ulong>.Count; i++)
+ {
+ candidate = vector64[i];
+ if (candidate != 0)
+ {
+ break;
+ }
+ }
+
+ // Single LEA instruction with jitted const (using function result)
+ return i * 4 + LocateFirstFoundChar(candidate);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static int LocateFirstFoundChar(ulong match)
+ {
+ unchecked
+ {
+ // Flag least significant power of two bit
+ var powerOfTwoFlag = match ^ (match - 1);
+ // Shift all powers of two into the high byte and extract
+ return (int)((powerOfTwoFlag * XorPowerOfTwoToHighChar) >> 49);
+ }
+ }
+
+ private const ulong XorPowerOfTwoToHighChar = (0x03ul |
+ 0x02ul << 16 |
+ 0x01ul << 32) + 1;
+
+ // Vector sub-search adapted from https://github.com/aspnet/KestrelHttpServer/pull/1138
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static int LocateLastFoundChar(Vector<ushort> match)
+ {
+ var vector64 = Vector.AsVectorUInt64(match);
+ ulong candidate = 0;
+ int i = Vector<ulong>.Count - 1;
+ // Pattern unrolled by jit https://github.com/dotnet/coreclr/pull/8001
+ for (; i >= 0; i--)
+ {
+ candidate = vector64[i];
+ if (candidate != 0)
+ {
+ break;
+ }
+ }
+
+ // Single LEA instruction with jitted const (using function result)
+ return i * 4 + LocateLastFoundChar(candidate);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static int LocateLastFoundChar(ulong match)
+ {
+ // Find the most significant char that has its highest bit set
+ int index = 3;
+ while ((long)match > 0)
+ {
+ match = match << 16;
+ index--;
+ }
+ return index;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.T.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.T.cs
index d1c62c8d5..d6f45d226 100644
--- a/src/System.Private.CoreLib/shared/System/SpanHelpers.T.cs
+++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.T.cs
@@ -3,16 +3,16 @@
// See the LICENSE file in the project root for more information.
using System.Diagnostics;
+using System.Runtime.CompilerServices; // Do not remove. This is necessary for netstandard, since this file is mirrored into corefx
+using System.Numerics;
#if !netstandard
using Internal.Runtime.CompilerServices;
-#else
-using System.Runtime.CompilerServices;
#endif
namespace System
{
- internal static partial class SpanHelpers
+ internal static partial class SpanHelpers // .T
{
public static int IndexOf<T>(ref T searchSpace, int searchSpaceLength, ref T value, int valueLength)
where T : IEquatable<T>
@@ -49,7 +49,64 @@ namespace System
}
return -1;
}
-
+
+ // Adapted from IndexOf(...)
+ public static bool Contains<T>(ref T searchSpace, T value, int length)
+ where T : IEquatable<T>
+ {
+ Debug.Assert(length >= 0);
+
+ IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
+ while (length >= 8)
+ {
+ length -= 8;
+
+ if (value.Equals(Unsafe.Add(ref searchSpace, index + 0)) ||
+ value.Equals(Unsafe.Add(ref searchSpace, index + 1)) ||
+ value.Equals(Unsafe.Add(ref searchSpace, index + 2)) ||
+ value.Equals(Unsafe.Add(ref searchSpace, index + 3)) ||
+ value.Equals(Unsafe.Add(ref searchSpace, index + 4)) ||
+ value.Equals(Unsafe.Add(ref searchSpace, index + 5)) ||
+ value.Equals(Unsafe.Add(ref searchSpace, index + 6)) ||
+ value.Equals(Unsafe.Add(ref searchSpace, index + 7)))
+ {
+ goto Found;
+ }
+
+ index += 8;
+ }
+
+ if (length >= 4)
+ {
+ length -= 4;
+
+ if (value.Equals(Unsafe.Add(ref searchSpace, index + 0)) ||
+ value.Equals(Unsafe.Add(ref searchSpace, index + 1)) ||
+ value.Equals(Unsafe.Add(ref searchSpace, index + 2)) ||
+ value.Equals(Unsafe.Add(ref searchSpace, index + 3)))
+ {
+ goto Found;
+ }
+
+ index += 4;
+ }
+
+ while (length > 0)
+ {
+ length -= 1;
+
+ if (value.Equals(Unsafe.Add(ref searchSpace, index)))
+ goto Found;
+
+ index += 1;
+ }
+
+ return false;
+
+ Found:
+ return true;
+ }
+
public static unsafe int IndexOf<T>(ref T searchSpace, T value, int length)
where T : IEquatable<T>
{
@@ -189,21 +246,21 @@ namespace System
}
return -1;
- Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
+ Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return index;
- Found1:
+ Found1:
return index + 1;
- Found2:
+ Found2:
return index + 2;
- Found3:
+ Found3:
return index + 3;
- Found4:
+ Found4:
return index + 4;
- Found5:
+ Found5:
return index + 5;
- Found6:
+ Found6:
return index + 6;
- Found7:
+ Found7:
return index + 7;
}
@@ -272,21 +329,21 @@ namespace System
}
return -1;
- Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
+ Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return index;
- Found1:
+ Found1:
return index + 1;
- Found2:
+ Found2:
return index + 2;
- Found3:
+ Found3:
return index + 3;
- Found4:
+ Found4:
return index + 4;
- Found5:
+ Found5:
return index + 5;
- Found6:
+ Found6:
return index + 6;
- Found7:
+ Found7:
return index + 7;
}
@@ -309,7 +366,8 @@ namespace System
// Reduce space for search, cause we don't care if we find the search value after the index of a previously found value
searchSpaceLength = tempIndex;
- if (index == 0) break;
+ if (index == 0)
+ break;
}
}
return index;
@@ -595,7 +653,8 @@ namespace System
for (int i = 0; i < valueLength; i++)
{
var tempIndex = LastIndexOf(ref searchSpace, Unsafe.Add(ref value, i), searchSpaceLength);
- if (tempIndex > index) index = tempIndex;
+ if (tempIndex > index)
+ index = tempIndex;
}
return index;
}
@@ -671,11 +730,13 @@ namespace System
Debug.Assert(secondLength >= 0);
var minLength = firstLength;
- if (minLength > secondLength) minLength = secondLength;
+ if (minLength > secondLength)
+ minLength = secondLength;
for (int i = 0; i < minLength; i++)
{
int result = Unsafe.Add(ref first, i).CompareTo(Unsafe.Add(ref second, i));
- if (result != 0) return result;
+ if (result != 0)
+ return result;
}
return firstLength.CompareTo(secondLength);
}
diff --git a/src/System.Private.CoreLib/shared/System/SpanHelpers.cs b/src/System.Private.CoreLib/shared/System/SpanHelpers.cs
index dad0f6294..0d5c57c5d 100644
--- a/src/System.Private.CoreLib/shared/System/SpanHelpers.cs
+++ b/src/System.Private.CoreLib/shared/System/SpanHelpers.cs
@@ -5,7 +5,6 @@
using System.Diagnostics;
using System.Globalization;
using System.Runtime;
-using System.Runtime.InteropServices;
using Internal.Runtime.CompilerServices;
@@ -19,127 +18,6 @@ namespace System
{
internal static partial class SpanHelpers
{
- public static int IndexOfCultureHelper(ReadOnlySpan<char> span, ReadOnlySpan<char> value, CompareInfo compareInfo)
- {
- Debug.Assert(span.Length != 0);
- Debug.Assert(value.Length != 0);
-
- if (GlobalizationMode.Invariant)
- {
- return CompareInfo.InvariantIndexOf(span, value, ignoreCase: false);
- }
-
- return compareInfo.IndexOf(span, value, CompareOptions.None);
- }
-
- public static int IndexOfCultureIgnoreCaseHelper(ReadOnlySpan<char> span, ReadOnlySpan<char> value, CompareInfo compareInfo)
- {
- Debug.Assert(span.Length != 0);
- Debug.Assert(value.Length != 0);
-
- if (GlobalizationMode.Invariant)
- {
- return CompareInfo.InvariantIndexOf(span, value, ignoreCase: true);
- }
-
- return compareInfo.IndexOf(span, value, CompareOptions.IgnoreCase);
- }
-
- public static int IndexOfOrdinalHelper(ReadOnlySpan<char> span, ReadOnlySpan<char> value, bool ignoreCase)
- {
- Debug.Assert(span.Length != 0);
- Debug.Assert(value.Length != 0);
-
- if (GlobalizationMode.Invariant)
- {
- return CompareInfo.InvariantIndexOf(span, value, ignoreCase);
- }
-
- return CompareInfo.Invariant.IndexOfOrdinal(span, value, ignoreCase);
- }
-
- public static bool StartsWithCultureHelper(ReadOnlySpan<char> span, ReadOnlySpan<char> value, CompareInfo compareInfo)
- {
- Debug.Assert(value.Length != 0);
-
- if (GlobalizationMode.Invariant)
- {
- return span.StartsWith(value);
- }
- if (span.Length == 0)
- {
- return false;
- }
- return compareInfo.IsPrefix(span, value, CompareOptions.None);
- }
-
- public static bool StartsWithCultureIgnoreCaseHelper(ReadOnlySpan<char> span, ReadOnlySpan<char> value, CompareInfo compareInfo)
- {
- Debug.Assert(value.Length != 0);
-
- if (GlobalizationMode.Invariant)
- {
- return StartsWithOrdinalIgnoreCaseHelper(span, value);
- }
- if (span.Length == 0)
- {
- return false;
- }
- return compareInfo.IsPrefix(span, value, CompareOptions.IgnoreCase);
- }
-
- public static bool StartsWithOrdinalIgnoreCaseHelper(ReadOnlySpan<char> span, ReadOnlySpan<char> value)
- {
- Debug.Assert(value.Length != 0);
-
- if (span.Length < value.Length)
- {
- return false;
- }
- return CompareInfo.CompareOrdinalIgnoreCase(span.Slice(0, value.Length), value) == 0;
- }
-
- public static bool EndsWithCultureHelper(ReadOnlySpan<char> span, ReadOnlySpan<char> value, CompareInfo compareInfo)
- {
- Debug.Assert(value.Length != 0);
-
- if (GlobalizationMode.Invariant)
- {
- return span.EndsWith(value);
- }
- if (span.Length == 0)
- {
- return false;
- }
- return compareInfo.IsSuffix(span, value, CompareOptions.None);
- }
-
- public static bool EndsWithCultureIgnoreCaseHelper(ReadOnlySpan<char> span, ReadOnlySpan<char> value, CompareInfo compareInfo)
- {
- Debug.Assert(value.Length != 0);
-
- if (GlobalizationMode.Invariant)
- {
- return EndsWithOrdinalIgnoreCaseHelper(span, value);
- }
- if (span.Length == 0)
- {
- return false;
- }
- return compareInfo.IsSuffix(span, value, CompareOptions.IgnoreCase);
- }
-
- public static bool EndsWithOrdinalIgnoreCaseHelper(ReadOnlySpan<char> span, ReadOnlySpan<char> value)
- {
- Debug.Assert(value.Length != 0);
-
- if (span.Length < value.Length)
- {
- return false;
- }
- return (CompareInfo.CompareOrdinalIgnoreCase(span.Slice(span.Length - value.Length), value) == 0);
- }
-
public static unsafe void ClearWithoutReferences(ref byte b, nuint byteLength)
{
if (byteLength == 0)
@@ -355,13 +233,13 @@ namespace System
nuint i = 0; // byte offset at which we're copying
- if ((Unsafe.As<byte, int>(ref b) & 3) != 0)
+ if (((nuint)Unsafe.AsPointer(ref b) & 3) != 0)
{
- if ((Unsafe.As<byte, int>(ref b) & 1) != 0)
+ if (((nuint)Unsafe.AsPointer(ref b) & 1) != 0)
{
- Unsafe.AddByteOffset<byte>(ref b, i) = 0;
+ b = 0;
i += 1;
- if ((Unsafe.As<byte, int>(ref b) & 2) != 0)
+ if (((nuint)Unsafe.AsPointer(ref b) & 2) != 0)
goto IntAligned;
}
Unsafe.As<byte, short>(ref Unsafe.AddByteOffset<byte>(ref b, i)) = 0;
@@ -378,7 +256,7 @@ namespace System
// The thing 1, 2, 3, and 4 have in common that the others don't is that if you
// subtract one from them, their 3rd lsb will not be set. Hence, the below check.
- if (((Unsafe.As<byte, int>(ref b) - 1) & 4) == 0)
+ if ((((nuint)Unsafe.AsPointer(ref b) - 1) & 4) == 0)
{
Unsafe.As<byte, int>(ref Unsafe.AddByteOffset<byte>(ref b, i)) = 0;
i += 4;
@@ -461,43 +339,77 @@ namespace System
public static unsafe void ClearWithReferences(ref IntPtr ip, nuint pointerSizeLength)
{
- if (pointerSizeLength == 0)
- return;
+ Debug.Assert((int)Unsafe.AsPointer(ref ip) % sizeof(IntPtr) == 0, "Should've been aligned on natural word boundary.");
- // TODO: Perhaps do switch casing to improve small size perf
+ // First write backward 8 natural words at a time.
+ // Writing backward allows us to get away with only simple modifications to the
+ // mov instruction's base and index registers between loop iterations.
- nuint i = 0;
- nuint n = 0;
- while ((n = i + 8) <= (pointerSizeLength))
+ for (; pointerSizeLength >= 8; pointerSizeLength -= 8)
{
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 0) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 1) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 2) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 3) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 4) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 5) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 6) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 7) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- i = n;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -1) = default;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -2) = default;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -3) = default;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -4) = default;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -5) = default;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -6) = default;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -7) = default;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -8) = default;
}
- if ((n = i + 4) <= (pointerSizeLength))
+
+ Debug.Assert(pointerSizeLength <= 7);
+
+ // The logic below works by trying to minimize the number of branches taken for any
+ // given range of lengths. For example, the lengths [ 4 .. 7 ] are handled by a single
+ // branch, [ 2 .. 3 ] are handled by a single branch, and [ 1 ] is handled by a single
+ // branch.
+ //
+ // We can write both forward and backward as a perf improvement. For example,
+ // the lengths [ 4 .. 7 ] can be handled by zeroing out the first four natural
+ // words and the last 3 natural words. In the best case (length = 7), there are
+ // no overlapping writes. In the worst case (length = 4), there are three
+ // overlapping writes near the middle of the buffer. In perf testing, the
+ // penalty for performing duplicate writes is less expensive than the penalty
+ // for complex branching.
+
+ if (pointerSizeLength >= 4)
+ {
+ goto Write4To7;
+ }
+ else if (pointerSizeLength >= 2)
{
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 0) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 1) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 2) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 3) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- i = n;
+ goto Write2To3;
}
- if ((n = i + 2) <= (pointerSizeLength))
+ else if (pointerSizeLength > 0)
{
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 0) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 1) * (nuint)sizeof(IntPtr)) = default(IntPtr);
- i = n;
+ goto Write1;
}
- if ((i + 1) <= (pointerSizeLength))
+ else
{
- Unsafe.AddByteOffset<IntPtr>(ref ip, (i + 0) * (nuint)sizeof(IntPtr)) = default(IntPtr);
+ return; // nothing to write
}
+
+ Write4To7:
+ Debug.Assert(pointerSizeLength >= 4);
+
+ // Write first four and last three.
+ Unsafe.Add(ref ip, 2) = default;
+ Unsafe.Add(ref ip, 3) = default;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -3) = default;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -2) = default;
+
+ Write2To3:
+ Debug.Assert(pointerSizeLength >= 2);
+
+ // Write first two and last one.
+ Unsafe.Add(ref ip, 1) = default;
+ Unsafe.Add(ref Unsafe.Add(ref ip, (IntPtr)pointerSizeLength), -1) = default;
+
+ Write1:
+ Debug.Assert(pointerSizeLength >= 1);
+
+ // Write only element.
+ ip = default;
}
}
}
diff --git a/src/System.Private.CoreLib/shared/System/StackOverflowException.cs b/src/System.Private.CoreLib/shared/System/StackOverflowException.cs
index 6f954cc75..a603ea88b 100644
--- a/src/System.Private.CoreLib/shared/System/StackOverflowException.cs
+++ b/src/System.Private.CoreLib/shared/System/StackOverflowException.cs
@@ -25,13 +25,13 @@ namespace System
HResult = HResults.COR_E_STACKOVERFLOW;
}
- public StackOverflowException(String message)
+ public StackOverflowException(string message)
: base(message)
{
HResult = HResults.COR_E_STACKOVERFLOW;
}
- public StackOverflowException(String message, Exception innerException)
+ public StackOverflowException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_STACKOVERFLOW;
diff --git a/src/System.Private.CoreLib/src/System/String.Comparison.cs b/src/System.Private.CoreLib/shared/System/String.Comparison.cs
index 21f996738..267bfe1fd 100644
--- a/src/System.Private.CoreLib/src/System/String.Comparison.cs
+++ b/src/System.Private.CoreLib/shared/System/String.Comparison.cs
@@ -20,269 +20,41 @@ namespace System
public partial class String
{
//
- //Native Static Methods
- //
-#if !MONO
- private static unsafe int FastCompareStringHelper(uint* strAChars, int countA, uint* strBChars, int countB)
- {
- int count = (countA < countB) ? countA : countB;
-
-#if BIT64
- long diff = (long)((byte*)strAChars - (byte*)strBChars);
-#else
- int diff = (int)((byte*)strAChars - (byte*)strBChars);
-#endif
-
-#if BIT64
- int alignmentA = (int)((long)strAChars) & (sizeof(IntPtr) - 1);
- int alignmentB = (int)((long)strBChars) & (sizeof(IntPtr) - 1);
-
- if (alignmentA == alignmentB)
- {
- if ((alignmentA == 2 || alignmentA == 6) && (count >= 1))
- {
- char* ptr2 = (char*)strBChars;
-
- if ((*((char*)((byte*)ptr2 + diff)) - *ptr2) != 0)
- return ((int)*((char*)((byte*)ptr2 + diff)) - (int)*ptr2);
-
- strBChars = (uint*)(++ptr2);
- count -= 1;
- alignmentA = (alignmentA == 2 ? 4 : 0);
- }
-
- if ((alignmentA == 4) && (count >= 2))
- {
- uint* ptr2 = (uint*)strBChars;
-
- if ((*((uint*)((byte*)ptr2 + diff)) - *ptr2) != 0)
- {
- char* chkptr1 = (char*)((byte*)strBChars + diff);
- char* chkptr2 = (char*)strBChars;
-
- if (*chkptr1 != *chkptr2)
- return ((int)*chkptr1 - (int)*chkptr2);
- return ((int)*(chkptr1 + 1) - (int)*(chkptr2 + 1));
- }
- strBChars = ++ptr2;
- count -= 2;
- alignmentA = 0;
- }
-
- if ((alignmentA == 0))
- {
- while (count >= 4)
- {
- long* ptr2 = (long*)strBChars;
-
- if ((*((long*)((byte*)ptr2 + diff)) - *ptr2) != 0)
- {
- if ((*((uint*)((byte*)ptr2 + diff)) - *(uint*)ptr2) != 0)
- {
- char* chkptr1 = (char*)((byte*)strBChars + diff);
- char* chkptr2 = (char*)strBChars;
-
- if (*chkptr1 != *chkptr2)
- return ((int)*chkptr1 - (int)*chkptr2);
- return ((int)*(chkptr1 + 1) - (int)*(chkptr2 + 1));
- }
- else
- {
- char* chkptr1 = (char*)((uint*)((byte*)strBChars + diff) + 1);
- char* chkptr2 = (char*)((uint*)strBChars + 1);
-
- if (*chkptr1 != *chkptr2)
- return ((int)*chkptr1 - (int)*chkptr2);
- return ((int)*(chkptr1 + 1) - (int)*(chkptr2 + 1));
- }
- }
- strBChars = (uint*)(++ptr2);
- count -= 4;
- }
- }
-
- {
- char* ptr2 = (char*)strBChars;
- while ((count -= 1) >= 0)
- {
- if ((*((char*)((byte*)ptr2 + diff)) - *ptr2) != 0)
- return ((int)*((char*)((byte*)ptr2 + diff)) - (int)*ptr2);
- ++ptr2;
- }
- }
- }
- else
-#endif // BIT64
- {
-#if BIT64
- if (Math.Abs(alignmentA - alignmentB) == 4)
- {
- if ((alignmentA == 2) || (alignmentB == 2))
- {
- char* ptr2 = (char*)strBChars;
-
- if ((*((char*)((byte*)ptr2 + diff)) - *ptr2) != 0)
- return ((int)*((char*)((byte*)ptr2 + diff)) - (int)*ptr2);
- strBChars = (uint*)(++ptr2);
- count -= 1;
- }
- }
-#endif // BIT64
-
- // Loop comparing a DWORD at a time.
- // Reads are potentially unaligned
- while ((count -= 2) >= 0)
- {
- if ((*((uint*)((byte*)strBChars + diff)) - *strBChars) != 0)
- {
- char* ptr1 = (char*)((byte*)strBChars + diff);
- char* ptr2 = (char*)strBChars;
- if (*ptr1 != *ptr2)
- return ((int)*ptr1 - (int)*ptr2);
- return ((int)*(ptr1 + 1) - (int)*(ptr2 + 1));
- }
- ++strBChars;
- }
-
- int c;
- if (count == -1)
- if ((c = *((char*)((byte*)strBChars + diff)) - *((char*)strBChars)) != 0)
- return c;
- }
-
- return countA - countB;
- }
-#endif
- //
- //
- // NATIVE INSTANCE METHODS
- //
- //
-
- //
// Search/Query methods
//
- //
- // Common worker for the various Equality methods. The caller must have already ensured that
- // both strings are non-null and that their lengths are equal. Ther caller should also have
- // done the Object.ReferenceEquals() fastpath check as we won't repeat it here.
- //
- private static unsafe bool EqualsHelper(String strA, String strB)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static bool EqualsHelper(string strA, string strB)
{
Debug.Assert(strA != null);
Debug.Assert(strB != null);
Debug.Assert(strA.Length == strB.Length);
- int length = strA.Length;
- fixed (char* ap = &strA._firstChar) fixed (char* bp = &strB._firstChar)
- {
- char* a = ap;
- char* b = bp;
-
-#if BIT64
- // Single int read aligns pointers for the following long reads
- // PERF: No length check needed as there is always an int32 worth of string allocated
- // This read can also include the null terminator which both strings will have
- if (*(int*)a != *(int*)b) return false;
- length -= 2; a += 2; b += 2;
-
- // for 64-bit platforms we unroll by 12 and
- // check 3 qword at a time. This is less code
- // than the 32 bit case and is a shorter path length
-
- while (length >= 12)
- {
- if (*(long*)a != *(long*)b) goto ReturnFalse;
- if (*(long*)(a + 4) != *(long*)(b + 4)) goto ReturnFalse;
- if (*(long*)(a + 8) != *(long*)(b + 8)) goto ReturnFalse;
- length -= 12; a += 12; b += 12;
- }
-#else
- while (length >= 10)
- {
- if (*(int*)a != *(int*)b) goto ReturnFalse;
- if (*(int*)(a + 2) != *(int*)(b + 2)) goto ReturnFalse;
- if (*(int*)(a + 4) != *(int*)(b + 4)) goto ReturnFalse;
- if (*(int*)(a + 6) != *(int*)(b + 6)) goto ReturnFalse;
- if (*(int*)(a + 8) != *(int*)(b + 8)) goto ReturnFalse;
- length -= 10; a += 10; b += 10;
- }
-#endif
-
- // This depends on the fact that the String objects are
- // always zero terminated and that the terminating zero is not included
- // in the length. For odd string sizes, the last compare will include
- // the zero terminator.
- while (length > 0)
- {
- if (*(int*)a != *(int*)b) goto ReturnFalse;
- length -= 2; a += 2; b += 2;
- }
-
- return true;
-
- ReturnFalse:
- return false;
- }
+ return SpanHelpers.SequenceEqual(
+ ref Unsafe.As<char, byte>(ref strA.GetRawStringData()),
+ ref Unsafe.As<char, byte>(ref strB.GetRawStringData()),
+ ((nuint)strA.Length) * 2);
}
- private static unsafe bool StartsWithOrdinalHelper(String str, String startsWith)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static int CompareOrdinalHelper(string strA, int indexA, int countA, string strB, int indexB, int countB)
{
- Debug.Assert(str != null);
- Debug.Assert(startsWith != null);
- Debug.Assert(str.Length >= startsWith.Length);
-
- int length = startsWith.Length;
-
- fixed (char* ap = &str._firstChar) fixed (char* bp = &startsWith._firstChar)
- {
- char* a = ap;
- char* b = bp;
-
-#if BIT64
- // Single int read aligns pointers for the following long reads
- // No length check needed as this method is called when length >= 2
- Debug.Assert(length >= 2);
- if (*(int*)a != *(int*)b) goto ReturnFalse;
- length -= 2; a += 2; b += 2;
-
- while (length >= 12)
- {
- if (*(long*)a != *(long*)b) goto ReturnFalse;
- if (*(long*)(a + 4) != *(long*)(b + 4)) goto ReturnFalse;
- if (*(long*)(a + 8) != *(long*)(b + 8)) goto ReturnFalse;
- length -= 12; a += 12; b += 12;
- }
-#else
- while (length >= 10)
- {
- if (*(int*)a != *(int*)b) goto ReturnFalse;
- if (*(int*)(a + 2) != *(int*)(b + 2)) goto ReturnFalse;
- if (*(int*)(a + 4) != *(int*)(b + 4)) goto ReturnFalse;
- if (*(int*)(a + 6) != *(int*)(b + 6)) goto ReturnFalse;
- if (*(int*)(a + 8) != *(int*)(b + 8)) goto ReturnFalse;
- length -= 10; a += 10; b += 10;
- }
-#endif
+ Debug.Assert(strA != null);
+ Debug.Assert(strB != null);
+ Debug.Assert(indexA >= 0 && indexB >= 0);
+ Debug.Assert(countA >= 0 && countB >= 0);
+ Debug.Assert(indexA + countA <= strA.Length && indexB + countB <= strB.Length);
- while (length >= 2)
- {
- if (*(int*)a != *(int*)b) goto ReturnFalse;
- length -= 2; a += 2; b += 2;
- }
+ return SpanHelpers.SequenceCompareTo(ref Unsafe.Add(ref strA.GetRawStringData(), indexA), countA, ref Unsafe.Add(ref strB.GetRawStringData(), indexB), countB);
+ }
- // PERF: This depends on the fact that the String objects are always zero terminated
- // and that the terminating zero is not included in the length. For even string sizes
- // this compare can include the zero terminator. Bitwise OR avoids a branch.
- return length == 0 | *a == *b;
+ private static bool EqualsOrdinalIgnoreCase(string strA, string strB)
+ {
+ Debug.Assert(strA.Length == strB.Length);
- ReturnFalse:
- return false;
- }
+ return CompareInfo.EqualsOrdinalIgnoreCase(ref strA.GetRawStringData(), ref strB.GetRawStringData(), strB.Length);
}
-
- private static unsafe int CompareOrdinalHelper(String strA, String strB)
+ private static unsafe int CompareOrdinalHelper(string strA, string strB)
{
Debug.Assert(strA != null);
Debug.Assert(strB != null);
@@ -310,9 +82,9 @@ namespace System
// and 64-bit (16 bytes) platforms.
// For empty strings, the second char will be null due to padding.
- // The start of the string is the EE type pointer + string length,
- // which takes up 8 bytes on 32-bit, 12 on x64. For empty strings,
- // the null terminator immediately follows, leaving us with an object
+ // The start of the string is the type pointer + string length, which
+ // takes up 8 bytes on 32-bit, 12 on x64. For empty strings the null
+ // terminator immediately follows, leaving us with an object
// 10/14 bytes in size. Since everything needs to be a multiple
// of 4/8, this will get padded and zeroed out.
@@ -348,7 +120,7 @@ namespace System
if (*(int*)(a + 4) != *(int*)(b + 4)) goto DiffOffset4;
if (*(int*)(a + 6) != *(int*)(b + 6)) goto DiffOffset6;
if (*(int*)(a + 8) != *(int*)(b + 8)) goto DiffOffset8;
- length -= 10; a += 10; b += 10;
+ length -= 10; a += 10; b += 10;
}
#endif // BIT64
@@ -371,20 +143,20 @@ namespace System
return strA.Length - strB.Length;
#if BIT64
- DiffOffset8: a += 4; b += 4;
- DiffOffset4: a += 4; b += 4;
+ DiffOffset8: a += 4; b += 4;
+ DiffOffset4: a += 4; b += 4;
#else // BIT64
- // Use jumps instead of falling through, since
- // otherwise going to DiffOffset8 will involve
- // 8 add instructions before getting to DiffNextInt
- DiffOffset8: a += 8; b += 8; goto DiffOffset0;
- DiffOffset6: a += 6; b += 6; goto DiffOffset0;
- DiffOffset4: a += 2; b += 2;
- DiffOffset2: a += 2; b += 2;
+ // Use jumps instead of falling through, since
+ // otherwise going to DiffOffset8 will involve
+ // 8 add instructions before getting to DiffNextInt
+ DiffOffset8: a += 8; b += 8; goto DiffOffset0;
+ DiffOffset6: a += 6; b += 6; goto DiffOffset0;
+ DiffOffset4: a += 2; b += 2;
+ DiffOffset2: a += 2; b += 2;
#endif // BIT64
DiffOffset0:
- // If we reached here, we already see a difference in the unrolled loop above
+ // If we reached here, we already see a difference in the unrolled loop above
#if BIT64
if (*(int*)a == *(int*)b)
{
@@ -401,65 +173,59 @@ namespace System
}
}
- internal static unsafe int CompareOrdinalHelper(string strA, int indexA, int countA, string strB, int indexB, int countB)
- {
- // Argument validation should be handled by callers.
- Debug.Assert(strA != null && strB != null);
- Debug.Assert(indexA >= 0 && indexB >= 0);
- Debug.Assert(countA >= 0 && countB >= 0);
- Debug.Assert(countA <= strA.Length - indexA);
- Debug.Assert(countB <= strB.Length - indexB);
-
- // Set up the loop variables.
- fixed (char* pStrA = &strA._firstChar, pStrB = &strB._firstChar)
- {
- char* strAChars = pStrA + indexA;
- char* strBChars = pStrB + indexB;
- return FastCompareStringHelper((uint*)strAChars, countA, (uint*)strBChars, countB);
- }
- }
-
- public static int Compare(String strA, String strB)
+ // Provides a culture-correct string comparison. StrA is compared to StrB
+ // to determine whether it is lexicographically less, equal, or greater, and then returns
+ // either a negative integer, 0, or a positive integer; respectively.
+ //
+ public static int Compare(string strA, string strB)
{
return Compare(strA, strB, StringComparison.CurrentCulture);
}
- public static int Compare(String strA, String strB, bool ignoreCase)
+
+ // Provides a culture-correct string comparison. strA is compared to strB
+ // to determine whether it is lexicographically less, equal, or greater, and then a
+ // negative integer, 0, or a positive integer is returned; respectively.
+ // The case-sensitive option is set by ignoreCase
+ //
+ public static int Compare(string strA, string strB, bool ignoreCase)
{
var comparisonType = ignoreCase ? StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture;
return Compare(strA, strB, comparisonType);
}
- // Provides a more flexible function for string comparision. See StringComparison
+
+ // Provides a more flexible function for string comparison. See StringComparison
// for meaning of different comparisonType.
- public static int Compare(String strA, String strB, StringComparison comparisonType)
+ public static int Compare(string strA, string strB, StringComparison comparisonType)
{
if (object.ReferenceEquals(strA, strB))
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return 0;
}
// They can't both be null at this point.
if (strA == null)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return -1;
}
if (strB == null)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return 1;
}
-
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, 0, strA.Length, strB, 0, strB.Length, CompareOptions.None);
-
case StringComparison.CurrentCultureIgnoreCase:
- return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, 0, strA.Length, strB, 0, strB.Length, CompareOptions.IgnoreCase);
+ return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, GetCaseCompareOfComparisonCulture(comparisonType));
+
+ case StringComparison.InvariantCulture:
+ case StringComparison.InvariantCultureIgnoreCase:
+ return CompareInfo.Invariant.Compare(strA, strB, GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.Ordinal:
// Most common case: first character is different.
@@ -472,24 +238,19 @@ namespace System
return CompareOrdinalHelper(strA, strB);
case StringComparison.OrdinalIgnoreCase:
- return CompareInfo.CompareOrdinalIgnoreCase(strA, 0, strA.Length, strB, 0, strB.Length);
-
- case StringComparison.InvariantCulture:
- return CompareInfo.Invariant.Compare(strA, strB, CompareOptions.None);
-
- case StringComparison.InvariantCultureIgnoreCase:
- return CompareInfo.Invariant.Compare(strA, strB, CompareOptions.IgnoreCase);
+ return CompareInfo.CompareOrdinalIgnoreCase(strA, strB);
default:
throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
}
}
+
// Provides a culture-correct string comparison. strA is compared to strB
// to determine whether it is lexicographically less, equal, or greater, and then a
// negative integer, 0, or a positive integer is returned; respectively.
//
- public static int Compare(String strA, String strB, CultureInfo culture, CompareOptions options)
+ public static int Compare(string strA, string strB, CultureInfo culture, CompareOptions options)
{
if (culture == null)
{
@@ -499,24 +260,25 @@ namespace System
return culture.CompareInfo.Compare(strA, strB, options);
}
+
+
// Provides a culture-correct string comparison. strA is compared to strB
// to determine whether it is lexicographically less, equal, or greater, and then a
// negative integer, 0, or a positive integer is returned; respectively.
// The case-sensitive option is set by ignoreCase, and the culture is set
// by culture
//
- public static int Compare(String strA, String strB, bool ignoreCase, CultureInfo culture)
+ public static int Compare(string strA, string strB, bool ignoreCase, CultureInfo culture)
{
- CompareOptions options = ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None;
+ var options = ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None;
return Compare(strA, strB, culture, options);
}
// Determines whether two string regions match. The substring of strA beginning
- // at indexA of length length is compared with the substring of strB
+ // at indexA of given length is compared with the substring of strB
// beginning at indexB of the same length.
//
-
- public static int Compare(String strA, int indexA, String strB, int indexB, int length)
+ public static int Compare(string strA, int indexA, string strB, int indexB, int length)
{
// NOTE: It's important we call the boolean overload, and not the StringComparison
// one. The two have some subtly different behavior (see notes in the former).
@@ -524,11 +286,10 @@ namespace System
}
// Determines whether two string regions match. The substring of strA beginning
- // at indexA of length count is compared with the substring of strB
+ // at indexA of given length is compared with the substring of strB
// beginning at indexB of the same length. Case sensitivity is determined by the ignoreCase boolean.
//
-
- public static int Compare(String strA, int indexA, String strB, int indexB, int length, bool ignoreCase)
+ public static int Compare(string strA, int indexA, string strB, int indexB, int length, bool ignoreCase)
{
// Ideally we would just forward to the string.Compare overload that takes
// a StringComparison parameter, and just pass in CurrentCulture/CurrentCultureIgnoreCase.
@@ -539,7 +300,7 @@ namespace System
// - string.Compare(null, -1, null, -1, -1, StringComparison.CurrentCulture) works
// since that method also returns early for nulls before validation. It shouldn't
// for this overload.
- // - Since we originally forwarded to FormatProvider for all of the argument
+ // - Since we originally forwarded to CompareInfo.Compare for all of the argument
// validation logic, the ArgumentOutOfRangeExceptions thrown will contain different
// parameter names.
// Therefore, we have to duplicate some of the logic here.
@@ -557,7 +318,7 @@ namespace System
lengthB = Math.Min(lengthB, strB.Length - indexB);
}
- CompareOptions options = ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None;
+ var options = ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None;
return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, options);
}
@@ -566,17 +327,18 @@ namespace System
// beginning at indexB of the same length. Case sensitivity is determined by the ignoreCase boolean,
// and the culture is set by culture.
//
- public static int Compare(String strA, int indexA, String strB, int indexB, int length, bool ignoreCase, CultureInfo culture)
+ public static int Compare(string strA, int indexA, string strB, int indexB, int length, bool ignoreCase, CultureInfo culture)
{
- CompareOptions options = ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None;
+ var options = ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None;
return Compare(strA, indexA, strB, indexB, length, culture, options);
}
+
// Determines whether two string regions match. The substring of strA beginning
// at indexA of length length is compared with the substring of strB
// beginning at indexB of the same length.
//
- public static int Compare(String strA, int indexA, String strB, int indexB, int length, CultureInfo culture, CompareOptions options)
+ public static int Compare(string strA, int indexA, string strB, int indexB, int length, CultureInfo culture, CompareOptions options)
{
if (culture == null)
{
@@ -599,12 +361,13 @@ namespace System
return culture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, options);
}
- public static int Compare(String strA, int indexA, String strB, int indexB, int length, StringComparison comparisonType)
+ public static int Compare(string strA, int indexA, string strB, int indexB, int length, StringComparison comparisonType)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
if (strA == null || strB == null)
{
+
if (object.ReferenceEquals(strA, strB))
{
// They're both null
@@ -614,7 +377,6 @@ namespace System
return strA == null ? -1 : 1;
}
- // @TODO: Spec#: Figure out what to do here with the return statement above.
if (length < 0)
{
throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NegativeLength);
@@ -643,32 +405,25 @@ namespace System
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.None);
-
case StringComparison.CurrentCultureIgnoreCase:
- return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.IgnoreCase);
-
- case StringComparison.Ordinal:
- return CompareOrdinalHelper(strA, indexA, lengthA, strB, indexB, lengthB);
-
- case StringComparison.OrdinalIgnoreCase:
- return CompareInfo.CompareOrdinalIgnoreCase(strA, indexA, lengthA, strB, indexB, lengthB);
+ return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.InvariantCulture:
- return CompareInfo.Invariant.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.None);
-
case StringComparison.InvariantCultureIgnoreCase:
- return CompareInfo.Invariant.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.IgnoreCase);
+ return CompareInfo.Invariant.Compare(strA, indexA, lengthA, strB, indexB, lengthB, GetCaseCompareOfComparisonCulture(comparisonType));
+
+ case StringComparison.Ordinal:
+ return CompareOrdinalHelper(strA, indexA, lengthA, strB, indexB, lengthB);
default:
- throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
+ Debug.Assert(comparisonType == StringComparison.OrdinalIgnoreCase); // CheckStringComparison validated these earlier
+ return CompareInfo.CompareOrdinalIgnoreCase(strA, indexA, lengthA, strB, indexB, lengthB);
}
}
// Compares strA and strB using an ordinal (code-point) comparison.
//
-
- public static int CompareOrdinal(String strA, String strB)
+ public static int CompareOrdinal(string strA, string strB)
{
if (object.ReferenceEquals(strA, strB))
{
@@ -695,43 +450,13 @@ namespace System
return CompareOrdinalHelper(strA, strB);
}
- // TODO https://github.com/dotnet/corefx/issues/21395: Expose this publicly?
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static int CompareOrdinal(ReadOnlySpan<char> strA, ReadOnlySpan<char> strB)
- {
- // TODO: Add a vectorized code path, similar to SequenceEqual
- // https://github.com/dotnet/corefx/blob/master/src/System.Memory/src/System/SpanHelpers.byte.cs#L900
-
- int minLength = Math.Min(strA.Length, strB.Length);
- ref char first = ref MemoryMarshal.GetReference(strA);
- ref char second = ref MemoryMarshal.GetReference(strB);
+ => SpanHelpers.SequenceCompareTo(ref MemoryMarshal.GetReference(strA), strA.Length, ref MemoryMarshal.GetReference(strB), strB.Length);
- int i = 0;
- if (minLength >= sizeof(nuint) / sizeof(char))
- {
- while (i < minLength - sizeof(nuint) / sizeof(char))
- {
- if (Unsafe.ReadUnaligned<nuint>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref first, i))) !=
- Unsafe.ReadUnaligned<nuint>(ref Unsafe.As<char, byte>(ref Unsafe.Add(ref second, i))))
- {
- break;
- }
- i += sizeof(nuint) / sizeof(char);
- }
- }
- while (i < minLength)
- {
- char a = Unsafe.Add(ref first, i);
- char b = Unsafe.Add(ref second, i);
- if (a != b)
- {
- return a - b;
- }
- i++;
- }
- return strA.Length - strB.Length;
- }
-
- public static int CompareOrdinal(String strA, int indexA, String strB, int indexB, int length)
+ // Compares strA and strB using an ordinal (code-point) comparison.
+ //
+ public static int CompareOrdinal(string strA, int indexA, string strB, int indexB, int length)
{
if (strA == null || strB == null)
{
@@ -779,8 +504,7 @@ namespace System
// indicates the relationship. This method returns a value less than 0 if this is less than value, 0
// if this is equal to value, or a value greater than 0 if this is greater than value.
//
-
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
@@ -799,49 +523,49 @@ namespace System
// Determines the sorting relation of StrB to the current instance.
//
-
- public int CompareTo(String strB)
+ public int CompareTo(string strB)
{
return string.Compare(this, strB, StringComparison.CurrentCulture);
}
- // Determines whether a specified string is a suffix of the the current instance.
+ // Determines whether a specified string is a suffix of the current instance.
//
// The case-sensitive and culture-sensitive option is set by options,
// and the default culture is used.
//
-
- public Boolean EndsWith(String value)
+ public bool EndsWith(string value)
{
return EndsWith(value, StringComparison.CurrentCulture);
}
- public Boolean EndsWith(String value, StringComparison comparisonType)
+ public bool EndsWith(string value, StringComparison comparisonType)
{
- if ((Object)value == null)
+ if ((object)value == null)
{
throw new ArgumentNullException(nameof(value));
}
-
- if ((Object)this == (Object)value)
+
+ if ((object)this == (object)value)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return true;
}
if (value.Length == 0)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return true;
}
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return CultureInfo.CurrentCulture.CompareInfo.IsSuffix(this, value, CompareOptions.None);
-
case StringComparison.CurrentCultureIgnoreCase:
- return CultureInfo.CurrentCulture.CompareInfo.IsSuffix(this, value, CompareOptions.IgnoreCase);
+ return CultureInfo.CurrentCulture.CompareInfo.IsSuffix(this, value, GetCaseCompareOfComparisonCulture(comparisonType));
+
+ case StringComparison.InvariantCulture:
+ case StringComparison.InvariantCultureIgnoreCase:
+ return CompareInfo.Invariant.IsSuffix(this, value, GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.Ordinal:
return this.Length < value.Length ? false : (CompareOrdinalHelper(this, this.Length - value.Length, value.Length, value, 0, value.Length) == 0);
@@ -849,18 +573,12 @@ namespace System
case StringComparison.OrdinalIgnoreCase:
return this.Length < value.Length ? false : (CompareInfo.CompareOrdinalIgnoreCase(this, this.Length - value.Length, value.Length, value, 0, value.Length) == 0);
- case StringComparison.InvariantCulture:
- return CompareInfo.Invariant.IsSuffix(this, value, CompareOptions.None);
-
- case StringComparison.InvariantCultureIgnoreCase:
- return CompareInfo.Invariant.IsSuffix(this, value, CompareOptions.IgnoreCase);
-
default:
throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
}
}
- public Boolean EndsWith(String value, Boolean ignoreCase, CultureInfo culture)
+ public bool EndsWith(string value, bool ignoreCase, CultureInfo culture)
{
if (null == value)
{
@@ -872,12 +590,7 @@ namespace System
return true;
}
- CultureInfo referenceCulture;
- if (culture == null)
- referenceCulture = CultureInfo.CurrentCulture;
- else
- referenceCulture = culture;
-
+ CultureInfo referenceCulture = culture ?? CultureInfo.CurrentCulture;
return referenceCulture.CompareInfo.IsSuffix(this, value, ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None);
}
@@ -888,13 +601,12 @@ namespace System
}
// Determines whether two strings match.
-
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (Object.ReferenceEquals(this, obj))
+ if (object.ReferenceEquals(this, obj))
return true;
- String str = obj as String;
+ string str = obj as string;
if (str == null)
return false;
@@ -905,11 +617,9 @@ namespace System
}
// Determines whether two strings match.
-
-
- public bool Equals(String value)
+ public bool Equals(string value)
{
- if (Object.ReferenceEquals(this, value))
+ if (object.ReferenceEquals(this, value))
return true;
// NOTE: No need to worry about casting to object here.
@@ -925,28 +635,29 @@ namespace System
return EqualsHelper(this, value);
}
-
- public bool Equals(String value, StringComparison comparisonType)
+ public bool Equals(string value, StringComparison comparisonType)
{
- if ((Object)this == (Object)value)
+ if ((object)this == (object)value)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return true;
}
- if ((Object)value == null)
+ if ((object)value == null)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return false;
}
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return (CultureInfo.CurrentCulture.CompareInfo.Compare(this, 0, this.Length, value, 0, value.Length, CompareOptions.None) == 0);
-
case StringComparison.CurrentCultureIgnoreCase:
- return (CultureInfo.CurrentCulture.CompareInfo.Compare(this, 0, this.Length, value, 0, value.Length, CompareOptions.IgnoreCase) == 0);
+ return (CultureInfo.CurrentCulture.CompareInfo.Compare(this, value, GetCaseCompareOfComparisonCulture(comparisonType)) == 0);
+
+ case StringComparison.InvariantCulture:
+ case StringComparison.InvariantCultureIgnoreCase:
+ return (CompareInfo.Invariant.Compare(this, value, GetCaseCompareOfComparisonCulture(comparisonType)) == 0);
case StringComparison.Ordinal:
if (this.Length != value.Length)
@@ -956,32 +667,24 @@ namespace System
case StringComparison.OrdinalIgnoreCase:
if (this.Length != value.Length)
return false;
- else
- {
- return CompareInfo.CompareOrdinalIgnoreCase(this, 0, this.Length, value, 0, value.Length) == 0;
- }
- case StringComparison.InvariantCulture:
- return (CompareInfo.Invariant.Compare(this, value, CompareOptions.None) == 0);
-
- case StringComparison.InvariantCultureIgnoreCase:
- return (CompareInfo.Invariant.Compare(this, value, CompareOptions.IgnoreCase) == 0);
+ return EqualsOrdinalIgnoreCase(this, value);
default:
throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
}
}
- // Determines whether two Strings match.
- public static bool Equals(String a, String b)
+ // Determines whether two Strings match.
+ public static bool Equals(string a, string b)
{
- if ((Object)a == (Object)b)
+ if ((object)a == (object)b)
{
return true;
}
- if ((Object)a == null || (Object)b == null || a.Length != b.Length)
+ if ((object)a == null || (object)b == null || a.Length != b.Length)
{
return false;
}
@@ -989,27 +692,29 @@ namespace System
return EqualsHelper(a, b);
}
- public static bool Equals(String a, String b, StringComparison comparisonType)
+ public static bool Equals(string a, string b, StringComparison comparisonType)
{
- if ((Object)a == (Object)b)
+ if ((object)a == (object)b)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return true;
}
- if ((Object)a == null || (Object)b == null)
+ if ((object)a == null || (object)b == null)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return false;
}
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return (CultureInfo.CurrentCulture.CompareInfo.Compare(a, 0, a.Length, b, 0, b.Length, CompareOptions.None) == 0);
-
case StringComparison.CurrentCultureIgnoreCase:
- return (CultureInfo.CurrentCulture.CompareInfo.Compare(a, 0, a.Length, b, 0, b.Length, CompareOptions.IgnoreCase) == 0);
+ return (CultureInfo.CurrentCulture.CompareInfo.Compare(a, b, GetCaseCompareOfComparisonCulture(comparisonType)) == 0);
+
+ case StringComparison.InvariantCulture:
+ case StringComparison.InvariantCultureIgnoreCase:
+ return (CompareInfo.Invariant.Compare(a, b, GetCaseCompareOfComparisonCulture(comparisonType)) == 0);
case StringComparison.Ordinal:
if (a.Length != b.Length)
@@ -1019,38 +724,22 @@ namespace System
case StringComparison.OrdinalIgnoreCase:
if (a.Length != b.Length)
return false;
- else
- {
- return CompareInfo.CompareOrdinalIgnoreCase(a, 0, a.Length, b, 0, b.Length) == 0;
- }
-
- case StringComparison.InvariantCulture:
- return (CompareInfo.Invariant.Compare(a, b, CompareOptions.None) == 0);
- case StringComparison.InvariantCultureIgnoreCase:
- return (CompareInfo.Invariant.Compare(a, b, CompareOptions.IgnoreCase) == 0);
+ return EqualsOrdinalIgnoreCase(a, b);
default:
throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
}
}
- public static bool operator ==(String a, String b)
+ public static bool operator ==(string a, string b)
{
- if (Object.ReferenceEquals(a, b))
- return true;
- if (a == null || b == null || a.Length != b.Length)
- return false;
- return EqualsHelper(a, b);
+ return string.Equals(a, b);
}
- public static bool operator !=(String a, String b)
+ public static bool operator !=(string a, string b)
{
- if (Object.ReferenceEquals(a, b))
- return false;
- if (a == null || b == null || a.Length != b.Length)
- return true;
- return !EqualsHelper(a, b);
+ return !string.Equals(a, b);
}
// Gets a hash code for this string. If strings A and B are such that A.Equals(B), then
@@ -1065,97 +754,82 @@ namespace System
}
// Gets a hash code for this string and this comparison. If strings A and B and comparison C are such
- // that String.Equals(A, B, C), then they will return the same hash code with this comparison C.
+ // that string.Equals(A, B, C), then they will return the same hash code with this comparison C.
public int GetHashCode(StringComparison comparisonType) => StringComparer.FromComparison(comparisonType).GetHashCode(this);
- // Use this if and only if you need the hashcode to not change across app domains (e.g. you have an app domain agile
- // hash table).
- internal int GetLegacyNonRandomizedHashCode()
+ // Use this if and only if 'Denial of Service' attacks are not a concern (i.e. never used for free-form user input),
+ // or are otherwise mitigated
+ internal unsafe int GetNonRandomizedHashCode()
{
- unsafe
+ fixed (char* src = &_firstChar)
{
- fixed (char* src = &_firstChar)
- {
- Debug.Assert(src[this.Length] == '\0', "src[this.Length] == '\\0'");
- Debug.Assert(((int)src) % 4 == 0, "Managed string should start at 4 bytes boundary");
-#if BIT64
- int hash1 = 5381;
-#else // !BIT64 (32)
- int hash1 = (5381<<16) + 5381;
-#endif
- int hash2 = hash1;
+ Debug.Assert(src[this.Length] == '\0', "src[this.Length] == '\\0'");
+ Debug.Assert(((int)src) % 4 == 0, "Managed string should start at 4 bytes boundary");
-#if BIT64
- int c;
- char* s = src;
- while ((c = s[0]) != 0)
- {
- hash1 = ((hash1 << 5) + hash1) ^ c;
- c = s[1];
- if (c == 0)
- break;
- hash2 = ((hash2 << 5) + hash2) ^ c;
- s += 2;
- }
-#else // !BIT64 (32)
- // 32 bit machines.
- int* pint = (int *)src;
- int len = this.Length;
- while (len > 2)
- {
- hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27)) ^ pint[0];
- hash2 = ((hash2 << 5) + hash2 + (hash2 >> 27)) ^ pint[1];
- pint += 2;
- len -= 4;
- }
+ uint hash1 = (5381 << 16) + 5381;
+ uint hash2 = hash1;
- if (len > 0)
- {
- hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27)) ^ pint[0];
- }
-#endif
- return hash1 + (hash2 * 1566083941);
+ uint* ptr = (uint*)src;
+ int length = this.Length;
+
+ while (length > 2)
+ {
+ length -= 4;
+ // Where length is 4n-1 (e.g. 3,7,11,15,19) this additionally consumes the null terminator
+ hash1 = (((hash1 << 5) | (hash1 >> 27)) + hash1) ^ ptr[0];
+ hash2 = (((hash2 << 5) | (hash2 >> 27)) + hash2) ^ ptr[1];
+ ptr += 2;
}
+
+ if (length > 0)
+ {
+ // Where length is 4n-3 (e.g. 1,5,9,13,17) this additionally consumes the null terminator
+ hash2 = (((hash2 << 5) | (hash2 >> 27)) + hash2) ^ ptr[0];
+ }
+
+ return (int)(hash1 + (hash2 * 1566083941));
}
}
// Determines whether a specified string is a prefix of the current instance
//
- public Boolean StartsWith(String value)
+ public bool StartsWith(string value)
{
- if ((Object)value == null)
+ if ((object)value == null)
{
throw new ArgumentNullException(nameof(value));
}
return StartsWith(value, StringComparison.CurrentCulture);
}
- public Boolean StartsWith(String value, StringComparison comparisonType)
+ public bool StartsWith(string value, StringComparison comparisonType)
{
- if ((Object)value == null)
+ if ((object)value == null)
{
throw new ArgumentNullException(nameof(value));
}
- if ((Object)this == (Object)value)
+ if ((object)this == (object)value)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return true;
}
if (value.Length == 0)
{
- StringSpanHelpers.CheckStringComparison(comparisonType);
+ CheckStringComparison(comparisonType);
return true;
}
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return CultureInfo.CurrentCulture.CompareInfo.IsPrefix(this, value, CompareOptions.None);
-
case StringComparison.CurrentCultureIgnoreCase:
- return CultureInfo.CurrentCulture.CompareInfo.IsPrefix(this, value, CompareOptions.IgnoreCase);
+ return CultureInfo.CurrentCulture.CompareInfo.IsPrefix(this, value, GetCaseCompareOfComparisonCulture(comparisonType));
+
+ case StringComparison.InvariantCulture:
+ case StringComparison.InvariantCultureIgnoreCase:
+ return CompareInfo.Invariant.IsPrefix(this, value, GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.Ordinal:
if (this.Length < value.Length || _firstChar != value._firstChar)
@@ -1163,28 +837,25 @@ namespace System
return false;
}
return (value.Length == 1) ?
- true : // First char is the same and thats all there is to compare
- StartsWithOrdinalHelper(this, value);
+ true : // First char is the same and thats all there is to compare
+ SpanHelpers.SequenceEqual(
+ ref Unsafe.As<char, byte>(ref this.GetRawStringData()),
+ ref Unsafe.As<char, byte>(ref value.GetRawStringData()),
+ ((nuint)value.Length) * 2);
case StringComparison.OrdinalIgnoreCase:
if (this.Length < value.Length)
{
return false;
}
- return CompareInfo.CompareOrdinalIgnoreCase(this, 0, value.Length, value, 0, value.Length) == 0;
-
- case StringComparison.InvariantCulture:
- return CompareInfo.Invariant.IsPrefix(this, value, CompareOptions.None);
-
- case StringComparison.InvariantCultureIgnoreCase:
- return CompareInfo.Invariant.IsPrefix(this, value, CompareOptions.IgnoreCase);
+ return CompareInfo.EqualsOrdinalIgnoreCase(ref this.GetRawStringData(), ref value.GetRawStringData(), value.Length);
default:
throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
}
}
- public Boolean StartsWith(String value, Boolean ignoreCase, CultureInfo culture)
+ public bool StartsWith(string value, bool ignoreCase, CultureInfo culture)
{
if (null == value)
{
@@ -1196,15 +867,39 @@ namespace System
return true;
}
- CultureInfo referenceCulture;
- if (culture == null)
- referenceCulture = CultureInfo.CurrentCulture;
- else
- referenceCulture = culture;
-
+ CultureInfo referenceCulture = culture ?? CultureInfo.CurrentCulture;
return referenceCulture.CompareInfo.IsPrefix(this, value, ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None);
}
public bool StartsWith(char value) => Length != 0 && _firstChar == value;
+
+ internal static void CheckStringComparison(StringComparison comparisonType)
+ {
+ // Single comparison to check if comparisonType is within [CurrentCulture .. OrdinalIgnoreCase]
+ if ((uint)comparisonType > (uint)StringComparison.OrdinalIgnoreCase)
+ {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.NotSupported_StringComparison, ExceptionArgument.comparisonType);
+ }
+ }
+
+ internal static CompareOptions GetCaseCompareOfComparisonCulture(StringComparison comparisonType)
+ {
+ Debug.Assert((uint)comparisonType <= (uint)StringComparison.OrdinalIgnoreCase);
+
+ // Culture enums can be & with CompareOptions.IgnoreCase 0x01 to extract if IgnoreCase or CompareOptions.None 0x00
+ //
+ // CompareOptions.None 0x00
+ // CompareOptions.IgnoreCase 0x01
+ //
+ // StringComparison.CurrentCulture: 0x00
+ // StringComparison.InvariantCulture: 0x02
+ // StringComparison.Ordinal 0x04
+ //
+ // StringComparison.CurrentCultureIgnoreCase: 0x01
+ // StringComparison.InvariantCultureIgnoreCase: 0x03
+ // StringComparison.OrdinalIgnoreCase 0x05
+
+ return (CompareOptions)((int)comparisonType & (int)CompareOptions.IgnoreCase);
+ }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/String.Manipulation.cs b/src/System.Private.CoreLib/shared/System/String.Manipulation.cs
index 9ea2ef0f0..3da96bb3b 100644
--- a/src/System.Private.CoreLib/shared/System/String.Manipulation.cs
+++ b/src/System.Private.CoreLib/shared/System/String.Manipulation.cs
@@ -897,7 +897,7 @@ namespace System
return result;
}
- // a remove that just takes a startindex.
+ // a remove that just takes a startindex.
public string Remove(int startIndex)
{
if (startIndex < 0)
@@ -919,16 +919,12 @@ namespace System
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return ReplaceCore(oldValue, newValue, CultureInfo.CurrentCulture, CompareOptions.None);
-
case StringComparison.CurrentCultureIgnoreCase:
- return ReplaceCore(oldValue, newValue, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase);
+ return ReplaceCore(oldValue, newValue, CultureInfo.CurrentCulture, GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.InvariantCulture:
- return ReplaceCore(oldValue, newValue, CultureInfo.InvariantCulture, CompareOptions.None);
-
case StringComparison.InvariantCultureIgnoreCase:
- return ReplaceCore(oldValue, newValue, CultureInfo.InvariantCulture, CompareOptions.IgnoreCase);
+ return ReplaceCore(oldValue, newValue, CultureInfo.InvariantCulture, GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.Ordinal:
return Replace(oldValue, newValue);
@@ -1140,7 +1136,7 @@ namespace System
int count = replacementIdx - thisIdx;
if (count != 0)
{
- this.AsSpan().Slice(thisIdx, count).CopyTo(dstSpan.Slice(dstIdx));
+ this.AsSpan(thisIdx, count).CopyTo(dstSpan.Slice(dstIdx));
dstIdx += count;
}
thisIdx = replacementIdx + oldValueLength;
@@ -1152,7 +1148,7 @@ namespace System
// Copy over the final non-matching portion at the end of the string.
Debug.Assert(this.Length - thisIdx == dstSpan.Length - dstIdx);
- this.AsSpan().Slice(thisIdx).CopyTo(dstSpan.Slice(dstIdx));
+ this.AsSpan(thisIdx).CopyTo(dstSpan.Slice(dstIdx));
return dst;
}
@@ -1252,7 +1248,7 @@ namespace System
return new string[] { this };
}
- string[] result = omitEmptyEntries
+ string[] result = omitEmptyEntries
? SplitOmitEmptyEntries(sepList, default, 1, count)
: SplitKeepEmptyEntries(sepList, default, 1, count);
@@ -1266,7 +1262,7 @@ namespace System
return SplitInternal(separator ?? string.Empty, null, int.MaxValue, options);
}
- public string[] Split(string separator, Int32 count, StringSplitOptions options = StringSplitOptions.None)
+ public string[] Split(string separator, int count, StringSplitOptions options = StringSplitOptions.None)
{
return SplitInternal(separator ?? string.Empty, null, count, options);
}
@@ -1276,7 +1272,7 @@ namespace System
return SplitInternal(null, separator, int.MaxValue, options);
}
- public string[] Split(string[] separator, Int32 count, StringSplitOptions options)
+ public string[] Split(string[] separator, int count, StringSplitOptions options)
{
return SplitInternal(null, separator, count, options);
}
@@ -1317,7 +1313,7 @@ namespace System
{
return SplitInternal(separator, count, options);
}
-
+
Span<int> sepListInitialSpan = stackalloc int[StackallocIntBufferSizeLimit];
var sepListBuilder = new ValueListBuilder<int>(sepListInitialSpan);
@@ -1327,14 +1323,14 @@ namespace System
MakeSeparatorList(separators, ref sepListBuilder, ref lengthListBuilder);
ReadOnlySpan<int> sepList = sepListBuilder.AsSpan();
ReadOnlySpan<int> lengthList = lengthListBuilder.AsSpan();
-
+
// Handle the special case of no replaces.
if (sepList.Length == 0)
{
return new string[] { this };
}
- string[] result = omitEmptyEntries
+ string[] result = omitEmptyEntries
? SplitOmitEmptyEntries(sepList, lengthList, 0, count)
: SplitKeepEmptyEntries(sepList, lengthList, 0, count);
@@ -1357,7 +1353,7 @@ namespace System
return new string[] { this };
}
- string[] result = options == StringSplitOptions.RemoveEmptyEntries
+ string[] result = options == StringSplitOptions.RemoveEmptyEntries
? SplitOmitEmptyEntries(sepList, default, separator.Length, count)
: SplitKeepEmptyEntries(sepList, default, separator.Length, count);
@@ -1402,15 +1398,15 @@ namespace System
}
- // This function will not keep the Empty string
+ // This function will not keep the Empty string
private string[] SplitOmitEmptyEntries(ReadOnlySpan<int> sepList, ReadOnlySpan<int> lengthList, int defaultLength, int count)
{
Debug.Assert(count >= 2);
int numReplaces = sepList.Length;
- // Allocate array to hold items. This array may not be
- // filled completely in this function, we will create a
+ // Allocate array to hold items. This array may not be
+ // filled completely in this function, we will create a
// new array and copy string references to that new array.
int maxItems = (numReplaces < count) ? (numReplaces + 1) : count;
string[] splitStrings = new string[maxItems];
@@ -1557,7 +1553,7 @@ namespace System
if (this[i] == separator[0] && currentSepLength <= Length - i)
{
if (currentSepLength == 1
- || CompareOrdinal(this, i, separator, 0, currentSepLength) == 0)
+ || this.AsSpan(i, currentSepLength).SequenceEqual(separator))
{
sepListBuilder.Append(i);
i += currentSepLength - 1;
@@ -1571,7 +1567,7 @@ namespace System
/// </summary>
/// <param name="separators">separator strngs</param>
/// <param name="sepListBuilder"><see cref="ValueListBuilder{T}"/> for separator indexes</param>
- /// <param name="lengthListBuilder"><see cref="ValueListBuilder{T}"/> for separator length values</param>
+ /// <param name="lengthListBuilder"><see cref="ValueListBuilder{T}"/> for separator length values</param>
private void MakeSeparatorList(string[] separators, ref ValueListBuilder<int> sepListBuilder, ref ValueListBuilder<int> lengthListBuilder)
{
Debug.Assert(separators != null && separators.Length > 0, "separators != null && separators.Length > 0");
@@ -1591,7 +1587,7 @@ namespace System
if (this[i] == separator[0] && currentSepLength <= Length - i)
{
if (currentSepLength == 1
- || CompareOrdinal(this, i, separator, 0, currentSepLength) == 0)
+ || this.AsSpan(i, currentSepLength).SequenceEqual(separator))
{
sepListBuilder.Append(i);
lengthListBuilder.Append(currentSepLength);
@@ -1702,7 +1698,7 @@ namespace System
}
// Trims the whitespace from both ends of the string. Whitespace is defined by
- // Char.IsWhiteSpace.
+ // char.IsWhiteSpace.
//
public string Trim() => TrimWhiteSpaceHelper(TrimType.Both);
diff --git a/src/System.Private.CoreLib/shared/System/String.Searching.cs b/src/System.Private.CoreLib/shared/System/String.Searching.cs
index c86d13524..7660c5225 100644
--- a/src/System.Private.CoreLib/shared/System/String.Searching.cs
+++ b/src/System.Private.CoreLib/shared/System/String.Searching.cs
@@ -22,10 +22,7 @@ namespace System
return (IndexOf(value, comparisonType) >= 0);
}
- public bool Contains(char value)
- {
- return IndexOf(value) != -1;
- }
+ public bool Contains(char value) => SpanHelpers.Contains(ref _firstChar, value, Length);
public bool Contains(char value, StringComparison comparisonType)
{
@@ -35,10 +32,7 @@ namespace System
// Returns the index of the first occurrence of a specified character in the current instance.
// The search starts at startIndex and runs thorough the next count characters.
//
- public int IndexOf(char value)
- {
- return IndexOf(value, 0, this.Length);
- }
+ public int IndexOf(char value) => SpanHelpers.IndexOf(ref _firstChar, value, Length);
public int IndexOf(char value, int startIndex)
{
@@ -50,19 +44,15 @@ namespace System
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, CompareOptions.None);
-
case StringComparison.CurrentCultureIgnoreCase:
- return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, CompareOptions.IgnoreCase);
+ return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.InvariantCulture:
- return CompareInfo.Invariant.IndexOf(this, value, CompareOptions.None);
-
case StringComparison.InvariantCultureIgnoreCase:
- return CompareInfo.Invariant.IndexOf(this, value, CompareOptions.IgnoreCase);
+ return CompareInfo.Invariant.IndexOf(this, value, GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.Ordinal:
- return CompareInfo.Invariant.IndexOf(this, value, CompareOptions.Ordinal);
+ return IndexOf(value);
case StringComparison.OrdinalIgnoreCase:
return CompareInfo.Invariant.IndexOf(this, value, CompareOptions.OrdinalIgnoreCase);
@@ -80,116 +70,11 @@ namespace System
if ((uint)count > (uint)(Length - startIndex))
throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count);
- fixed (char* pChars = &_firstChar)
- {
- char* pCh = pChars + startIndex;
- char* pEndCh = pCh + count;
-
- if (Vector.IsHardwareAccelerated && count >= Vector<ushort>.Count * 2)
- {
- unchecked
- {
- const int elementsPerByte = sizeof(ushort) / sizeof(byte);
- int unaligned = ((int)pCh & (Vector<byte>.Count - 1)) / elementsPerByte;
- count = ((Vector<ushort>.Count - unaligned) & (Vector<ushort>.Count - 1));
- }
- }
- SequentialScan:
- while (count >= 4)
- {
- if (*pCh == value) goto ReturnIndex;
- if (*(pCh + 1) == value) goto ReturnIndex1;
- if (*(pCh + 2) == value) goto ReturnIndex2;
- if (*(pCh + 3) == value) goto ReturnIndex3;
-
- count -= 4;
- pCh += 4;
- }
-
- while (count > 0)
- {
- if (*pCh == value)
- goto ReturnIndex;
-
- count--;
- pCh++;
- }
-
- if (pCh < pEndCh)
- {
- count = (int)((pEndCh - pCh) & ~(Vector<ushort>.Count - 1));
- // Get comparison Vector
- Vector<ushort> vComparison = new Vector<ushort>(value);
- while (count > 0)
- {
- var vMatches = Vector.Equals(vComparison, Unsafe.ReadUnaligned<Vector<ushort>>(pCh));
- if (Vector<ushort>.Zero.Equals(vMatches))
- {
- pCh += Vector<ushort>.Count;
- count -= Vector<ushort>.Count;
- continue;
- }
- // Find offset of first match
- return (int)(pCh - pChars) + LocateFirstFoundChar(vMatches);
- }
-
- if (pCh < pEndCh)
- {
- unchecked
- {
- count = (int)(pEndCh - pCh);
- }
- goto SequentialScan;
- }
- }
+ int result = SpanHelpers.IndexOf(ref Unsafe.Add(ref _firstChar, startIndex), value, count);
- return -1;
-
- ReturnIndex3: pCh++;
- ReturnIndex2: pCh++;
- ReturnIndex1: pCh++;
- ReturnIndex:
- return (int)(pCh - pChars);
- }
+ return result == -1 ? result : result + startIndex;
}
- // Vector sub-search adapted from https://github.com/aspnet/KestrelHttpServer/pull/1138
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static int LocateFirstFoundChar(Vector<ushort> match)
- {
- var vector64 = Vector.AsVectorUInt64(match);
- ulong candidate = 0;
- int i = 0;
- // Pattern unrolled by jit https://github.com/dotnet/coreclr/pull/8001
- for (; i < Vector<ulong>.Count; i++)
- {
- candidate = vector64[i];
- if (candidate != 0)
- {
- break;
- }
- }
-
- // Single LEA instruction with jitted const (using function result)
- return i * 4 + LocateFirstFoundChar(candidate);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static int LocateFirstFoundChar(ulong match)
- {
- unchecked
- {
- // Flag least significant power of two bit
- var powerOfTwoFlag = match ^ (match - 1);
- // Shift all powers of two into the high byte and extract
- return (int)((powerOfTwoFlag * XorPowerOfTwoToHighChar) >> 49);
- }
- }
-
- private const ulong XorPowerOfTwoToHighChar = (0x03ul |
- 0x02ul << 16 |
- 0x01ul << 32) + 1;
-
// Returns the index of the first occurrence of any specified character in the current instance.
// The search starts at startIndex and runs to startIndex + count - 1.
//
@@ -289,7 +174,7 @@ namespace System
private unsafe int IndexOfCharArray(char[] anyOf, int startIndex, int count)
{
// use probabilistic map, see InitializeProbabilisticMap
- ProbabilisticMap map = default(ProbabilisticMap);
+ ProbabilisticMap map = default;
uint* charMap = (uint*)&map;
InitializeProbabilisticMap(charMap, anyOf);
@@ -374,12 +259,12 @@ namespace System
return false;
}
- private unsafe static bool IsCharBitSet(uint* charMap, byte value)
+ private static unsafe bool IsCharBitSet(uint* charMap, byte value)
{
return (charMap[value & PROBABILISTICMAP_BLOCK_INDEX_MASK] & (1u << (value >> PROBABILISTICMAP_BLOCK_INDEX_SHIFT))) != 0;
}
- private unsafe static void SetCharBit(uint* charMap, byte value)
+ private static unsafe void SetCharBit(uint* charMap, byte value)
{
charMap[value & PROBABILISTICMAP_BLOCK_INDEX_MASK] |= 1u << (value >> PROBABILISTICMAP_BLOCK_INDEX_SHIFT);
}
@@ -434,22 +319,16 @@ namespace System
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.None);
-
case StringComparison.CurrentCultureIgnoreCase:
- return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase);
+ return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, startIndex, count, GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.InvariantCulture:
- return CompareInfo.Invariant.IndexOf(this, value, startIndex, count, CompareOptions.None);
-
case StringComparison.InvariantCultureIgnoreCase:
- return CompareInfo.Invariant.IndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase);
+ return CompareInfo.Invariant.IndexOf(this, value, startIndex, count, GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.Ordinal:
- return CompareInfo.Invariant.IndexOfOrdinal(this, value, startIndex, count, ignoreCase: false);
-
case StringComparison.OrdinalIgnoreCase:
- return CompareInfo.Invariant.IndexOfOrdinal(this, value, startIndex, count, ignoreCase: true);
+ return CompareInfo.Invariant.IndexOfOrdinal(this, value, startIndex, count, GetCaseCompareOfComparisonCulture(comparisonType) != CompareOptions.None);
default:
throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
@@ -461,10 +340,7 @@ namespace System
// The character at position startIndex is included in the search. startIndex is the larger
// index within the string.
//
- public int LastIndexOf(char value)
- {
- return LastIndexOf(value, this.Length - 1, this.Length);
- }
+ public int LastIndexOf(char value) => SpanHelpers.LastIndexOf(ref _firstChar, value, Length);
public int LastIndexOf(char value, int startIndex)
{
@@ -482,112 +358,10 @@ namespace System
if ((uint)count > (uint)startIndex + 1)
throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count);
- fixed (char* pChars = &_firstChar)
- {
- char* pCh = pChars + startIndex;
- char* pEndCh = pCh - count;
-
- //We search [startIndex..EndIndex]
- if (Vector.IsHardwareAccelerated && count >= Vector<ushort>.Count * 2)
- {
- unchecked
- {
- const int elementsPerByte = sizeof(ushort) / sizeof(byte);
- count = (((int)pCh & (Vector<byte>.Count - 1)) / elementsPerByte) + 1;
- }
- }
- SequentialScan:
- while (count >= 4)
- {
- if (*pCh == value) goto ReturnIndex;
- if (*(pCh - 1) == value) goto ReturnIndex1;
- if (*(pCh - 2) == value) goto ReturnIndex2;
- if (*(pCh - 3) == value) goto ReturnIndex3;
+ int startSearchAt = startIndex + 1 - count;
+ int result = SpanHelpers.LastIndexOf(ref Unsafe.Add(ref _firstChar, startSearchAt), value, count);
- count -= 4;
- pCh -= 4;
- }
-
- while (count > 0)
- {
- if (*pCh == value)
- goto ReturnIndex;
-
- count--;
- pCh--;
- }
-
- if (pCh > pEndCh)
- {
- count = (int)((pCh - pEndCh) & ~(Vector<ushort>.Count - 1));
-
- // Get comparison Vector
- Vector<ushort> vComparison = new Vector<ushort>(value);
- while (count > 0)
- {
- char* pStart = pCh - Vector<ushort>.Count + 1;
- var vMatches = Vector.Equals(vComparison, Unsafe.ReadUnaligned<Vector<ushort>>(pStart));
- if (Vector<ushort>.Zero.Equals(vMatches))
- {
- pCh -= Vector<ushort>.Count;
- count -= Vector<ushort>.Count;
- continue;
- }
- // Find offset of last match
- return (int)(pStart - pChars) + LocateLastFoundChar(vMatches);
- }
-
- if (pCh > pEndCh)
- {
- unchecked
- {
- count = (int)(pCh - pEndCh);
- }
- goto SequentialScan;
- }
- }
- return -1;
-
- ReturnIndex3: pCh--;
- ReturnIndex2: pCh--;
- ReturnIndex1: pCh--;
- ReturnIndex:
- return (int)(pCh - pChars);
- }
- }
-
- // Vector sub-search adapted from https://github.com/aspnet/KestrelHttpServer/pull/1138
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static int LocateLastFoundChar(Vector<ushort> match)
- {
- var vector64 = Vector.AsVectorUInt64(match);
- ulong candidate = 0;
- int i = Vector<ulong>.Count - 1;
- // Pattern unrolled by jit https://github.com/dotnet/coreclr/pull/8001
- for (; i >= 0; i--)
- {
- candidate = vector64[i];
- if (candidate != 0)
- {
- break;
- }
- }
-
- // Single LEA instruction with jitted const (using function result)
- return i * 4 + LocateLastFoundChar(candidate);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static int LocateLastFoundChar(ulong match)
- {
- // Find the most significant char that has its highest bit set
- int index = 3;
- while ((long)match > 0)
- {
- match = match << 16;
- index--;
- }
- return index;
+ return result == -1 ? result : result + startSearchAt;
}
// Returns the index of the last occurrence of any specified character in the current instance.
@@ -640,7 +414,7 @@ namespace System
private unsafe int LastIndexOfCharArray(char[] anyOf, int startIndex, int count)
{
// use probabilistic map, see InitializeProbabilisticMap
- ProbabilisticMap map = default(ProbabilisticMap);
+ ProbabilisticMap map = default;
uint* charMap = (uint*)&map;
InitializeProbabilisticMap(charMap, anyOf);
@@ -735,22 +509,16 @@ namespace System
switch (comparisonType)
{
case StringComparison.CurrentCulture:
- return CultureInfo.CurrentCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, CompareOptions.None);
-
case StringComparison.CurrentCultureIgnoreCase:
- return CultureInfo.CurrentCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase);
+ return CultureInfo.CurrentCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.InvariantCulture:
- return CompareInfo.Invariant.LastIndexOf(this, value, startIndex, count, CompareOptions.None);
-
case StringComparison.InvariantCultureIgnoreCase:
- return CompareInfo.Invariant.LastIndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase);
+ return CompareInfo.Invariant.LastIndexOf(this, value, startIndex, count, GetCaseCompareOfComparisonCulture(comparisonType));
case StringComparison.Ordinal:
- return CompareInfo.Invariant.LastIndexOfOrdinal(this, value, startIndex, count, ignoreCase: false);
-
case StringComparison.OrdinalIgnoreCase:
- return CompareInfo.Invariant.LastIndexOfOrdinal(this, value, startIndex, count, ignoreCase: true);
+ return CompareInfo.Invariant.LastIndexOfOrdinal(this, value, startIndex, count, GetCaseCompareOfComparisonCulture(comparisonType) != CompareOptions.None);
default:
throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
diff --git a/src/System.Private.CoreLib/src/System/String.cs b/src/System.Private.CoreLib/shared/System/String.cs
index 4e43f26c3..c573072eb 100644
--- a/src/System.Private.CoreLib/src/System/String.cs
+++ b/src/System.Private.CoreLib/shared/System/String.cs
@@ -2,115 +2,66 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-/*============================================================
-**
-** Purpose: Your favorite String class. Native methods
-** are implemented in StringNative.cpp
-**
-===========================================================*/
-
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
-using System.Runtime;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
-using Internal.Runtime.CompilerServices;
-
namespace System
{
// The String class represents a static string of characters. Many of
- // the String methods perform some type of transformation on the current
- // instance and return the result as a new String. All comparison methods are
- // implemented as a part of String. As with arrays, character positions
- // (indices) are zero-based.
-
- // STRING LAYOUT
- // -------------
- // Strings are null-terminated for easy interop with native, but the value returned by String.Length
- // does NOT include this null character in its count. As a result, there's some trickiness here in the
- // layout and allocation of strings that needs explanation...
- //
- // String is allocated like any other array, using the RhNewArray API. It is essentially a very special
- // char[] object. In order to be an array, the String EEType must have an 'array element size' of 2,
- // which is setup by a special case in the binder. Strings must also have a typical array instance
- // layout, which means that the first field after the m_pEEType field is the 'number of array elements'
- // field. However, here, it is called _stringLength because it contains the number of characters in the
- // string (NOT including the terminating null element) and, thus, directly represents both the array
- // length and String.Length.
- //
- // As with all arrays, the GC calculates the size of an object using the following formula:
- //
- // obj_size = align(base_size + (num_elements * element_size), sizeof(void*))
- //
- // The values 'base_size' and 'element_size' are both stored in the EEType for String and 'num_elements'
- // is _stringLength.
- //
- // Our base_size is the size of the fixed portion of the string defined below. It, therefore, contains
- // the size of the _firstChar field in it. This means that, since our string data actually starts
- // inside the fixed 'base_size' area, and our num_elements is equal to String.Length, we end up with one
- // extra character at the end. This is how we get our extra null terminator which allows us to pass a
- // pinned string out to native code as a null-terminated string. This is also why we don't increment the
- // requested string length by one before passing it to RhNewArray. There is no need to allocate an extra
- // array element, it is already allocated here in the fixed layout of the String.
- //
- // Typically, the base_size of an array type is aligned up to the nearest pointer size multiple (so that
- // array elements start out aligned in case they need alignment themselves), but we don't want to do that
- // with String because we are allocating String.Length components with RhNewArray and the overall object
- // size will then need another alignment, resulting in wasted space. So the binder specially shrinks the
- // base_size of String, leaving it unaligned in order to allow the use of that otherwise wasted space.
- //
- // One more note on base_size -- on 64-bit, the base_size ends up being 22 bytes, which is less than the
- // min_obj_size of (3 * sizeof(void*)). This is OK because our array allocator will still align up the
- // overall object size, so a 0-length string will end up with an object size of 24 bytes, which meets the
- // min_obj_size requirement.
- //
- // NOTE: This class is marked EagerStaticClassConstruction because McgCurrentModule class being eagerly
- // constructed itself depends on this class also being eagerly constructed. Plus, it's nice to have this
- // eagerly constructed to avoid the cost of defered ctors. I can't imagine any app that doesn't use string
- //
+ // the string methods perform some type of transformation on the current
+ // instance and return the result as a new string. As with arrays, character
+ // positions (indices) are zero-based.
+
[Serializable]
- public sealed partial class String : IComparable, IEnumerable, IEnumerable<char>, IComparable<String>, IEquatable<String>, IConvertible, ICloneable
+ [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
+ public sealed partial class String : IComparable, IEnumerable, IConvertible, IEnumerable<char>, IComparable<string>, IEquatable<string>, ICloneable
{
// String constructors
- // These are special. the implementation methods for these have a different signature from the
+ // These are special. The implementation methods for these have a different signature from the
// declared constructors.
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[PreserveDependency("System.String.CreateString(System.Char[])")]
public extern String(char[] value);
- [System.Runtime.CompilerServices.DependencyReductionRoot]
- private static String Ctor(char[] value)
+#if PROJECTN
+ [DependencyReductionRoot]
+#endif
+#if !CORECLR
+ static
+#endif
+ private string Ctor(char[] value)
{
- if (value != null && value.Length != 0)
- {
- String result = FastAllocateString(value.Length);
+ if (value == null || value.Length == 0)
+ return Empty;
- unsafe
- {
- fixed (char* dest = &result._firstChar, source = value)
- {
- wstrcpy(dest, source, value.Length);
- }
- }
- return result;
+ string result = FastAllocateString(value.Length);
+ unsafe
+ {
+ fixed (char* dest = &result._firstChar, source = value)
+ wstrcpy(dest, source, value.Length);
}
- else
- return String.Empty;
+ return result;
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[PreserveDependency("System.String.CreateString(System.Char[], System.Int32, System.Int32)")]
public extern String(char[] value, int startIndex, int length);
- [System.Runtime.CompilerServices.DependencyReductionRoot]
- private static String Ctor(char[] value, int startIndex, int length)
+#if PROJECTN
+ [DependencyReductionRoot]
+#endif
+#if !CORECLR
+ static
+#endif
+ private string Ctor(char[] value, int startIndex, int length)
{
if (value == null)
throw new ArgumentNullException(nameof(value));
@@ -124,96 +75,79 @@ namespace System
if (startIndex > value.Length - length)
throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index);
- if (length > 0)
- {
- String result = FastAllocateString(length);
+ if (length == 0)
+ return Empty;
- unsafe
- {
- fixed (char* dest = &result._firstChar, source = value)
- {
- wstrcpy(dest, source + startIndex, length);
- }
- }
- return result;
+ string result = FastAllocateString(length);
+ unsafe
+ {
+ fixed (char* dest = &result._firstChar, source = value)
+ wstrcpy(dest, source + startIndex, length);
}
- else
- return String.Empty;
+ return result;
}
[CLSCompliant(false)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[PreserveDependency("System.String.CreateString(System.Char*)")]
- unsafe public extern String(char* value);
+ public extern unsafe String(char* value);
- [System.Runtime.CompilerServices.DependencyReductionRoot]
- private static unsafe String Ctor(char* ptr)
+#if PROJECTN
+ [DependencyReductionRoot]
+#endif
+#if !CORECLR
+ static
+#endif
+ private unsafe string Ctor(char* ptr)
{
if (ptr == null)
- return String.Empty;
-
-#if !PLATFORM_UNIX
- if (ptr < (char*)64000)
- throw new ArgumentException(SR.Arg_MustBeStringPtrNotAtom);
-#endif // PLATFORM_UNIX
+ return Empty;
- try
- {
- int count = wcslen(ptr);
- if (count == 0)
- return String.Empty;
+ int count = wcslen(ptr);
+ if (count == 0)
+ return Empty;
- String result = FastAllocateString(count);
- fixed (char* dest = &result._firstChar)
- wstrcpy(dest, ptr, count);
- return result;
- }
- catch (NullReferenceException)
- {
- throw new ArgumentOutOfRangeException(nameof(ptr), SR.ArgumentOutOfRange_PartialWCHAR);
- }
+ string result = FastAllocateString(count);
+ fixed (char* dest = &result._firstChar)
+ wstrcpy(dest, ptr, count);
+ return result;
}
[CLSCompliant(false)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[PreserveDependency("System.String.CreateString(System.Char*, System.Int32, System.Int32)")]
- unsafe public extern String(char* value, int startIndex, int length);
+ public extern unsafe String(char* value, int startIndex, int length);
- [System.Runtime.CompilerServices.DependencyReductionRoot]
- private static unsafe String Ctor(char* ptr, int startIndex, int length)
+#if PROJECTN
+ [DependencyReductionRoot]
+#endif
+#if !CORECLR
+ static
+#endif
+ private unsafe string Ctor(char* ptr, int startIndex, int length)
{
if (length < 0)
- {
throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NegativeLength);
- }
if (startIndex < 0)
- {
throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_StartIndex);
- }
- char* pFrom = ptr + startIndex;
- if (pFrom < ptr)
- {
- // This means that the pointer operation has had an overflow
+ char* pStart = ptr + startIndex;
+
+ // overflow check
+ if (pStart < ptr)
throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_PartialWCHAR);
- }
if (length == 0)
- return String.Empty;
-
- String result = FastAllocateString(length);
+ return Empty;
- try
- {
- fixed (char* dest = &result._firstChar)
- wstrcpy(dest, pFrom, length);
- return result;
- }
- catch (NullReferenceException)
- {
+ if (ptr == null)
throw new ArgumentOutOfRangeException(nameof(ptr), SR.ArgumentOutOfRange_PartialWCHAR);
- }
+
+ string result = FastAllocateString(length);
+ fixed (char* dest = &result._firstChar)
+ wstrcpy(dest, pStart, length);
+ return result;
}
[CLSCompliant(false)]
@@ -221,16 +155,23 @@ namespace System
[PreserveDependency("System.String.CreateString(System.SByte*)")]
public extern unsafe String(sbyte* value);
+#if PROJECTN
[DependencyReductionRoot]
- private static unsafe string Ctor(sbyte* value)
+#endif
+#if !CORECLR
+ static
+#endif
+ private unsafe string Ctor(sbyte* value)
{
byte* pb = (byte*)value;
if (pb == null)
- return string.Empty; // Compatibility
+ return Empty;
+
+ int numBytes = new ReadOnlySpan<byte>((byte*)value, int.MaxValue).IndexOf<byte>(0);
- int numBytes = Buffer.IndexOfByte(pb, 0, 0, int.MaxValue);
- if (numBytes < 0) // This check covers the "-1 = not-found" case and "negative length" case (downstream code assumes length is non-negative).
- throw new ArgumentException(SR.Arg_ExpectedNulTermination); // We'll likely have AV'd before we get to this point, but just in case...
+ // Check for overflow
+ if (numBytes < 0)
+ throw new ArgumentException(SR.Arg_MustBeNullTerminatedString);
return CreateStringForSByteConstructor(pb, numBytes);
}
@@ -240,39 +181,47 @@ namespace System
[PreserveDependency("System.String.CreateString(System.SByte*, System.Int32, System.Int32)")]
public extern unsafe String(sbyte* value, int startIndex, int length);
+#if PROJECTN
[DependencyReductionRoot]
- private static unsafe string Ctor(sbyte* value, int startIndex, int length)
+#endif
+#if !CORECLR
+ static
+#endif
+ private unsafe string Ctor(sbyte* value, int startIndex, int length)
{
- byte* pb = (byte*)value;
-
if (startIndex < 0)
throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_StartIndex);
if (length < 0)
throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NegativeLength);
- if (pb == null)
+ if (value == null)
+ {
+ if (length == 0)
+ return Empty;
+
throw new ArgumentNullException(nameof(value));
+ }
+
+ byte* pStart = (byte*)(value + startIndex);
- byte* pStart = pb + startIndex;
- if (pStart < pb)
+ // overflow check
+ if (pStart < value)
throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_PartialWCHAR);
return CreateStringForSByteConstructor(pStart, length);
}
- // Encoder for String..ctor(sbyte*) and String..ctor(sbyte*, int, int). One of the last bastions of ANSI in the framework...
+ // Encoder for String..ctor(sbyte*) and String..ctor(sbyte*, int, int)
private static unsafe string CreateStringForSByteConstructor(byte *pb, int numBytes)
{
Debug.Assert(numBytes >= 0);
Debug.Assert(pb <= (pb + numBytes));
if (numBytes == 0)
- return string.Empty;
+ return Empty;
-#if PLATFORM_UNIX || MONO
- return Encoding.UTF8.GetString(pb, numBytes);
-#else
+#if PLATFORM_WINDOWS
int numCharsRequired = Interop.Kernel32.MultiByteToWideChar(Interop.Kernel32.CP_ACP, Interop.Kernel32.MB_PRECOMPOSED, pb, numBytes, (char*)null, 0);
if (numCharsRequired == 0)
throw new ArgumentException(SR.Arg_InvalidANSIString);
@@ -285,6 +234,8 @@ namespace System
if (numCharsRequired == 0)
throw new ArgumentException(SR.Arg_InvalidANSIString);
return newString;
+#else
+ return Encoding.UTF8.GetString(pb, numBytes);
#endif
}
@@ -293,14 +244,20 @@ namespace System
[PreserveDependency("System.String.CreateString(System.SByte*, System.Int32, System.Int32, System.Text.Encoding)")]
public extern unsafe String(sbyte* value, int startIndex, int length, Encoding enc);
+#if PROJECTN
[DependencyReductionRoot]
- private static unsafe string Ctor(sbyte* value, int startIndex, int length, Encoding enc)
+#endif
+#if !CORECLR
+ static
+#endif
+ private unsafe string Ctor(sbyte* value, int startIndex, int length, Encoding enc)
{
if (enc == null)
return new string(value, startIndex, length);
if (length < 0)
throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_NeedNonNegNum);
+
if (startIndex < 0)
throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_StartIndex);
@@ -315,40 +272,44 @@ namespace System
byte* pStart = (byte*)(value + startIndex);
if (pStart < value)
{
- // overflow check
- throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_PartialWCHAR);
- }
+ if (length == 0)
+ return Empty;
- byte[] copyOfValue = new byte[length];
- fixed (byte* pCopyOfValue = copyOfValue)
- {
- try
- {
- Buffer.Memcpy(dest: pCopyOfValue, src: pStart, len: length);
- }
- catch (Exception)
- {
- throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_PartialWCHAR);
- }
+ throw new ArgumentNullException(nameof(value));
}
- return enc.GetString(copyOfValue);
+ byte* pStart = (byte*)(value + startIndex);
+
+ // overflow check
+ if (pStart < value)
+ throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_PartialWCHAR);
+
+ return enc.GetString(new ReadOnlySpan<byte>(pStart, length));
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[PreserveDependency("System.String.CreateString(System.Char, System.Int32)")]
public extern String(char c, int count);
- [System.Runtime.CompilerServices.DependencyReductionRoot]
- private static String Ctor(char c, int count)
+#if PROJECTN
+ [DependencyReductionRoot]
+#endif
+#if !CORECLR
+ static
+#endif
+ private string Ctor(char c, int count)
{
- if (count > 0)
+ if (count <= 0)
{
- String result = FastAllocateString(count);
+ if (count == 0)
+ return Empty;
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NegativeCount);
+ }
- if (c == '\0')
- return result; // Fast path null char string
+ string result = FastAllocateString(count);
+ if (c != '\0') // Fast path null char string
+ {
unsafe
{
fixed (char* dest = &result._firstChar)
@@ -375,56 +336,49 @@ namespace System
((char*)dmem)[0] = c;
}
}
- return result;
}
- else if (count == 0)
- return String.Empty;
- else
- throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NegativeCount);
+ return result;
}
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[PreserveDependency("System.String.CreateString(System.ReadOnlySpan`1<System.Char>)")]
public extern String(ReadOnlySpan<char> value);
+#if PROJECTN
[DependencyReductionRoot]
- private unsafe static string Ctor(ReadOnlySpan<char> value)
+#endif
+#if !CORECLR
+ static
+#endif
+ private unsafe string Ctor(ReadOnlySpan<char> value)
{
if (value.Length == 0)
- {
return Empty;
- }
string result = FastAllocateString(value.Length);
fixed (char* dest = &result._firstChar, src = &MemoryMarshal.GetReference(value))
- {
wstrcpy(dest, src, value.Length);
- }
return result;
}
public static string Create<TState>(int length, TState state, SpanAction<char, TState> action)
{
if (action == null)
- {
throw new ArgumentNullException(nameof(action));
- }
-
- if (length > 0)
- {
- string result = FastAllocateString(length);
- action(new Span<char>(ref result.GetRawStringData(), length), state);
- return result;
- }
- if (length == 0)
+ if (length <= 0)
{
- return Empty;
+ if (length == 0)
+ return Empty;
+ throw new ArgumentOutOfRangeException(nameof(length));
}
- throw new ArgumentOutOfRangeException(nameof(length));
+ string result = FastAllocateString(length);
+ action(new Span<char>(ref result.GetRawStringData(), length), state);
+ return result;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator ReadOnlySpan<char>(string value) =>
value != null ? new ReadOnlySpan<char>(ref value.GetRawStringData(), value.Length) : default;
@@ -433,22 +387,14 @@ namespace System
return this;
}
- public static unsafe String Copy(String str)
+ public static unsafe string Copy(string str)
{
if (str == null)
- {
throw new ArgumentNullException(nameof(str));
- }
-
- int length = str.Length;
-
- String result = FastAllocateString(length);
- fixed (char* dest = &result._firstChar)
- fixed (char* src = &str._firstChar)
- {
- wstrcpy(dest, src, length);
- }
+ string result = FastAllocateString(str.Length);
+ fixed (char* dest = &result._firstChar, src = &str._firstChar)
+ wstrcpy(dest, src, str.Length);
return result;
}
@@ -457,7 +403,7 @@ namespace System
// sourceIndex + count - 1 to the character array buffer, beginning
// at destinationIndex.
//
- unsafe public void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count)
+ public unsafe void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count)
{
if (destination == null)
throw new ArgumentNullException(nameof(destination));
@@ -470,94 +416,72 @@ namespace System
if (destinationIndex > destination.Length - count || destinationIndex < 0)
throw new ArgumentOutOfRangeException(nameof(destinationIndex), SR.ArgumentOutOfRange_IndexCount);
- // Note: fixed does not like empty arrays
- if (count > 0)
- {
- fixed (char* src = &_firstChar)
- fixed (char* dest = destination)
- wstrcpy(dest + destinationIndex, src + sourceIndex, count);
- }
+ fixed (char* src = &_firstChar, dest = destination)
+ wstrcpy(dest + destinationIndex, src + sourceIndex, count);
}
// Returns the entire string as an array of characters.
- unsafe public char[] ToCharArray()
+ public unsafe char[] ToCharArray()
{
- // Huge performance improvement for short strings by doing this.
- int length = Length;
- if (length > 0)
- {
- char[] chars = new char[length];
- fixed (char* src = &_firstChar)
- fixed (char* dest = &chars[0])
- {
- wstrcpy(dest, src, length);
- }
- return chars;
- }
- return Array.Empty<char>();
+ if (Length == 0)
+ return Array.Empty<char>();
+
+ char[] chars = new char[Length];
+ fixed (char* src = &_firstChar, dest = &chars[0])
+ wstrcpy(dest, src, Length);
+ return chars;
}
// Returns a substring of this string as an array of characters.
//
- unsafe public char[] ToCharArray(int startIndex, int length)
+ public unsafe char[] ToCharArray(int startIndex, int length)
{
// Range check everything.
if (startIndex < 0 || startIndex > Length || startIndex > Length - length)
throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_Index);
- if (length < 0)
- throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_Index);
- if (length > 0)
+ if (length <= 0)
{
- char[] chars = new char[length];
- fixed (char* src = &_firstChar)
- fixed (char* dest = &chars[0])
- {
- wstrcpy(dest, src + startIndex, length);
- }
- return chars;
+ if (length == 0)
+ return Array.Empty<char>();
+ throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_Index);
}
- return Array.Empty<char>();
+
+ char[] chars = new char[length];
+ fixed (char* src = &_firstChar, dest = &chars[0])
+ wstrcpy(dest, src + startIndex, length);
+ return chars;
}
- public static bool IsNullOrEmpty(String value)
+ [NonVersionable]
+ public static bool IsNullOrEmpty(string value)
{
- return (value == null || value.Length == 0);
+ // Using 0u >= (uint)value.Length rather than
+ // value.Length == 0 as it will elide the bounds check to
+ // the first char: value[0] if that is performed following the test
+ // for the same test cost.
+ // Ternary operator returning true/false prevents redundant asm generation:
+ // https://github.com/dotnet/coreclr/issues/914
+ return (value == null || 0u >= (uint)value.Length) ? true : false;
}
- public static bool IsNullOrWhiteSpace(String value)
+ public static bool IsNullOrWhiteSpace(string value)
{
if (value == null) return true;
for (int i = 0; i < value.Length; i++)
{
- if (!Char.IsWhiteSpace(value[i])) return false;
+ if (!char.IsWhiteSpace(value[i])) return false;
}
return true;
}
- // Gets the length of this string
- //
- /// This is a EE implemented function so that the JIT can recognise is specially
- /// and eliminate checks on character fetchs in a loop like:
- /// for(int i = 0; i < str.Length; i++) str[i]
- /// The actually code generated for this will be one instruction and will be inlined.
- //
- // Spec#: Add postcondition in a contract assembly. Potential perf problem.
- public int Length
- {
- get { return _stringLength; }
- }
-
- internal ref char GetRawStringData()
- {
- return ref _firstChar;
- }
+ internal ref char GetRawStringData() => ref _firstChar;
// Helper for encodings so they can talk to our buffer directly
// stringLength must be the exact size we'll expect
- unsafe internal static String CreateStringFromEncoding(
+ internal static unsafe string CreateStringFromEncoding(
byte* bytes, int byteLength, Encoding encoding)
{
Debug.Assert(bytes != null);
@@ -570,9 +494,9 @@ namespace System
// They gave us an empty string if they needed one
// 0 bytelength might be possible if there's something in an encoder
if (stringLength == 0)
- return String.Empty;
+ return Empty;
- String s = FastAllocateString(stringLength);
+ string s = FastAllocateString(stringLength);
fixed (char* pTempChars = &s._firstChar)
{
int doubleCheck = encoding.GetChars(bytes, byteLength, pTempChars, stringLength, null);
@@ -600,13 +524,13 @@ namespace System
// Returns this string.
- public override String ToString()
+ public override string ToString()
{
return this;
}
// Returns this string.
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return this;
}
@@ -641,6 +565,9 @@ namespace System
}
#if !BIT64
+ // The following code is (somewhat surprisingly!) significantly faster than a naive loop,
+ // at least on x86 and the current jit.
+
// The loop condition below works because if "end[0] & end[1]" is non-zero, that means
// neither operand can have been zero. If is zero, we have to look at the operands individually,
// but we hope this going to fairly rare.
@@ -676,7 +603,7 @@ namespace System
// NOTE: We can access a ulong a time since the ptr is aligned,
// and therefore we're only accessing the same word/page. (See notes
// for the 32-bit version above.)
-
+
const ulong MagicMask = 0x7fff7fff7fff7fff;
while (true)
@@ -715,6 +642,14 @@ namespace System
int count = (int)(end - ptr);
+#if BIT64
+ // Check for overflow
+ if (ptr + count != end)
+ throw new ArgumentException(SR.Arg_MustBeNullTerminatedString);
+#else
+ Debug.Assert(ptr + count == end);
+#endif
+
return count;
}
@@ -787,7 +722,7 @@ namespace System
return Convert.ToDouble(this, provider);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(this, provider);
}
@@ -797,7 +732,7 @@ namespace System
return Convert.ToDateTime(this, provider);
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
@@ -811,16 +746,38 @@ namespace System
public bool IsNormalized(NormalizationForm normalizationForm)
{
+#if CORECLR
+ if (this.IsFastSort())
+ {
+ // If its FastSort && one of the 4 main forms, then its already normalized
+ if (normalizationForm == NormalizationForm.FormC ||
+ normalizationForm == NormalizationForm.FormKC ||
+ normalizationForm == NormalizationForm.FormD ||
+ normalizationForm == NormalizationForm.FormKD)
+ return true;
+ }
+#endif
return Normalization.IsNormalized(this, normalizationForm);
}
- public String Normalize()
+ public string Normalize()
{
return Normalize(NormalizationForm.FormC);
}
- public String Normalize(NormalizationForm normalizationForm)
+ public string Normalize(NormalizationForm normalizationForm)
{
+#if CORECLR
+ if (this.IsAscii())
+ {
+ // If its FastSort && one of the 4 main forms, then its already normalized
+ if (normalizationForm == NormalizationForm.FormC ||
+ normalizationForm == NormalizationForm.FormKC ||
+ normalizationForm == NormalizationForm.FormD ||
+ normalizationForm == NormalizationForm.FormKD)
+ return this;
+ }
+#endif
return Normalization.Normalize(this, normalizationForm);
}
}
diff --git a/src/System.Private.CoreLib/shared/System/StringComparer.cs b/src/System.Private.CoreLib/shared/System/StringComparer.cs
index de311e91d..47731cb78 100644
--- a/src/System.Private.CoreLib/shared/System/StringComparer.cs
+++ b/src/System.Private.CoreLib/shared/System/StringComparer.cs
@@ -114,10 +114,10 @@ namespace System
if (x == null) return -1;
if (y == null) return 1;
- String sa = x as String;
+ string sa = x as string;
if (sa != null)
{
- String sb = y as String;
+ string sb = y as string;
if (sb != null)
{
return Compare(sa, sb);
@@ -133,15 +133,15 @@ namespace System
throw new ArgumentException(SR.Argument_ImplementIComparable);
}
- public new bool Equals(Object x, Object y)
+ public new bool Equals(object x, object y)
{
if (x == y) return true;
if (x == null || y == null) return false;
- String sa = x as String;
+ string sa = x as string;
if (sa != null)
{
- String sb = y as String;
+ string sb = y as string;
if (sb != null)
{
return Equals(sa, sb);
@@ -165,8 +165,8 @@ namespace System
return obj.GetHashCode();
}
- public abstract int Compare(String x, String y);
- public abstract bool Equals(String x, String y);
+ public abstract int Compare(string x, string y);
+ public abstract bool Equals(string x, string y);
public abstract int GetHashCode(string obj);
}
@@ -293,7 +293,7 @@ namespace System
{
return false;
}
- return (string.Compare(x, y, StringComparison.OrdinalIgnoreCase) == 0);
+ return string.Equals(x, y, StringComparison.OrdinalIgnoreCase);
}
return x.Equals(y);
}
@@ -307,7 +307,7 @@ namespace System
if (_ignoreCase)
{
- return TextInfo.GetHashCodeOrdinalIgnoreCase(obj);
+ return CompareInfo.GetIgnoreCaseHash(obj);
}
return obj.GetHashCode();
@@ -375,7 +375,7 @@ namespace System
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.obj);
}
- return TextInfo.GetHashCodeOrdinalIgnoreCase(obj);
+ return CompareInfo.GetIgnoreCaseHash(obj);
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
diff --git a/src/System.Private.CoreLib/shared/System/StringSpanHelpers.cs b/src/System.Private.CoreLib/shared/System/StringSpanHelpers.cs
deleted file mode 100644
index 9ddcc9450..000000000
--- a/src/System.Private.CoreLib/shared/System/StringSpanHelpers.cs
+++ /dev/null
@@ -1,142 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Globalization;
-
-namespace System
-{
- /// <summary>Helpers for string-like operations on spans of chars.</summary>
- internal static class StringSpanHelpers
- {
- // TODO https://github.com/dotnet/corefx/issues/21395: Provide public, efficient implementations
-
- public static bool Equals(this ReadOnlySpan<char> left, ReadOnlySpan<char> right, StringComparison comparisonType) =>
- comparisonType == StringComparison.Ordinal ? Equals(left, right) :
- comparisonType == StringComparison.OrdinalIgnoreCase ? EqualsOrdinalIgnoreCase(left, right) :
- throw new ArgumentOutOfRangeException(nameof(comparisonType));
-
- public static bool Equals(this ReadOnlySpan<char> left, string right) =>
- Equals(left, right.AsSpan());
-
- public static bool Equals(this ReadOnlySpan<char> left, ReadOnlySpan<char> right)
- {
- if (left.Length != right.Length)
- {
- return false;
- }
-
- for (int i = 0; i < left.Length; i++)
- {
- if (left[i] != right[i])
- {
- return false;
- }
- }
-
- return true;
- }
-
-#if MONO
- internal
-#endif
- static bool EqualsOrdinalIgnoreCase(this ReadOnlySpan<char> left, ReadOnlySpan<char> right)
- {
- if (left.Length != right.Length)
- {
- return false;
- }
-
- for (int i = 0; i < left.Length; i++)
- {
- char x = left[i], y = right[i];
- if (x != y &&
- TextInfo.ToUpperAsciiInvariant(x) != TextInfo.ToUpperAsciiInvariant(y))
- {
- return false;
- }
- }
-
- return true;
- }
-
- public static int IndexOf(this ReadOnlySpan<char> source, char value) =>
- IndexOf(source, value, 0);
-
- public static int IndexOf(this ReadOnlySpan<char> source, char value, int startIndex)
- {
- for (int i = startIndex; i < source.Length; i++)
- {
- if (source[i] == value)
- {
- return i;
- }
- }
-
- return -1;
- }
-
- public static bool Contains(this ReadOnlySpan<char> source, char value)
- {
- for (int i = 0; i < source.Length; i++)
- {
- if (source[i] == value)
- {
- return true;
- }
- }
-
- return false;
- }
-
- public static ReadOnlySpan<char> Remove(this ReadOnlySpan<char> source, int startIndex, int count)
- {
- if (startIndex < 0)
- throw new ArgumentOutOfRangeException(nameof(startIndex), SR.ArgumentOutOfRange_StartIndex);
- if (count < 0)
- throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NegativeCount);
- if (count > source.Length - startIndex)
- throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_IndexCount);
-
- if (count == 0)
- {
- return source;
- }
-
- int newLength = source.Length - count;
- if (newLength == 0)
- {
- return ReadOnlySpan<char>.Empty;
- }
-
- Span<char> result = new char[newLength];
- source.Slice(0, startIndex).CopyTo(result);
- source.Slice(startIndex + count).CopyTo(result.Slice(startIndex));
- return result;
- }
-
- // Returns the index of the last occurrence of a specified character in the current instance.
- public static int LastIndexOf(this ReadOnlySpan<char> source, char value)
- {
- if (source.Length == 0)
- return -1;
-
- for (int i = source.Length - 1; i >= 0; i--)
- {
- if (source[i] == value)
- return i;
- }
-
- return -1;
- }
-
- public static void CheckStringComparison(StringComparison comparisonType)
- {
- // Single comparison to check if comparisonType is within [CurrentCulture .. OrdinalIgnoreCase]
- if ((uint)(comparisonType - StringComparison.CurrentCulture) > (StringComparison.OrdinalIgnoreCase - StringComparison.CurrentCulture))
- {
- throw new ArgumentException(SR.NotSupported_StringComparison, nameof(comparisonType));
- }
- }
- }
-}
diff --git a/src/System.Private.CoreLib/shared/System/SystemException.cs b/src/System.Private.CoreLib/shared/System/SystemException.cs
index b7e8e4217..9a1daf210 100644
--- a/src/System.Private.CoreLib/shared/System/SystemException.cs
+++ b/src/System.Private.CoreLib/shared/System/SystemException.cs
@@ -16,13 +16,13 @@ namespace System
HResult = HResults.COR_E_SYSTEM;
}
- public SystemException(String message)
+ public SystemException(string message)
: base(message)
{
HResult = HResults.COR_E_SYSTEM;
}
- public SystemException(String message, Exception innerException)
+ public SystemException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_SYSTEM;
diff --git a/src/System.Private.CoreLib/shared/System/Text/ASCIIEncoding.cs b/src/System.Private.CoreLib/shared/System/Text/ASCIIEncoding.cs
index e89943a19..217d93467 100644
--- a/src/System.Private.CoreLib/shared/System/Text/ASCIIEncoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/ASCIIEncoding.cs
@@ -31,7 +31,7 @@ namespace System.Text
{
}
- internal override void SetDefaultFallbacks()
+ internal sealed override void SetDefaultFallbacks()
{
// For ASCIIEncoding we just use default replacement fallback
this.encoderFallback = EncoderFallback.ReplacementFallback;
@@ -59,13 +59,13 @@ namespace System.Text
{
// Validate input parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - index < count)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input, return 0, avoid fixed empty array problem
if (count == 0)
@@ -81,11 +81,11 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe int GetByteCount(String chars)
+ public override unsafe int GetByteCount(string chars)
{
// Validate input
if (chars==null)
- throw new ArgumentNullException("chars");
+ throw new ArgumentNullException(nameof(chars));
fixed (char* pChars = chars)
return GetByteCount(pChars, chars.Length, null);
@@ -100,34 +100,42 @@ namespace System.Text
{
// Validate Parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
// Call it with empty encoder
return GetByteCount(chars, count, null);
}
+ public override unsafe int GetByteCount(ReadOnlySpan<char> chars)
+ {
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ {
+ return GetByteCount(charsPtr, chars.Length, encoder: null);
+ }
+ }
+
// Parent method is safe.
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
- public override unsafe int GetBytes(String chars, int charIndex, int charCount,
+ public override unsafe int GetBytes(string chars, int charIndex, int charCount,
byte[] bytes, int byteIndex)
{
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCount);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCount);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
int byteCount = bytes.Length - byteIndex;
@@ -154,16 +162,16 @@ namespace System.Text
{
// Validate parameters
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
// If nothing to encode return 0
if (charCount == 0)
@@ -186,14 +194,23 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetBytes(chars, charCount, bytes, byteCount, null);
}
+ public override unsafe int GetBytes(ReadOnlySpan<char> chars, Span<byte> bytes)
+ {
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ {
+ return GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length, encoder: null);
+ }
+ }
+
// Returns the number of characters produced by decoding a range of bytes
// in a byte array.
//
@@ -206,13 +223,13 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input just return 0, fixed doesn't like 0 length arrays
if (count == 0)
@@ -232,14 +249,22 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetCharCount(bytes, count, null);
}
+ public override unsafe int GetCharCount(ReadOnlySpan<byte> bytes)
+ {
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ {
+ return GetCharCount(bytesPtr, bytes.Length, decoder: null);
+ }
+ }
+
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
@@ -250,16 +275,16 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if ( bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (charIndex < 0 || charIndex > chars.Length)
- throw new ArgumentOutOfRangeException("charIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index);
// If no input, return 0 & avoid fixed problem
if (byteCount == 0)
@@ -282,14 +307,23 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetChars(bytes, byteCount, chars, charCount, null);
}
+ public override unsafe int GetChars(ReadOnlySpan<byte> bytes, Span<char> chars)
+ {
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ {
+ return GetChars(bytesPtr, bytes.Length, charsPtr, chars.Length, decoder: null);
+ }
+ }
+
// Returns a string containing the decoded representation of a range of
// bytes in a byte array.
//
@@ -298,24 +332,24 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe String GetString(byte[] bytes, int byteIndex, int byteCount)
+ public override unsafe string GetString(byte[] bytes, int byteIndex, int byteCount)
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// Avoid problems with empty input buffer
- if (byteCount == 0) return String.Empty;
+ if (byteCount == 0) return string.Empty;
fixed (byte* pBytes = bytes)
- return String.CreateStringFromEncoding(
+ return string.CreateStringFromEncoding(
pBytes + byteIndex, byteCount, this);
}
@@ -326,7 +360,7 @@ namespace System.Text
// GetByteCount
// Note: We start by assuming that the output will be the same as count. Having
// an encoder or fallback may change that assumption
- internal override unsafe int GetByteCount(char* chars, int charCount, EncoderNLS encoder)
+ internal sealed override unsafe int GetByteCount(char* chars, int charCount, EncoderNLS encoder)
{
// Just need to ASSERT, this is called by something else internal that checked parameters already
Debug.Assert(charCount >= 0, "[ASCIIEncoding.GetByteCount]count is negative");
@@ -348,7 +382,7 @@ namespace System.Text
if (encoder != null)
{
charLeftOver = encoder._charLeftOver;
- Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
+ Debug.Assert(charLeftOver == 0 || char.IsHighSurrogate(charLeftOver),
"[ASCIIEncoding.GetByteCount]leftover character should be high surrogate");
fallback = encoder.Fallback as EncoderReplacementFallback;
@@ -400,7 +434,7 @@ namespace System.Text
// We may have a left over character from last time, try and process it.
if (charLeftOver > 0)
{
- Debug.Assert(Char.IsHighSurrogate(charLeftOver), "[ASCIIEncoding.GetByteCount]leftover character should be high surrogate");
+ Debug.Assert(char.IsHighSurrogate(charLeftOver), "[ASCIIEncoding.GetByteCount]leftover character should be high surrogate");
Debug.Assert(encoder != null, "[ASCIIEncoding.GetByteCount]Expected encoder");
// Since left over char was a surrogate, it'll have to be fallen back.
@@ -460,8 +494,8 @@ namespace System.Text
return byteCount;
}
- internal override unsafe int GetBytes(char* chars, int charCount,
- byte* bytes, int byteCount, EncoderNLS encoder)
+ internal sealed override unsafe int GetBytes(
+ char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS encoder)
{
// Just need to ASSERT, this is called by something else internal that checked parameters already
Debug.Assert(bytes != null, "[ASCIIEncoding.GetBytes]bytes is null");
@@ -502,7 +536,7 @@ namespace System.Text
fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, true);
}
- Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
+ Debug.Assert(charLeftOver == 0 || char.IsHighSurrogate(charLeftOver),
"[ASCIIEncoding.GetBytes]leftover character should be high surrogate");
// Verify that we have no fallbackbuffer, for ASCII its always empty, so just assert
@@ -676,7 +710,7 @@ namespace System.Text
}
// This is internal and called by something else,
- internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS decoder)
+ internal sealed override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS decoder)
{
// Just assert, we're called internally so these should be safe, checked already
Debug.Assert(bytes != null, "[ASCIIEncoding.GetCharCount]bytes is null");
@@ -748,8 +782,8 @@ namespace System.Text
return charCount;
}
- internal override unsafe int GetChars(byte* bytes, int byteCount,
- char* chars, int charCount, DecoderNLS decoder)
+ internal sealed override unsafe int GetChars(
+ byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS decoder)
{
// Just need to ASSERT, this is called by something else internal that checked parameters already
Debug.Assert(bytes != null, "[ASCIIEncoding.GetChars]bytes is null");
diff --git a/src/System.Private.CoreLib/shared/System/Text/Decoder.cs b/src/System.Private.CoreLib/shared/System/Text/Decoder.cs
index b827648fc..b4a7575ba 100644
--- a/src/System.Private.CoreLib/shared/System/Text/Decoder.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/Decoder.cs
@@ -134,7 +134,7 @@ namespace System.Text
public virtual unsafe int GetCharCount(ReadOnlySpan<byte> bytes, bool flush)
{
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
{
return GetCharCount(bytesPtr, bytes.Length, flush);
}
@@ -227,8 +227,8 @@ namespace System.Text
public virtual unsafe int GetChars(ReadOnlySpan<byte> bytes, Span<char> chars, bool flush)
{
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
{
return GetChars(bytesPtr, bytes.Length, charsPtr, chars.Length, flush);
}
@@ -341,8 +341,8 @@ namespace System.Text
public virtual unsafe void Convert(ReadOnlySpan<byte> bytes, Span<char> chars, bool flush, out int bytesUsed, out int charsUsed, out bool completed)
{
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
{
Convert(bytesPtr, bytes.Length, charsPtr, chars.Length, flush, out bytesUsed, out charsUsed, out completed);
}
diff --git a/src/System.Private.CoreLib/shared/System/Text/DecoderBestFitFallback.cs b/src/System.Private.CoreLib/shared/System/Text/DecoderBestFitFallback.cs
index 30c817c91..8c62730c2 100644
--- a/src/System.Private.CoreLib/shared/System/Text/DecoderBestFitFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/DecoderBestFitFallback.cs
@@ -38,7 +38,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
InternalDecoderBestFitFallback that = value as InternalDecoderBestFitFallback;
if (that != null)
@@ -63,15 +63,15 @@ namespace System.Text
private InternalDecoderBestFitFallback _oFallback;
// Private object for locking instead of locking on a public type for SQL reliability work.
- private static Object s_InternalSyncObject;
- private static Object InternalSyncObject
+ private static object s_InternalSyncObject;
+ private static object InternalSyncObject
{
get
{
if (s_InternalSyncObject == null)
{
- Object o = new Object();
- Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
+ object o = new object();
+ Interlocked.CompareExchange<object>(ref s_InternalSyncObject, o, null);
}
return s_InternalSyncObject;
}
diff --git a/src/System.Private.CoreLib/shared/System/Text/DecoderExceptionFallback.cs b/src/System.Private.CoreLib/shared/System/Text/DecoderExceptionFallback.cs
index 8bfc1f32d..56c004714 100644
--- a/src/System.Private.CoreLib/shared/System/Text/DecoderExceptionFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/DecoderExceptionFallback.cs
@@ -29,7 +29,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
DecoderExceptionFallback that = value as DecoderExceptionFallback;
if (that != null)
@@ -112,19 +112,19 @@ namespace System.Text
HResult = HResults.COR_E_ARGUMENT;
}
- public DecoderFallbackException(String message)
+ public DecoderFallbackException(string message)
: base(message)
{
HResult = HResults.COR_E_ARGUMENT;
}
- public DecoderFallbackException(String message, Exception innerException)
+ public DecoderFallbackException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_ARGUMENT;
}
- public DecoderFallbackException(String message, byte[] bytesUnknown, int index)
+ public DecoderFallbackException(string message, byte[] bytesUnknown, int index)
: base(message)
{
_bytesUnknown = bytesUnknown;
diff --git a/src/System.Private.CoreLib/shared/System/Text/DecoderFallback.cs b/src/System.Private.CoreLib/shared/System/Text/DecoderFallback.cs
index 11b9539b5..fff8ad1d7 100644
--- a/src/System.Private.CoreLib/shared/System/Text/DecoderFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/DecoderFallback.cs
@@ -104,9 +104,9 @@ namespace System.Text
while ((ch = GetNextChar()) != 0)
{
// Make sure no mixed up surrogates
- if (Char.IsSurrogate(ch))
+ if (char.IsSurrogate(ch))
{
- if (Char.IsHighSurrogate(ch))
+ if (char.IsHighSurrogate(ch))
{
// High Surrogate
if (bHighSurrogate)
@@ -159,9 +159,9 @@ namespace System.Text
while ((ch = GetNextChar()) != 0)
{
// Make sure no mixed up surrogates
- if (Char.IsSurrogate(ch))
+ if (char.IsSurrogate(ch))
{
- if (Char.IsHighSurrogate(ch))
+ if (char.IsHighSurrogate(ch))
{
// High Surrogate
if (bHighSurrogate)
diff --git a/src/System.Private.CoreLib/shared/System/Text/DecoderReplacementFallback.cs b/src/System.Private.CoreLib/shared/System/Text/DecoderReplacementFallback.cs
index 422b80bb2..a97baf05c 100644
--- a/src/System.Private.CoreLib/shared/System/Text/DecoderReplacementFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/DecoderReplacementFallback.cs
@@ -9,14 +9,14 @@ namespace System.Text
public sealed class DecoderReplacementFallback : DecoderFallback
{
// Our variables
- private String _strDefault;
+ private string _strDefault;
// Construction. Default replacement fallback uses no best fit and ? replacement string
public DecoderReplacementFallback() : this("?")
{
}
- public DecoderReplacementFallback(String replacement)
+ public DecoderReplacementFallback(string replacement)
{
if (replacement == null)
throw new ArgumentNullException(nameof(replacement));
@@ -26,10 +26,10 @@ namespace System.Text
for (int i = 0; i < replacement.Length; i++)
{
// Found a surrogate?
- if (Char.IsSurrogate(replacement, i))
+ if (char.IsSurrogate(replacement, i))
{
// High or Low?
- if (Char.IsHighSurrogate(replacement, i))
+ if (char.IsHighSurrogate(replacement, i))
{
// if already had a high one, stop
if (bFoundHigh)
@@ -60,7 +60,7 @@ namespace System.Text
_strDefault = replacement;
}
- public String DefaultString
+ public string DefaultString
{
get
{
@@ -82,7 +82,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
DecoderReplacementFallback that = value as DecoderReplacementFallback;
if (that != null)
@@ -103,7 +103,7 @@ namespace System.Text
public sealed class DecoderReplacementFallbackBuffer : DecoderFallbackBuffer
{
// Store our default string
- private String _strDefault;
+ private string _strDefault;
private int _fallbackCount = -1;
private int _fallbackIndex = -1;
diff --git a/src/System.Private.CoreLib/shared/System/Text/Encoder.cs b/src/System.Private.CoreLib/shared/System/Text/Encoder.cs
index fb1bdb803..df7d51203 100644
--- a/src/System.Private.CoreLib/shared/System/Text/Encoder.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/Encoder.cs
@@ -132,7 +132,7 @@ namespace System.Text
public virtual unsafe int GetByteCount(ReadOnlySpan<char> chars, bool flush)
{
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
{
return GetByteCount(charsPtr, chars.Length, flush);
}
@@ -221,8 +221,8 @@ namespace System.Text
public virtual unsafe int GetBytes(ReadOnlySpan<char> chars, Span<byte> bytes, bool flush)
{
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
{
return GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length, flush);
}
@@ -335,8 +335,8 @@ namespace System.Text
public virtual unsafe void Convert(ReadOnlySpan<char> chars, Span<byte> bytes, bool flush, out int charsUsed, out int bytesUsed, out bool completed)
{
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
{
Convert(charsPtr, chars.Length, bytesPtr, bytes.Length, flush, out charsUsed, out bytesUsed, out completed);
}
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncoderBestFitFallback.cs b/src/System.Private.CoreLib/shared/System/Text/EncoderBestFitFallback.cs
index 7f3be2a7a..4aab3f62a 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncoderBestFitFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncoderBestFitFallback.cs
@@ -38,7 +38,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
InternalEncoderBestFitFallback that = value as InternalEncoderBestFitFallback;
if (that != null)
@@ -63,15 +63,15 @@ namespace System.Text
private int _iSize;
// Private object for locking instead of locking on a public type for SQL reliability work.
- private static Object s_InternalSyncObject;
- private static Object InternalSyncObject
+ private static object s_InternalSyncObject;
+ private static object InternalSyncObject
{
get
{
if (s_InternalSyncObject == null)
{
- Object o = new Object();
- Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
+ object o = new object();
+ Interlocked.CompareExchange<object>(ref s_InternalSyncObject, o, null);
}
return s_InternalSyncObject;
}
@@ -113,12 +113,12 @@ namespace System.Text
public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index)
{
// Double check input surrogate pair
- if (!Char.IsHighSurrogate(charUnknownHigh))
+ if (!char.IsHighSurrogate(charUnknownHigh))
throw new ArgumentOutOfRangeException(nameof(charUnknownHigh),
SR.Format(SR.ArgumentOutOfRange_Range,
0xD800, 0xDBFF));
- if (!Char.IsLowSurrogate(charUnknownLow))
+ if (!char.IsLowSurrogate(charUnknownLow))
throw new ArgumentOutOfRangeException(nameof(charUnknownLow),
SR.Format(SR.ArgumentOutOfRange_Range,
0xDC00, 0xDFFF));
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncoderExceptionFallback.cs b/src/System.Private.CoreLib/shared/System/Text/EncoderExceptionFallback.cs
index 66de1940f..92afcf701 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncoderExceptionFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncoderExceptionFallback.cs
@@ -28,7 +28,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
EncoderExceptionFallback that = value as EncoderExceptionFallback;
if (that != null)
@@ -57,18 +57,18 @@ namespace System.Text
public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index)
{
- if (!Char.IsHighSurrogate(charUnknownHigh))
+ if (!char.IsHighSurrogate(charUnknownHigh))
{
throw new ArgumentOutOfRangeException(nameof(charUnknownHigh),
SR.Format(SR.ArgumentOutOfRange_Range, 0xD800, 0xDBFF));
}
- if (!Char.IsLowSurrogate(charUnknownLow))
+ if (!char.IsLowSurrogate(charUnknownLow))
{
throw new ArgumentOutOfRangeException(nameof(charUnknownLow),
SR.Format(SR.ArgumentOutOfRange_Range, 0xDC00, 0xDFFF));
}
- int iTemp = Char.ConvertToUtf32(charUnknownHigh, charUnknownLow);
+ int iTemp = char.ConvertToUtf32(charUnknownHigh, charUnknownLow);
// Fall back our char
throw new EncoderFallbackException(
@@ -111,34 +111,34 @@ namespace System.Text
HResult = HResults.COR_E_ARGUMENT;
}
- public EncoderFallbackException(String message)
+ public EncoderFallbackException(string message)
: base(message)
{
HResult = HResults.COR_E_ARGUMENT;
}
- public EncoderFallbackException(String message, Exception innerException)
+ public EncoderFallbackException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_ARGUMENT;
}
internal EncoderFallbackException(
- String message, char charUnknown, int index) : base(message)
+ string message, char charUnknown, int index) : base(message)
{
_charUnknown = charUnknown;
_index = index;
}
internal EncoderFallbackException(
- String message, char charUnknownHigh, char charUnknownLow, int index) : base(message)
+ string message, char charUnknownHigh, char charUnknownLow, int index) : base(message)
{
- if (!Char.IsHighSurrogate(charUnknownHigh))
+ if (!char.IsHighSurrogate(charUnknownHigh))
{
throw new ArgumentOutOfRangeException(nameof(charUnknownHigh),
SR.Format(SR.ArgumentOutOfRange_Range, 0xD800, 0xDBFF));
}
- if (!Char.IsLowSurrogate(charUnknownLow))
+ if (!char.IsLowSurrogate(charUnknownLow))
{
throw new ArgumentOutOfRangeException(nameof(CharUnknownLow),
SR.Format(SR.ArgumentOutOfRange_Range, 0xDC00, 0xDFFF));
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncoderFallback.cs b/src/System.Private.CoreLib/shared/System/Text/EncoderFallback.cs
index d860a02a7..f98b15e07 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncoderFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncoderFallback.cs
@@ -142,7 +142,7 @@ namespace System.Text
int index = (int)(chars - charStart) - 1;
// See if it was a high surrogate
- if (Char.IsHighSurrogate(ch))
+ if (char.IsHighSurrogate(ch))
{
// See if there's a low surrogate to go with it
if (chars >= this.charEnd)
@@ -165,11 +165,11 @@ namespace System.Text
{
// Might have a low surrogate
char cNext = *chars;
- if (Char.IsLowSurrogate(cNext))
+ if (char.IsLowSurrogate(cNext))
{
// If already falling back then fail
if (bFallingBack && iRecursionCount++ > iMaxRecursion)
- ThrowLastCharRecursive(Char.ConvertToUtf32(ch, cNext));
+ ThrowLastCharRecursive(char.ConvertToUtf32(ch, cNext));
// Next is a surrogate, add it as surrogate pair, and increment chars
chars++;
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncoderReplacementFallback.cs b/src/System.Private.CoreLib/shared/System/Text/EncoderReplacementFallback.cs
index a1d0bbcd9..760c280fd 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncoderReplacementFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncoderReplacementFallback.cs
@@ -11,14 +11,14 @@ namespace System.Text
public sealed class EncoderReplacementFallback : EncoderFallback
{
// Our variables
- private String _strDefault;
+ private string _strDefault;
// Construction. Default replacement fallback uses no best fit and ? replacement string
public EncoderReplacementFallback() : this("?")
{
}
- public EncoderReplacementFallback(String replacement)
+ public EncoderReplacementFallback(string replacement)
{
// Must not be null
if (replacement == null)
@@ -29,10 +29,10 @@ namespace System.Text
for (int i = 0; i < replacement.Length; i++)
{
// Found a surrogate?
- if (Char.IsSurrogate(replacement, i))
+ if (char.IsSurrogate(replacement, i))
{
// High or Low?
- if (Char.IsHighSurrogate(replacement, i))
+ if (char.IsHighSurrogate(replacement, i))
{
// if already had a high one, stop
if (bFoundHigh)
@@ -63,7 +63,7 @@ namespace System.Text
_strDefault = replacement;
}
- public String DefaultString
+ public string DefaultString
{
get
{
@@ -85,7 +85,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
EncoderReplacementFallback that = value as EncoderReplacementFallback;
if (that != null)
@@ -106,7 +106,7 @@ namespace System.Text
public sealed class EncoderReplacementFallbackBuffer : EncoderFallbackBuffer
{
// Store our default string
- private String _strDefault;
+ private string _strDefault;
private int _fallbackCount = -1;
private int _fallbackIndex = -1;
@@ -127,7 +127,7 @@ namespace System.Text
// If we're recursive we may still have something in our buffer that makes this a surrogate
if (char.IsHighSurrogate(charUnknown) && _fallbackCount >= 0 &&
char.IsLowSurrogate(_strDefault[_fallbackIndex + 1]))
- ThrowLastCharRecursive(Char.ConvertToUtf32(charUnknown, _strDefault[_fallbackIndex + 1]));
+ ThrowLastCharRecursive(char.ConvertToUtf32(charUnknown, _strDefault[_fallbackIndex + 1]));
// Nope, just one character
ThrowLastCharRecursive(unchecked((int)charUnknown));
@@ -144,18 +144,18 @@ namespace System.Text
public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index)
{
// Double check input surrogate pair
- if (!Char.IsHighSurrogate(charUnknownHigh))
+ if (!char.IsHighSurrogate(charUnknownHigh))
throw new ArgumentOutOfRangeException(nameof(charUnknownHigh),
SR.Format(SR.ArgumentOutOfRange_Range, 0xD800, 0xDBFF));
- if (!Char.IsLowSurrogate(charUnknownLow))
+ if (!char.IsLowSurrogate(charUnknownLow))
throw new ArgumentOutOfRangeException(nameof(charUnknownLow),
SR.Format(SR.ArgumentOutOfRange_Range, 0xDC00, 0xDFFF));
// If we had a buffer already we're being recursive, throw, it's probably at the suspect
// character in our array.
if (_fallbackCount >= 1)
- ThrowLastCharRecursive(Char.ConvertToUtf32(charUnknownHigh, charUnknownLow));
+ ThrowLastCharRecursive(char.ConvertToUtf32(charUnknownHigh, charUnknownLow));
// Go ahead and get our fallback
_fallbackCount = _strDefault.Length;
diff --git a/src/System.Private.CoreLib/shared/System/Text/Encoding.cs b/src/System.Private.CoreLib/shared/System/Text/Encoding.cs
index e469180ce..005f08afd 100644
--- a/src/System.Private.CoreLib/shared/System/Text/Encoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/Encoding.cs
@@ -325,7 +325,7 @@ namespace System.Text
// Returns an Encoding object for a given name or a given code page value.
//
- public static Encoding GetEncoding(String name)
+ public static Encoding GetEncoding(string name)
{
Encoding baseEncoding = EncodingProvider.GetEncodingFromProvider(name);
if (baseEncoding != null)
@@ -342,7 +342,7 @@ namespace System.Text
// Returns an Encoding object for a given name or a given code page value.
//
- public static Encoding GetEncoding(String name,
+ public static Encoding GetEncoding(string name,
EncoderFallback encoderFallback, DecoderFallback decoderFallback)
{
Encoding baseEncoding = EncodingProvider.GetEncodingFromProvider(name, encoderFallback, decoderFallback);
@@ -386,7 +386,7 @@ namespace System.Text
// Returns the name for this encoding that can be used with mail agent body tags.
// If the encoding may not be used, the string is empty.
- public virtual String BodyName
+ public virtual string BodyName
{
get
{
@@ -443,7 +443,7 @@ namespace System.Text
}
}
#else
- public virtual String EncodingName
+ public virtual string EncodingName
{
get
{
@@ -454,7 +454,7 @@ namespace System.Text
// Returns the name for this encoding that can be used with mail agent header
// tags. If the encoding may not be used, the string is empty.
- public virtual String HeaderName
+ public virtual string HeaderName
{
get
{
@@ -467,7 +467,7 @@ namespace System.Text
}
// Returns the IANA preferred name for this encoding.
- public virtual String WebName
+ public virtual string WebName
{
get
{
@@ -603,7 +603,7 @@ namespace System.Text
}
- public virtual Object Clone()
+ public virtual object Clone()
{
Encoding newEncoding = (Encoding)this.MemberwiseClone();
@@ -646,7 +646,7 @@ namespace System.Text
return GetByteCount(chars, 0, chars.Length);
}
- public virtual int GetByteCount(String s)
+ public virtual int GetByteCount(string s)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -713,7 +713,7 @@ namespace System.Text
public virtual unsafe int GetByteCount(ReadOnlySpan<char> chars)
{
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
{
return GetByteCount(charsPtr, chars.Length);
}
@@ -767,7 +767,7 @@ namespace System.Text
// Returns a byte array containing the encoded representation of the given
// string.
//
- public virtual byte[] GetBytes(String s)
+ public virtual byte[] GetBytes(string s)
{
if (s == null)
throw new ArgumentNullException(nameof(s),
@@ -817,7 +817,7 @@ namespace System.Text
}
}
- public virtual int GetBytes(String s, int charIndex, int charCount,
+ public virtual int GetBytes(string s, int charIndex, int charCount,
byte[] bytes, int byteIndex)
{
if (s == null)
@@ -895,8 +895,8 @@ namespace System.Text
public virtual unsafe int GetBytes(ReadOnlySpan<char> chars, Span<byte> bytes)
{
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
{
return GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length);
}
@@ -945,7 +945,7 @@ namespace System.Text
public virtual unsafe int GetCharCount(ReadOnlySpan<byte> bytes)
{
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
{
return GetCharCount(bytesPtr, bytes.Length);
}
@@ -1057,8 +1057,8 @@ namespace System.Text
public virtual unsafe int GetChars(ReadOnlySpan<byte> bytes, Span<char> chars)
{
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
{
return GetChars(bytesPtr, bytes.Length, charsPtr, chars.Length);
}
@@ -1082,14 +1082,14 @@ namespace System.Text
if (byteCount < 0)
throw new ArgumentOutOfRangeException(nameof(byteCount), SR.ArgumentOutOfRange_NeedNonNegNum);
- return String.CreateStringFromEncoding(bytes, byteCount, this);
+ return string.CreateStringFromEncoding(bytes, byteCount, this);
}
public unsafe string GetString(ReadOnlySpan<byte> bytes)
{
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
{
- return GetString(bytesPtr, bytes.Length);
+ return string.CreateStringFromEncoding(bytesPtr, bytes.Length, this);
}
}
@@ -1184,7 +1184,7 @@ namespace System.Text
// Returns a string containing the decoded representation of a given byte
// array.
//
- public virtual String GetString(byte[] bytes)
+ public virtual string GetString(byte[] bytes)
{
if (bytes == null)
throw new ArgumentNullException(nameof(bytes),
@@ -1198,9 +1198,9 @@ namespace System.Text
//
// Internally we override this for performance
//
- public virtual String GetString(byte[] bytes, int index, int count)
+ public virtual string GetString(byte[] bytes, int index, int count)
{
- return new String(GetChars(bytes, index, count));
+ return new string(GetChars(bytes, index, count));
}
// Returns an encoding for Unicode format. The returned encoding will be
@@ -1241,7 +1241,7 @@ namespace System.Text
private static Encoding BigEndianUTF32 => UTF32Encoding.s_bigEndianDefault;
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
Encoding that = value as Encoding;
if (that != null)
@@ -1325,7 +1325,7 @@ namespace System.Text
_encoding = encoding;
}
- public Object GetRealObject(StreamingContext context)
+ public object GetRealObject(StreamingContext context)
{
throw new PlatformNotSupportedException();
}
@@ -1390,7 +1390,7 @@ namespace System.Text
_encoding = encoding;
}
- public Object GetRealObject(StreamingContext context)
+ public object GetRealObject(StreamingContext context)
{
throw new PlatformNotSupportedException();
}
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncodingInfo.cs b/src/System.Private.CoreLib/shared/System/Text/EncodingInfo.cs
index 99995f759..8e71e58fa 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncodingInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncodingInfo.cs
@@ -53,7 +53,7 @@ namespace System.Text
return Encoding.GetEncoding(iCodePage);
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
EncodingInfo that = value as EncodingInfo;
if (that != null)
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncodingNLS.cs b/src/System.Private.CoreLib/shared/System/Text/EncodingNLS.cs
index d5de9e553..e6fa0627d 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncodingNLS.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncodingNLS.cs
@@ -40,13 +40,13 @@ namespace System.Text
{
// Validate input parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - index < count)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input, return 0, avoid fixed empty array problem
if (count == 0)
@@ -61,11 +61,11 @@ namespace System.Text
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe int GetByteCount(String s)
+ public override unsafe int GetByteCount(string s)
{
// Validate input
if (s==null)
- throw new ArgumentNullException("s");
+ throw new ArgumentNullException(nameof(s));
fixed (char* pChars = s)
return GetByteCount(pChars, s.Length, null);
@@ -78,10 +78,10 @@ namespace System.Text
{
// Validate Parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
// Call it with empty encoder
return GetByteCount(chars, count, null);
@@ -91,20 +91,20 @@ namespace System.Text
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
- public override unsafe int GetBytes(String s, int charIndex, int charCount,
+ public override unsafe int GetBytes(string s, int charIndex, int charCount,
byte[] bytes, int byteIndex)
{
if (s == null || bytes == null)
- throw new ArgumentNullException((s == null ? "s" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((s == null ? nameof(s) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (s.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("s", SR.ArgumentOutOfRange_IndexCount);
+ throw new ArgumentOutOfRangeException(nameof(s), SR.ArgumentOutOfRange_IndexCount);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
int byteCount = bytes.Length - byteIndex;
@@ -130,16 +130,16 @@ namespace System.Text
{
// Validate parameters
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
// If nothing to encode return 0, avoid fixed problem
if (charCount == 0)
@@ -160,10 +160,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetBytes(chars, charCount, bytes, byteCount, null);
}
@@ -179,13 +179,13 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input just return 0, fixed doesn't like 0 length arrays
if (count == 0)
@@ -203,10 +203,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetCharCount(bytes, count, null);
}
@@ -220,16 +220,16 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if ( bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (charIndex < 0 || charIndex > chars.Length)
- throw new ArgumentOutOfRangeException("charIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index);
// If no input, return 0 & avoid fixed problem
if (byteCount == 0)
@@ -250,10 +250,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetChars(bytes, byteCount, chars, charCount, null);
}
@@ -265,23 +265,23 @@ namespace System.Text
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe String GetString(byte[] bytes, int index, int count)
+ public override unsafe string GetString(byte[] bytes, int index, int count)
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// Avoid problems with empty input buffer
- if (count == 0) return String.Empty;
+ if (count == 0) return string.Empty;
fixed (byte* pBytes = bytes)
- return String.CreateStringFromEncoding(
+ return string.CreateStringFromEncoding(
pBytes + index, count, this);
}
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncodingProvider.cs b/src/System.Private.CoreLib/shared/System/Text/EncodingProvider.cs
index ce8c3e020..4d15eea01 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncodingProvider.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncodingProvider.cs
@@ -130,7 +130,7 @@ namespace System.Text
return null;
}
- private static Object s_InternalSyncObject = new Object();
+ private static object s_InternalSyncObject = new object();
private static volatile EncodingProvider[] s_providers;
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Text/Latin1Encoding.cs b/src/System.Private.CoreLib/shared/System/Text/Latin1Encoding.cs
index 335eb76e3..736fff5d2 100644
--- a/src/System.Private.CoreLib/shared/System/Text/Latin1Encoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/Latin1Encoding.cs
@@ -11,7 +11,7 @@ namespace System.Text
// Latin1Encoding is a simple override to optimize the GetString version of Latin1Encoding.
// because of the best fit cases we can't do this when encoding the string, only when decoding
//
- internal class Latin1Encoding : EncodingNLS
+ internal sealed class Latin1Encoding : EncodingNLS
{
// Used by Encoding.Latin1 for lazy initialization
// The initialization code will not be run until a static member of the class is referenced
@@ -42,7 +42,7 @@ namespace System.Text
if (encoder != null)
{
charLeftOver = encoder._charLeftOver;
- Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
+ Debug.Assert(charLeftOver == 0 || char.IsHighSurrogate(charLeftOver),
"[Latin1Encoding.GetByteCount]leftover character should be high surrogate");
fallback = encoder.Fallback as EncoderReplacementFallback;
@@ -164,7 +164,7 @@ namespace System.Text
{
charLeftOver = encoder._charLeftOver;
fallback = encoder.Fallback as EncoderReplacementFallback;
- Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
+ Debug.Assert(charLeftOver == 0 || char.IsHighSurrogate(charLeftOver),
"[Latin1Encoding.GetBytes]leftover character should be high surrogate");
// Verify that we have no fallbackbuffer, for ASCII its always empty, so just assert
diff --git a/src/System.Private.CoreLib/shared/System/Text/StringBuilder.Debug.cs b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.Debug.cs
new file mode 100644
index 000000000..a62c4777a
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.Debug.cs
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+
+namespace System.Text
+{
+ public sealed partial class StringBuilder
+ {
+ private void ShowChunks(int maxChunksToShow = 10)
+ {
+ int count = 0;
+ StringBuilder head = this, current = this;
+ while (current != null)
+ {
+ if (count < maxChunksToShow)
+ {
+ count++;
+ }
+ else
+ {
+ head = head.m_ChunkPrevious;
+ }
+ current = current.m_ChunkPrevious;
+ }
+ current = head;
+ string[] chunks = new string[count];
+ for (int i = count; i > 0; i--)
+ {
+ chunks[i - 1] = new string(current.m_ChunkChars).Replace('\0', '.');
+ current = current.m_ChunkPrevious;
+ }
+ Debug.WriteLine('|' + string.Join('|', chunks) + '|');
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs
index a7804c399..99021e2dd 100644
--- a/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs
@@ -18,10 +18,10 @@ using System.Collections.Generic;
namespace System.Text
{
// This class represents a mutable string. It is convenient for situations in
- // which it is desirable to modify a string, perhaps by removing, replacing, or
+ // which it is desirable to modify a string, perhaps by removing, replacing, or
// inserting characters, without creating a new String subsequent to
- // each modification.
- //
+ // each modification.
+ //
// The methods contained within this class do not return a new StringBuilder
// object unless specified otherwise. This class may be used in conjunction with the String
// class to carry out modifications upon strings.
@@ -30,8 +30,8 @@ namespace System.Text
public sealed partial class StringBuilder : ISerializable
{
// A StringBuilder is internally represented as a linked list of blocks each of which holds
- // a chunk of the string. It turns out string as a whole can also be represented as just a chunk,
- // so that is what we do.
+ // a chunk of the string. It turns out string as a whole can also be represented as just a chunk,
+ // so that is what we do.
/// <summary>
/// The character buffer for this chunk.
@@ -73,7 +73,7 @@ namespace System.Text
// We want to keep chunk arrays out of large object heap (< 85K bytes ~ 40K chars) to be sure.
// Making the maximum chunk size big means less allocation code called, but also more waste
// in unused characters and slower inserts / replaces (since you do need to slide characters over
- // within a buffer).
+ // within a buffer).
internal const int MaxChunkSize = 8000;
/// <summary>
@@ -201,7 +201,7 @@ namespace System.Text
int persistedCapacity = 0;
string persistedString = null;
- int persistedMaxCapacity = Int32.MaxValue;
+ int persistedMaxCapacity = int.MaxValue;
bool capacityPresent = false;
// Get the data
@@ -353,7 +353,7 @@ namespace System.Text
return Capacity;
}
- public override String ToString()
+ public override string ToString()
{
AssertInvariants();
@@ -377,7 +377,7 @@ namespace System.Text
int chunkOffset = chunk.m_ChunkOffset;
int chunkLength = chunk.m_ChunkLength;
- // Check that we will not overrun our boundaries.
+ // Check that we will not overrun our boundaries.
if ((uint)(chunkLength + chunkOffset) <= (uint)result.Length && (uint)chunkLength <= (uint)sourceArray.Length)
{
fixed (char* sourcePtr = &sourceArray[0])
@@ -462,13 +462,10 @@ namespace System.Text
throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_SmallCapacity);
}
- int originalCapacity = Capacity;
-
if (value == 0 && m_ChunkPrevious == null)
{
m_ChunkLength = 0;
m_ChunkOffset = 0;
- Debug.Assert(Capacity >= originalCapacity);
return;
}
@@ -483,22 +480,32 @@ namespace System.Text
StringBuilder chunk = FindChunkForIndex(value);
if (chunk != this)
{
- // We crossed a chunk boundary when reducing the Length. We must replace this middle-chunk with a new larger chunk,
- // to ensure the original capacity is preserved.
- int newLen = originalCapacity - chunk.m_ChunkOffset;
- char[] newArray = new char[newLen];
-
- Debug.Assert(newLen > chunk.m_ChunkChars.Length, "The new chunk should be larger than the one it is replacing.");
- Array.Copy(chunk.m_ChunkChars, 0, newArray, 0, chunk.m_ChunkLength);
+ // Avoid possible infinite capacity growth. See https://github.com/dotnet/coreclr/pull/16926
+ int capacityToPreserve = Math.Min(Capacity, Math.Max(Length * 6 / 5, m_ChunkChars.Length));
+ int newLen = capacityToPreserve - chunk.m_ChunkOffset;
+ if (newLen > chunk.m_ChunkChars.Length)
+ {
+ // We crossed a chunk boundary when reducing the Length. We must replace this middle-chunk with a new larger chunk,
+ // to ensure the capacity we want is preserved.
+ char[] newArray = new char[newLen];
+ Array.Copy(chunk.m_ChunkChars, 0, newArray, 0, chunk.m_ChunkLength);
+ m_ChunkChars = newArray;
+ }
+ else
+ {
+ // Special case where the capacity we want to keep corresponds exactly to the size of the content.
+ // Just take ownership of the array.
+ Debug.Assert(newLen == chunk.m_ChunkChars.Length, "The new chunk should be larger or equal to the one it is replacing.");
+ m_ChunkChars = chunk.m_ChunkChars;
+ }
- m_ChunkChars = newArray;
m_ChunkPrevious = chunk.m_ChunkPrevious;
m_ChunkOffset = chunk.m_ChunkOffset;
}
m_ChunkLength = value - chunk.m_ChunkOffset;
AssertInvariants();
}
- Debug.Assert(Capacity >= originalCapacity);
+ Debug.Assert(Length == value, "Something went wrong setting Length.");
}
}
@@ -551,6 +558,138 @@ namespace System.Text
}
/// <summary>
+ /// GetChunks returns ChunkEnumerator that follows the IEnumerable pattern and
+ /// thus can be used in a C# 'foreach' statements to retreive the data in the StringBuilder
+ /// as chunks (ReadOnlyMemory) of characters. An example use is:
+ ///
+ /// foreach (ReadOnlyMemory<char> chunk in sb.GetChunks())
+ /// foreach(char c in chunk.Span)
+ /// { /* operation on c }
+ ///
+ /// It is undefined what happens if the StringBuilder is modified while the chunk
+ /// enumeration is incomplete. StringBuilder is also not thread-safe, so operating
+ /// on it with concurrent threads is illegal. Finally the ReadOnlyMemory chunks returned
+ /// are NOT guarenteed to remain unchanged if the StringBuilder is modified, so do
+ /// not cache them for later use either. This API's purpose is efficiently extracting
+ /// the data of a CONSTANT StringBuilder.
+ ///
+ /// Creating a ReadOnlySpan from a ReadOnlyMemory (the .Span property) is expensive
+ /// compared to the fetching of the character, so create a local variable for the SPAN
+ /// if you need to use it in a nested for statement. For example
+ ///
+ /// foreach (ReadOnlyMemory<char> chunk in sb.GetChunks())
+ /// {
+ /// var span = chunk.Span;
+ /// for(int i = 0; i < span.Length; i++)
+ /// { /* operation on span[i] */ }
+ /// }
+ /// </summary>
+ public ChunkEnumerator GetChunks() => new ChunkEnumerator(this);
+
+ /// <summary>
+ /// ChunkEnumerator supports both the IEnumerable and IEnumerator pattern so foreach
+ /// works (see GetChunks). It needs to be public (so the compiler can use it
+ /// when building a foreach statement) but users typically don't use it explicitly.
+ /// (which is why it is a nested type).
+ /// </summary>
+ public struct ChunkEnumerator
+ {
+ private readonly StringBuilder _firstChunk; // The first Stringbuilder chunk (which is the end of the logical string)
+ private StringBuilder _currentChunk; // The chunk that this enumerator is currently returning (Current).
+ private readonly ManyChunkInfo _manyChunks; // Only used for long string builders with many chunks (see constructor)
+
+ /// <summary>
+ /// Implement IEnumerable.GetEnumerator() to return 'this' as the IEnumerator
+ /// </summary>
+ [ComponentModel.EditorBrowsable(ComponentModel.EditorBrowsableState.Never)] // Only here to make foreach work
+ public ChunkEnumerator GetEnumerator() { return this; }
+
+ /// <summary>
+ /// Implements the IEnumerator pattern.
+ /// </summary>
+ public bool MoveNext()
+ {
+ if (_currentChunk == _firstChunk)
+ return false;
+
+ if (_manyChunks != null)
+ return _manyChunks.MoveNext(ref _currentChunk);
+
+ StringBuilder next = _firstChunk;
+ while (next.m_ChunkPrevious != _currentChunk)
+ next = next.m_ChunkPrevious;
+ _currentChunk = next;
+ return true;
+ }
+
+ /// <summary>
+ /// Implements the IEnumerator pattern.
+ /// </summary>
+ public ReadOnlyMemory<char> Current => new ReadOnlyMemory<char>(_currentChunk.m_ChunkChars, 0, _currentChunk.m_ChunkLength);
+
+ #region private
+ internal ChunkEnumerator(StringBuilder stringBuilder)
+ {
+ Debug.Assert(stringBuilder != null);
+ _firstChunk = stringBuilder;
+ _currentChunk = null; // MoveNext will find the last chunk if we do this.
+ _manyChunks = null;
+
+ // There is a performance-vs-allocation tradeoff. Because the chunks
+ // are a linked list with each chunk pointing to its PREDECESSOR, walking
+ // the list FORWARD is not efficient. If there are few chunks (< 8) we
+ // simply scan from the start each time, and tolerate the N*N behavior.
+ // However above this size, we allocate an array to hold pointers to all
+ // the chunks and we can be efficient for large N.
+ int chunkCount = ChunkCount(stringBuilder);
+ if (8 < chunkCount)
+ _manyChunks = new ManyChunkInfo(stringBuilder, chunkCount);
+ }
+
+ private static int ChunkCount(StringBuilder stringBuilder)
+ {
+ int ret = 0;
+ while (stringBuilder != null)
+ {
+ ret++;
+ stringBuilder = stringBuilder.m_ChunkPrevious;
+ }
+ return ret;
+ }
+
+ /// <summary>
+ /// Used to hold all the chunks indexes when you have many chunks.
+ /// </summary>
+ private class ManyChunkInfo
+ {
+ private readonly StringBuilder[] _chunks; // These are in normal order (first chunk first)
+ private int _chunkPos;
+
+ public bool MoveNext(ref StringBuilder current)
+ {
+ int pos = ++_chunkPos;
+ if (_chunks.Length <= pos)
+ return false;
+ current = _chunks[pos];
+ return true;
+ }
+
+ public ManyChunkInfo(StringBuilder stringBuilder, int chunkCount)
+ {
+ _chunks = new StringBuilder[chunkCount];
+ while (0 <= --chunkCount)
+ {
+ Debug.Assert(stringBuilder != null);
+ _chunks[chunkCount] = stringBuilder;
+ stringBuilder = stringBuilder.m_ChunkPrevious;
+ }
+ _chunkPos = -1;
+ }
+ }
+#endregion
+ }
+
+ /// <summary>
/// Appends a character 0 or more times to the end of this builder.
/// </summary>
/// <param name="value">The character to append.</param>
@@ -648,7 +787,7 @@ namespace System.Text
/// Appends a string to the end of this builder.
/// </summary>
/// <param name="value">The string to append.</param>
- public StringBuilder Append(String value)
+ public StringBuilder Append(string value)
{
if (value != null)
{
@@ -691,7 +830,7 @@ namespace System.Text
}
// We put this fixed in its own helper to avoid the cost of zero-initing `valueChars` in the
- // case we don't actually use it.
+ // case we don't actually use it.
private void AppendHelper(string value)
{
unsafe
@@ -903,7 +1042,7 @@ namespace System.Text
/// <param name="index">The index to insert in this builder.</param>
/// <param name="value">The string to insert.</param>
/// <param name="count">The number of times to insert the string.</param>
- public StringBuilder Insert(int index, String value, int count)
+ public StringBuilder Insert(int index, string value, int count)
{
if (count < 0)
{
@@ -921,7 +1060,7 @@ namespace System.Text
return this;
}
- // Ensure we don't insert more chars than we can hold, and we don't
+ // Ensure we don't insert more chars than we can hold, and we don't
// have any integer overflow in our new length.
long insertingChars = (long)value.Length * count;
if (insertingChars > MaxCapacity - this.Length)
@@ -1115,7 +1254,7 @@ namespace System.Text
{
return AppendJoinCore(&separator, 1, values);
}
-
+
private unsafe StringBuilder AppendJoinCore<T>(char* separator, int separatorLength, IEnumerable<T> values)
{
Debug.Assert(separator != null);
@@ -1182,7 +1321,7 @@ namespace System.Text
#endregion
- public StringBuilder Insert(int index, String value)
+ public StringBuilder Insert(int index, string value)
{
if ((uint)index > (uint)Length)
{
@@ -1292,7 +1431,7 @@ namespace System.Text
[CLSCompliant(false)]
public StringBuilder Insert(int index, ulong value) => Insert(index, value.ToString(), 1);
- public StringBuilder Insert(int index, Object value) => (value == null) ? this : Insert(index, value.ToString(), 1);
+ public StringBuilder Insert(int index, object value) => (value == null) ? this : Insert(index, value.ToString(), 1);
public StringBuilder Insert(int index, ReadOnlySpan<char> value)
{
@@ -1312,13 +1451,13 @@ namespace System.Text
return this;
}
- public StringBuilder AppendFormat(String format, Object arg0) => AppendFormatHelper(null, format, new ParamsArray(arg0));
+ public StringBuilder AppendFormat(string format, object arg0) => AppendFormatHelper(null, format, new ParamsArray(arg0));
- public StringBuilder AppendFormat(String format, Object arg0, Object arg1) => AppendFormatHelper(null, format, new ParamsArray(arg0, arg1));
+ public StringBuilder AppendFormat(string format, object arg0, object arg1) => AppendFormatHelper(null, format, new ParamsArray(arg0, arg1));
- public StringBuilder AppendFormat(String format, Object arg0, Object arg1, Object arg2) => AppendFormatHelper(null, format, new ParamsArray(arg0, arg1, arg2));
+ public StringBuilder AppendFormat(string format, object arg0, object arg1, object arg2) => AppendFormatHelper(null, format, new ParamsArray(arg0, arg1, arg2));
- public StringBuilder AppendFormat(String format, params Object[] args)
+ public StringBuilder AppendFormat(string format, params object[] args)
{
if (args == null)
{
@@ -1331,13 +1470,13 @@ namespace System.Text
return AppendFormatHelper(null, format, new ParamsArray(args));
}
- public StringBuilder AppendFormat(IFormatProvider provider, String format, Object arg0) => AppendFormatHelper(provider, format, new ParamsArray(arg0));
+ public StringBuilder AppendFormat(IFormatProvider provider, string format, object arg0) => AppendFormatHelper(provider, format, new ParamsArray(arg0));
- public StringBuilder AppendFormat(IFormatProvider provider, String format, Object arg0, Object arg1) => AppendFormatHelper(provider, format, new ParamsArray(arg0, arg1));
+ public StringBuilder AppendFormat(IFormatProvider provider, string format, object arg0, object arg1) => AppendFormatHelper(provider, format, new ParamsArray(arg0, arg1));
- public StringBuilder AppendFormat(IFormatProvider provider, String format, Object arg0, Object arg1, Object arg2) => AppendFormatHelper(provider, format, new ParamsArray(arg0, arg1, arg2));
+ public StringBuilder AppendFormat(IFormatProvider provider, string format, object arg0, object arg1, object arg2) => AppendFormatHelper(provider, format, new ParamsArray(arg0, arg1, arg2));
- public StringBuilder AppendFormat(IFormatProvider provider, String format, params Object[] args)
+ public StringBuilder AppendFormat(IFormatProvider provider, string format, params object[] args)
{
if (args == null)
{
@@ -1359,7 +1498,7 @@ namespace System.Text
private const int IndexLimit = 1000000; // Note: 0 <= ArgIndex < IndexLimit
private const int WidthLimit = 1000000; // Note: -WidthLimit < ArgAlign < WidthLimit
- internal StringBuilder AppendFormatHelper(IFormatProvider provider, String format, ParamsArray args)
+ internal StringBuilder AppendFormatHelper(IFormatProvider provider, string format, ParamsArray args)
{
if (format == null)
{
@@ -1495,8 +1634,8 @@ namespace System.Text
//
// Start of parsing of optional formatting parameter.
//
- Object arg = args[index];
- String itemFormat = null;
+ object arg = args[index];
+ string itemFormat = null;
ReadOnlySpan<char> itemFormatSpan = default; // used if itemFormat is null
// Is current character a colon? which indicates start of formatting parameter.
if (ch == ':')
@@ -1552,7 +1691,7 @@ namespace System.Text
if (startPos != pos)
{
// There was no brace escaping, extract the item format as a single string
- itemFormatSpan = format.AsSpan().Slice(startPos, pos - startPos);
+ itemFormatSpan = format.AsSpan(startPos, pos - startPos);
}
}
else
@@ -1566,7 +1705,7 @@ namespace System.Text
if (ch != '}') FormatError();
// Construct the output for this arg hole.
pos++;
- String s = null;
+ string s = null;
if (cf != null)
{
if (itemFormatSpan.Length != 0 && itemFormat == null)
@@ -1609,7 +1748,7 @@ namespace System.Text
}
}
// Append it to the final output of the Format String.
- if (s == null) s = String.Empty;
+ if (s == null) s = string.Empty;
int pad = width - s.Length;
if (!leftJustify && pad > 0) Append(' ', pad);
Append(s);
@@ -1628,7 +1767,7 @@ namespace System.Text
/// If <paramref name="newValue"/> is <c>null</c>, instances of <paramref name="oldValue"/>
/// are removed from this builder.
/// </remarks>
- public StringBuilder Replace(String oldValue, String newValue) => Replace(oldValue, newValue, 0, Length);
+ public StringBuilder Replace(string oldValue, string newValue) => Replace(oldValue, newValue, 0, Length);
/// <summary>
/// Determines if the contents of this builder are equal to the contents of another builder.
@@ -1680,10 +1819,10 @@ namespace System.Text
/// <summary>
/// Determines if the contents of this builder are equal to the contents of ReadOnlySpan<char>.
/// </summary>
- /// <param name="value">The ReadOnlySpan{char}.</param>
- public bool Equals(ReadOnlySpan<char> value)
+ /// <param name="span">The ReadOnlySpan{char}.</param>
+ public bool Equals(ReadOnlySpan<char> span)
{
- if (value.Length != Length)
+ if (span.Length != Length)
return false;
StringBuilder sbChunk = this;
@@ -1696,7 +1835,7 @@ namespace System.Text
ReadOnlySpan<char> chunk = new ReadOnlySpan<char>(sbChunk.m_ChunkChars, 0, chunk_length);
- if (!chunk.Equals(value.Slice(value.Length - offset, chunk_length)))
+ if (!chunk.EqualsOrdinal(span.Slice(span.Length - offset, chunk_length)))
return false;
sbChunk = sbChunk.m_ChunkPrevious;
@@ -1717,7 +1856,7 @@ namespace System.Text
/// If <paramref name="newValue"/> is <c>null</c>, instances of <paramref name="oldValue"/>
/// are removed from this builder.
/// </remarks>
- public StringBuilder Replace(String oldValue, String newValue, int startIndex, int count)
+ public StringBuilder Replace(string oldValue, string newValue, int startIndex, int count)
{
int currentLength = Length;
if ((uint)startIndex > (uint)currentLength)
@@ -1749,7 +1888,7 @@ namespace System.Text
int indexInChunk = startIndex - chunk.m_ChunkOffset;
while (count > 0)
{
- // Look for a match in the chunk,indexInChunk pointer
+ // Look for a match in the chunk,indexInChunk pointer
if (StartsWith(chunk, indexInChunk, count, oldValue))
{
// Push it on the replacements array (with growth), we will do all replacements in a
@@ -1775,13 +1914,13 @@ namespace System.Text
if (indexInChunk >= chunk.m_ChunkLength || count == 0) // Have we moved out of the current chunk?
{
- // Replacing mutates the blocks, so we need to convert to a logical index and back afterwards.
+ // Replacing mutates the blocks, so we need to convert to a logical index and back afterwards.
int index = indexInChunk + chunk.m_ChunkOffset;
int indexBeforeAdjustment = index;
// See if we accumulated any replacements, if so apply them.
ReplaceAllInChunk(replacements, replacementsCount, chunk, oldValue.Length, newValue);
- // The replacement has affected the logical index. Adjust it.
+ // The replacement has affected the logical index. Adjust it.
index += ((newValue.Length - oldValue.Length) * replacementsCount);
replacementsCount = 0;
@@ -1874,7 +2013,7 @@ namespace System.Text
throw new ArgumentOutOfRangeException(nameof(valueCount), SR.ArgumentOutOfRange_LengthGreaterThanCapacity);
}
- // This case is so common we want to optimize for it heavily.
+ // This case is so common we want to optimize for it heavily.
int newIndex = valueCount + m_ChunkLength;
if (newIndex <= m_ChunkChars.Length)
{
@@ -1891,7 +2030,7 @@ namespace System.Text
m_ChunkLength = m_ChunkChars.Length;
}
- // Expand the builder to add another chunk.
+ // Expand the builder to add another chunk.
int restLength = valueCount - firstLength;
ExpandByABlock(restLength);
Debug.Assert(m_ChunkLength == 0, "A new block was not created.");
@@ -1948,16 +2087,16 @@ namespace System.Text
{
fixed (char* valuePtr = value)
{
- // calculate the total amount of extra space or space needed for all the replacements.
+ // calculate the total amount of extra space or space needed for all the replacements.
int delta = (value.Length - removeCount) * replacementsCount;
StringBuilder targetChunk = sourceChunk; // the target as we copy chars down
int targetIndexInChunk = replacements[0];
- // Make the room needed for all the new characters if needed.
+ // Make the room needed for all the new characters if needed.
if (delta > 0)
MakeRoom(targetChunk.m_ChunkOffset + targetIndexInChunk, delta, out targetChunk, out targetIndexInChunk, true);
- // We made certain that characters after the insertion point are not moved,
+ // We made certain that characters after the insertion point are not moved,
int i = 0;
for (;;)
{
@@ -1974,7 +2113,7 @@ namespace System.Text
Debug.Assert(gapStart < sourceChunk.m_ChunkChars.Length, "gap starts at end of buffer. Should not happen");
Debug.Assert(gapStart <= gapEnd, "negative gap size");
Debug.Assert(gapEnd <= sourceChunk.m_ChunkLength, "gap too big");
- if (delta != 0) // can skip the sliding of gaps if source an target string are the same size.
+ if (delta != 0) // can skip the sliding of gaps if source an target string are the same size.
{
// Copy the gap data between the current replacement and the next replacement
fixed (char* sourcePtr = &sourceChunk.m_ChunkChars[gapStart])
@@ -1987,7 +2126,7 @@ namespace System.Text
}
}
- // Remove extra space if necessary.
+ // Remove extra space if necessary.
if (delta < 0)
Remove(targetChunk.m_ChunkOffset + targetIndexInChunk, -delta, out targetChunk, out targetIndexInChunk);
}
@@ -2044,7 +2183,7 @@ namespace System.Text
/// </param>
/// <param name="value">The pointer to the start of the character buffer.</param>
/// <param name="count">The number of characters in the buffer.</param>
- unsafe private void ReplaceInPlaceAtChunk(ref StringBuilder chunk, ref int indexInChunk, char* value, int count)
+ private unsafe void ReplaceInPlaceAtChunk(ref StringBuilder chunk, ref int indexInChunk, char* value, int count)
{
if (count != 0)
{
@@ -2056,7 +2195,7 @@ namespace System.Text
int lengthToCopy = Math.Min(lengthInChunk, count);
ThreadSafeCopy(value, chunk.m_ChunkChars, indexInChunk, lengthToCopy);
- // Advance the index.
+ // Advance the index.
indexInChunk += lengthToCopy;
if (indexInChunk >= chunk.m_ChunkLength)
{
@@ -2374,7 +2513,7 @@ namespace System.Text
int endIndex = startIndex + count;
- // Find the chunks for the start and end of the block to delete.
+ // Find the chunks for the start and end of the block to delete.
chunk = this;
StringBuilder endChunk = null;
int endIndexInChunk = 0;
@@ -2425,7 +2564,7 @@ namespace System.Text
// SafeCritical: We ensure that `endIndexInChunk + copyCount` is within range of `m_ChunkChars`, and
// also ensure that `copyTargetIndexInChunk + copyCount` is within the chunk.
- // Remove any characters in the end chunk, by sliding the characters down.
+ // Remove any characters in the end chunk, by sliding the characters down.
if (copyTargetIndexInChunk != endIndexInChunk) // Sometimes no move is necessary
{
ThreadSafeCopy(endChunk.m_ChunkChars, endIndexInChunk, endChunk.m_ChunkChars, copyTargetIndexInChunk, copyCount);
diff --git a/src/System.Private.CoreLib/shared/System/Text/StringBuilderCache.cs b/src/System.Private.CoreLib/shared/System/Text/StringBuilderCache.cs
new file mode 100644
index 000000000..e699cc27c
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Text/StringBuilderCache.cs
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Text
+{
+ /// <summary>Provide a cached reusable instance of stringbuilder per thread.</summary>
+ internal static class StringBuilderCache
+ {
+ // The value 360 was chosen in discussion with performance experts as a compromise between using
+ // as litle memory per thread as possible and still covering a large part of short-lived
+ // StringBuilder creations on the startup path of VS designers.
+ private const int MaxBuilderSize = 360;
+ private const int DefaultCapacity = 16; // == StringBuilder.DefaultCapacity
+
+ // WARNING: We allow diagnostic tools to directly inspect this member (t_cachedInstance).
+ // See https://github.com/dotnet/corert/blob/master/Documentation/design-docs/diagnostics/diagnostics-tools-contract.md for more details.
+ // Please do not change the type, the name, or the semantic usage of this member without understanding the implication for tools.
+ // Get in touch with the diagnostics team if you have questions.
+ [ThreadStatic]
+ private static StringBuilder t_cachedInstance;
+
+ /// <summary>Get a StringBuilder for the specified capacity.</summary>
+ /// <remarks>If a StringBuilder of an appropriate size is cached, it will be returned and the cache emptied.</remarks>
+ public static StringBuilder Acquire(int capacity = DefaultCapacity)
+ {
+ if (capacity <= MaxBuilderSize)
+ {
+ StringBuilder sb = t_cachedInstance;
+ if (sb != null)
+ {
+ // Avoid stringbuilder block fragmentation by getting a new StringBuilder
+ // when the requested size is larger than the current capacity
+ if (capacity <= sb.Capacity)
+ {
+ t_cachedInstance = null;
+ sb.Clear();
+ return sb;
+ }
+ }
+ }
+ return new StringBuilder(capacity);
+ }
+
+ /// <summary>Place the specified builder in the cache if it is not too big.</summary>
+ public static void Release(StringBuilder sb)
+ {
+ if (sb.Capacity <= MaxBuilderSize)
+ {
+ t_cachedInstance = sb;
+ }
+ }
+
+ /// <summary>ToString() the stringbuilder, Release it to the cache, and return the resulting string.</summary>
+ public static string GetStringAndRelease(StringBuilder sb)
+ {
+ string result = sb.ToString();
+ Release(sb);
+ return result;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Text/UTF32Encoding.cs b/src/System.Private.CoreLib/shared/System/Text/UTF32Encoding.cs
index 7828775ea..86169e6b1 100644
--- a/src/System.Private.CoreLib/shared/System/Text/UTF32Encoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/UTF32Encoding.cs
@@ -103,13 +103,13 @@ namespace System.Text
{
// Validate input parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - index < count)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input, return 0, avoid fixed empty array problem
if (count == 0)
@@ -125,11 +125,11 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe int GetByteCount(String s)
+ public override unsafe int GetByteCount(string s)
{
// Validate input
if (s==null)
- throw new ArgumentNullException("s");
+ throw new ArgumentNullException(nameof(s));
fixed (char* pChars = s)
return GetByteCount(pChars, s.Length, null);
@@ -144,10 +144,10 @@ namespace System.Text
{
// Validate Parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
// Call it with empty encoder
return GetByteCount(chars, count, null);
@@ -158,20 +158,20 @@ namespace System.Text
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
- public override unsafe int GetBytes(String s, int charIndex, int charCount,
+ public override unsafe int GetBytes(string s, int charIndex, int charCount,
byte[] bytes, int byteIndex)
{
if (s == null || bytes == null)
- throw new ArgumentNullException((s == null ? "s" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((s == null ? nameof(s) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (s.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("s", SR.ArgumentOutOfRange_IndexCount);
+ throw new ArgumentOutOfRangeException(nameof(s), SR.ArgumentOutOfRange_IndexCount);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
int byteCount = bytes.Length - byteIndex;
@@ -198,16 +198,16 @@ namespace System.Text
{
// Validate parameters
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
// If nothing to encode return 0, avoid fixed problem
if (charCount == 0)
@@ -230,10 +230,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetBytes(chars, charCount, bytes, byteCount, null);
}
@@ -250,13 +250,13 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input just return 0, fixed doesn't like 0 length arrays.
if (count == 0)
@@ -276,10 +276,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetCharCount(bytes, count, null);
}
@@ -294,16 +294,16 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if ( bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (charIndex < 0 || charIndex > chars.Length)
- throw new ArgumentOutOfRangeException("charIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index);
// If no input, return 0 & avoid fixed problem
if (byteCount == 0)
@@ -326,10 +326,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetChars(bytes, byteCount, chars, charCount, null);
}
@@ -342,23 +342,23 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe String GetString(byte[] bytes, int index, int count)
+ public override unsafe string GetString(byte[] bytes, int index, int count)
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// Avoid problems with empty input buffer
- if (count == 0) return String.Empty;
+ if (count == 0) return string.Empty;
fixed (byte* pBytes = bytes)
- return String.CreateStringFromEncoding(
+ return string.CreateStringFromEncoding(
pBytes + index, count, this);
}
@@ -417,7 +417,7 @@ namespace System.Text
//
// In previous char, we encounter a high surrogate, so we are expecting a low surrogate here.
//
- if (Char.IsLowSurrogate(ch))
+ if (char.IsLowSurrogate(ch))
{
// They're all legal
highSurrogate = '\0';
@@ -447,7 +447,7 @@ namespace System.Text
}
// Do we have another high surrogate?
- if (Char.IsHighSurrogate(ch))
+ if (char.IsHighSurrogate(ch))
{
//
// We'll have a high surrogate to check next time.
@@ -457,7 +457,7 @@ namespace System.Text
}
// Check for illegal characters
- if (Char.IsLowSurrogate(ch))
+ if (char.IsLowSurrogate(ch))
{
// We have a leading low surrogate, do the fallback
charsForFallback = chars;
@@ -552,7 +552,7 @@ namespace System.Text
//
// In previous char, we encountered a high surrogate, so we are expecting a low surrogate here.
//
- if (Char.IsLowSurrogate(ch))
+ if (char.IsLowSurrogate(ch))
{
// Is it a legal one?
uint iTemp = GetSurrogate(highSurrogate, ch);
@@ -616,7 +616,7 @@ namespace System.Text
}
// Do we have another high surrogate?, if so remember it
- if (Char.IsHighSurrogate(ch))
+ if (char.IsHighSurrogate(ch))
{
//
// We'll have a high surrogate to check next time.
@@ -626,7 +626,7 @@ namespace System.Text
}
// Check for illegal characters (low surrogate)
- if (Char.IsLowSurrogate(ch))
+ if (char.IsLowSurrogate(ch))
{
// We have a leading low surrogate, do the fallback
charsForFallback = chars;
@@ -1159,7 +1159,7 @@ namespace System.Text
_emitUTF32ByteOrderMark ? (_bigEndian ? s_bigEndianPreamble : s_littleEndianPreamble) :
Array.Empty<byte>();
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
UTF32Encoding that = value as UTF32Encoding;
if (that != null)
diff --git a/src/System.Private.CoreLib/shared/System/Text/UTF7Encoding.cs b/src/System.Private.CoreLib/shared/System/Text/UTF7Encoding.cs
index 0246c2891..5c51c8107 100644
--- a/src/System.Private.CoreLib/shared/System/Text/UTF7Encoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/UTF7Encoding.cs
@@ -14,17 +14,17 @@ namespace System.Text
{
public class UTF7Encoding : Encoding
{
- private const String base64Chars =
+ private const string base64Chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
// 0123456789111111111122222222223333333333444444444455555555556666
// 012345678901234567890123456789012345678901234567890123
// These are the characters that can be directly encoded in UTF7.
- private const String directChars =
+ private const string directChars =
"\t\n\r '(),-./0123456789:?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
// These are the characters that can be optionally directly encoded in UTF7.
- private const String optionalChars =
+ private const string optionalChars =
"!\"#$%&*;<=>@[]^_`{|}";
// Used by Encoding.UTF7 for lazy initialization
@@ -88,16 +88,16 @@ namespace System.Text
}
// We go ahead and set this because Encoding expects it, however nothing can fall back in UTF7.
- internal override void SetDefaultFallbacks()
+ internal sealed override void SetDefaultFallbacks()
{
// UTF7 had an odd decoderFallback behavior, and the Encoder fallback
// is irrelevant because we encode surrogates individually and never check for unmatched ones
// (so nothing can fallback during encoding)
- this.encoderFallback = new EncoderReplacementFallback(String.Empty);
+ this.encoderFallback = new EncoderReplacementFallback(string.Empty);
this.decoderFallback = new DecoderUTF7Fallback();
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
UTF7Encoding that = value as UTF7Encoding;
if (that != null)
@@ -133,13 +133,13 @@ namespace System.Text
{
// Validate input parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - index < count)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input, return 0, avoid fixed empty array problem
if (count == 0)
@@ -159,7 +159,7 @@ namespace System.Text
{
// Validate input
if (s==null)
- throw new ArgumentNullException("s");
+ throw new ArgumentNullException(nameof(s));
fixed (char* pChars = s)
return GetByteCount(pChars, s.Length, null);
@@ -174,10 +174,10 @@ namespace System.Text
{
// Validate Parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
// Call it with empty encoder
return GetByteCount(chars, count, null);
@@ -192,16 +192,16 @@ namespace System.Text
byte[] bytes, int byteIndex)
{
if (s == null || bytes == null)
- throw new ArgumentNullException((s == null ? "s" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((s == null ? nameof(s) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (s.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("s", SR.ArgumentOutOfRange_IndexCount);
+ throw new ArgumentOutOfRangeException(nameof(s), SR.ArgumentOutOfRange_IndexCount);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
int byteCount = bytes.Length - byteIndex;
@@ -228,16 +228,16 @@ namespace System.Text
{
// Validate parameters
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
// If nothing to encode return 0, avoid fixed problem
if (charCount == 0)
@@ -260,10 +260,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetBytes(chars, charCount, bytes, byteCount, null);
}
@@ -280,13 +280,13 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input just return 0, fixed doesn't like 0 length arrays.
if (count == 0)
@@ -306,10 +306,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetCharCount(bytes, count, null);
}
@@ -324,16 +324,16 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if ( bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (charIndex < 0 || charIndex > chars.Length)
- throw new ArgumentOutOfRangeException("charIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index);
// If no input, return 0 & avoid fixed problem
if (byteCount == 0)
@@ -356,10 +356,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetChars(bytes, byteCount, chars, charCount, null);
}
@@ -372,23 +372,23 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe String GetString(byte[] bytes, int index, int count)
+ public override unsafe string GetString(byte[] bytes, int index, int count)
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// Avoid problems with empty input buffer
- if (count == 0) return String.Empty;
+ if (count == 0) return string.Empty;
fixed (byte* pBytes = bytes)
- return String.CreateStringFromEncoding(
+ return string.CreateStringFromEncoding(
pBytes + index, count, this);
}
@@ -396,7 +396,7 @@ namespace System.Text
// End of standard methods copied from EncodingNLS.cs
//
- internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS baseEncoder)
+ internal sealed override unsafe int GetByteCount(char* chars, int count, EncoderNLS baseEncoder)
{
Debug.Assert(chars != null, "[UTF7Encoding.GetByteCount]chars!=null");
Debug.Assert(count >= 0, "[UTF7Encoding.GetByteCount]count >=0");
@@ -405,8 +405,8 @@ namespace System.Text
return GetBytes(chars, count, null, 0, baseEncoder);
}
- internal override unsafe int GetBytes(char* chars, int charCount,
- byte* bytes, int byteCount, EncoderNLS baseEncoder)
+ internal sealed override unsafe int GetBytes(
+ char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS baseEncoder)
{
Debug.Assert(byteCount >= 0, "[UTF7Encoding.GetBytes]byteCount >=0");
Debug.Assert(chars != null, "[UTF7Encoding.GetBytes]chars!=null");
@@ -545,7 +545,7 @@ namespace System.Text
return buffer.Count;
}
- internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
+ internal sealed override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
{
Debug.Assert(count >= 0, "[UTF7Encoding.GetCharCount]count >=0");
Debug.Assert(bytes != null, "[UTF7Encoding.GetCharCount]bytes!=null");
@@ -554,8 +554,8 @@ namespace System.Text
return GetChars(bytes, count, null, 0, baseDecoder);
}
- internal override unsafe int GetChars(byte* bytes, int byteCount,
- char* chars, int charCount, DecoderNLS baseDecoder)
+ internal sealed override unsafe int GetChars(
+ byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder)
{
Debug.Assert(byteCount >= 0, "[UTF7Encoding.GetChars]byteCount >=0");
Debug.Assert(bytes != null, "[UTF7Encoding.GetChars]bytes!=null");
@@ -873,7 +873,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
DecoderUTF7Fallback that = value as DecoderUTF7Fallback;
if (that != null)
diff --git a/src/System.Private.CoreLib/shared/System/Text/UTF8Encoding.cs b/src/System.Private.CoreLib/shared/System/Text/UTF8Encoding.cs
index 67f87c9b0..c9e51f661 100644
--- a/src/System.Private.CoreLib/shared/System/Text/UTF8Encoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/UTF8Encoding.cs
@@ -93,7 +93,7 @@ namespace System.Text
SetDefaultFallbacks();
}
- internal override void SetDefaultFallbacks()
+ internal sealed override void SetDefaultFallbacks()
{
// For UTF-X encodings, we use a replacement fallback with an empty string
if (_isThrowException)
@@ -130,13 +130,13 @@ namespace System.Text
{
// Validate input parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - index < count)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input, return 0, avoid fixed empty array problem
if (count == 0)
@@ -152,7 +152,7 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe int GetByteCount(String chars)
+ public override unsafe int GetByteCount(string chars)
{
// Validate input
if (chars==null)
@@ -171,34 +171,42 @@ namespace System.Text
{
// Validate Parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
// Call it with empty encoder
return GetByteCount(chars, count, null);
}
+ public override unsafe int GetByteCount(ReadOnlySpan<char> chars)
+ {
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ {
+ return GetByteCount(charsPtr, chars.Length, baseEncoder: null);
+ }
+ }
+
// Parent method is safe.
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
- public override unsafe int GetBytes(String s, int charIndex, int charCount,
+ public override unsafe int GetBytes(string s, int charIndex, int charCount,
byte[] bytes, int byteIndex)
{
if (s == null || bytes == null)
- throw new ArgumentNullException((s == null ? "s" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((s == null ? nameof(s) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (s.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("s", SR.ArgumentOutOfRange_IndexCount);
+ throw new ArgumentOutOfRangeException(nameof(s), SR.ArgumentOutOfRange_IndexCount);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
int byteCount = bytes.Length - byteIndex;
@@ -225,16 +233,16 @@ namespace System.Text
{
// Validate parameters
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
// If nothing to encode return 0, avoid fixed problem
if (charCount == 0)
@@ -257,14 +265,23 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetBytes(chars, charCount, bytes, byteCount, null);
}
+ public override unsafe int GetBytes(ReadOnlySpan<char> chars, Span<byte> bytes)
+ {
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ {
+ return GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length, baseEncoder: null);
+ }
+ }
+
// Returns the number of characters produced by decoding a range of bytes
// in a byte array.
//
@@ -277,13 +294,13 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input just return 0, fixed doesn't like 0 length arrays.
if (count == 0)
@@ -303,14 +320,22 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetCharCount(bytes, count, null);
}
+ public override unsafe int GetCharCount(ReadOnlySpan<byte> bytes)
+ {
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ {
+ return GetCharCount(bytesPtr, bytes.Length, baseDecoder: null);
+ }
+ }
+
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
@@ -321,16 +346,16 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if ( bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (charIndex < 0 || charIndex > chars.Length)
- throw new ArgumentOutOfRangeException("charIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index);
// If no input, return 0 & avoid fixed problem
if (byteCount == 0)
@@ -353,14 +378,23 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetChars(bytes, byteCount, chars, charCount, null);
}
+ public override unsafe int GetChars(ReadOnlySpan<byte> bytes, Span<char> chars)
+ {
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ {
+ return GetChars(bytesPtr, bytes.Length, charsPtr, chars.Length, baseDecoder: null);
+ }
+ }
+
// Returns a string containing the decoded representation of a range of
// bytes in a byte array.
//
@@ -369,23 +403,23 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe String GetString(byte[] bytes, int index, int count)
+ public override unsafe string GetString(byte[] bytes, int index, int count)
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// Avoid problems with empty input buffer
- if (count == 0) return String.Empty;
+ if (count == 0) return string.Empty;
fixed (byte* pBytes = bytes)
- return String.CreateStringFromEncoding(
+ return string.CreateStringFromEncoding(
pBytes + index, count, this);
}
@@ -395,7 +429,7 @@ namespace System.Text
// To simplify maintenance, the structure of GetByteCount and GetBytes should be
// kept the same as much as possible
- internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS baseEncoder)
+ internal sealed override unsafe int GetByteCount(char* chars, int count, EncoderNLS baseEncoder)
{
// For fallback we may need a fallback buffer.
// We wait to initialize it though in case we don't have any broken input unicode
@@ -715,12 +749,15 @@ namespace System.Text
break;
LongCodeWithMask:
-#if BIGENDIAN
- // be careful about the sign extension
- ch = (int)(((uint)ch) >> 16);
-#else // BIGENDIAN
- ch = (char)ch;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ ch = (char)ch;
+ }
+ else
+ {
+ // be careful about the sign extension
+ ch = (int)(((uint)ch) >> 16);
+ }
pSrc++;
if (ch <= 0x7F)
@@ -783,13 +820,13 @@ namespace System.Text
// diffs two char pointers using unsigned arithmetic. The unsigned arithmetic
// is good enough for us, and it tends to generate better code than the signed
// arithmetic generated by default
- unsafe private static int PtrDiff(char* a, char* b)
+ private static unsafe int PtrDiff(char* a, char* b)
{
return (int)(((uint)((byte*)a - (byte*)b)) >> 1);
}
// byte* flavor just for parity
- unsafe private static int PtrDiff(byte* a, byte* b)
+ private static unsafe int PtrDiff(byte* a, byte* b)
{
return (int)(a - b);
}
@@ -801,8 +838,8 @@ namespace System.Text
// Our workhorse
// Note: We ignore mismatched surrogates, unless the exception flag is set in which case we throw
- internal override unsafe int GetBytes(char* chars, int charCount,
- byte* bytes, int byteCount, EncoderNLS baseEncoder)
+ internal sealed override unsafe int GetBytes(
+ char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS baseEncoder)
{
Debug.Assert(chars != null, "[UTF8Encoding.GetBytes]chars!=null");
Debug.Assert(byteCount >= 0, "[UTF8Encoding.GetBytes]byteCount >=0");
@@ -1142,31 +1179,37 @@ namespace System.Text
}
// Unfortunately, this is endianess sensitive
-#if BIGENDIAN
- *pTarget = (byte)(ch>>16);
- *(pTarget+1) = (byte)ch;
- pSrc += 4;
- *(pTarget+2) = (byte)(chc>>16);
- *(pTarget+3) = (byte)chc;
- pTarget += 4;
-#else // BIGENDIAN
- *pTarget = (byte)ch;
- *(pTarget + 1) = (byte)(ch >> 16);
- pSrc += 4;
- *(pTarget + 2) = (byte)chc;
- *(pTarget + 3) = (byte)(chc >> 16);
- pTarget += 4;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ *pTarget = (byte)ch;
+ *(pTarget + 1) = (byte)(ch >> 16);
+ pSrc += 4;
+ *(pTarget + 2) = (byte)chc;
+ *(pTarget + 3) = (byte)(chc >> 16);
+ pTarget += 4;
+ }
+ else
+ {
+ *pTarget = (byte)(ch>>16);
+ *(pTarget+1) = (byte)ch;
+ pSrc += 4;
+ *(pTarget+2) = (byte)(chc>>16);
+ *(pTarget+3) = (byte)chc;
+ pTarget += 4;
+ }
}
continue;
LongCodeWithMask:
-#if BIGENDIAN
- // be careful about the sign extension
- ch = (int)(((uint)ch) >> 16);
-#else // BIGENDIAN
- ch = (char)ch;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ ch = (char)ch;
+ }
+ else
+ {
+ // be careful about the sign extension
+ ch = (int)(((uint)ch) >> 16);
+ }
pSrc++;
if (ch > 0x7F)
@@ -1284,7 +1327,7 @@ namespace System.Text
//
// To simplify maintenance, the structure of GetCharCount and GetChars should be
// kept the same as much as possible
- internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
+ internal sealed override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
{
Debug.Assert(count >= 0, "[UTF8Encoding.GetCharCount]count >=0");
Debug.Assert(bytes != null, "[UTF8Encoding.GetCharCount]bytes!=null");
@@ -1564,17 +1607,26 @@ namespace System.Text
}
break;
-#if BIGENDIAN
- LongCodeWithMask32:
- // be careful about the sign extension
- ch = (int)(((uint)ch) >> 16);
- LongCodeWithMask16:
- ch = (int)(((uint)ch) >> 8);
-#else // BIGENDIAN
LongCodeWithMask32:
+ if (BitConverter.IsLittleEndian)
+ {
+ ch &= 0xFF;
+ }
+ else
+ {
+ // be careful about the sign extension
+ ch = (int)(((uint)ch) >> 16);
+ }
LongCodeWithMask16:
- ch &= 0xFF;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ ch &= 0xFF;
+ }
+ else
+ {
+ ch = (int)(((uint)ch) >> 8);
+ }
+
pSrc++;
if (ch <= 0x7F)
{
@@ -1713,8 +1765,8 @@ namespace System.Text
//
// To simplify maintenance, the structure of GetCharCount and GetChars should be
// kept the same as much as possible
- internal override unsafe int GetChars(byte* bytes, int byteCount,
- char* chars, int charCount, DecoderNLS baseDecoder)
+ internal sealed override unsafe int GetChars(
+ byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder)
{
Debug.Assert(chars != null, "[UTF8Encoding.GetChars]chars!=null");
Debug.Assert(byteCount >= 0, "[UTF8Encoding.GetChars]count >=0");
@@ -2048,17 +2100,20 @@ namespace System.Text
}
// Unfortunately, this is endianess sensitive
-#if BIGENDIAN
- *pTarget = (char)((ch >> 8) & 0x7F);
- pSrc += 2;
- *(pTarget+1) = (char)(ch & 0x7F);
- pTarget += 2;
-#else // BIGENDIAN
- *pTarget = (char)(ch & 0x7F);
- pSrc += 2;
- *(pTarget + 1) = (char)((ch >> 8) & 0x7F);
- pTarget += 2;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ *pTarget = (char)(ch & 0x7F);
+ pSrc += 2;
+ *(pTarget + 1) = (char)((ch >> 8) & 0x7F);
+ pTarget += 2;
+ }
+ else
+ {
+ *pTarget = (char)((ch >> 8) & 0x7F);
+ pSrc += 2;
+ *(pTarget+1) = (char)(ch & 0x7F);
+ pTarget += 2;
+ }
}
// Run 8 characters at a time!
@@ -2072,43 +2127,54 @@ namespace System.Text
}
// Unfortunately, this is endianess sensitive
-#if BIGENDIAN
- *pTarget = (char)((ch >> 24) & 0x7F);
- *(pTarget+1) = (char)((ch >> 16) & 0x7F);
- *(pTarget+2) = (char)((ch >> 8) & 0x7F);
- *(pTarget+3) = (char)(ch & 0x7F);
- pSrc += 8;
- *(pTarget+4) = (char)((chb >> 24) & 0x7F);
- *(pTarget+5) = (char)((chb >> 16) & 0x7F);
- *(pTarget+6) = (char)((chb >> 8) & 0x7F);
- *(pTarget+7) = (char)(chb & 0x7F);
- pTarget += 8;
-#else // BIGENDIAN
- *pTarget = (char)(ch & 0x7F);
- *(pTarget + 1) = (char)((ch >> 8) & 0x7F);
- *(pTarget + 2) = (char)((ch >> 16) & 0x7F);
- *(pTarget + 3) = (char)((ch >> 24) & 0x7F);
- pSrc += 8;
- *(pTarget + 4) = (char)(chb & 0x7F);
- *(pTarget + 5) = (char)((chb >> 8) & 0x7F);
- *(pTarget + 6) = (char)((chb >> 16) & 0x7F);
- *(pTarget + 7) = (char)((chb >> 24) & 0x7F);
- pTarget += 8;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ *pTarget = (char)(ch & 0x7F);
+ *(pTarget + 1) = (char)((ch >> 8) & 0x7F);
+ *(pTarget + 2) = (char)((ch >> 16) & 0x7F);
+ *(pTarget + 3) = (char)((ch >> 24) & 0x7F);
+ pSrc += 8;
+ *(pTarget + 4) = (char)(chb & 0x7F);
+ *(pTarget + 5) = (char)((chb >> 8) & 0x7F);
+ *(pTarget + 6) = (char)((chb >> 16) & 0x7F);
+ *(pTarget + 7) = (char)((chb >> 24) & 0x7F);
+ pTarget += 8;
+ }
+ else
+ {
+ *pTarget = (char)((ch >> 24) & 0x7F);
+ *(pTarget+1) = (char)((ch >> 16) & 0x7F);
+ *(pTarget+2) = (char)((ch >> 8) & 0x7F);
+ *(pTarget+3) = (char)(ch & 0x7F);
+ pSrc += 8;
+ *(pTarget+4) = (char)((chb >> 24) & 0x7F);
+ *(pTarget+5) = (char)((chb >> 16) & 0x7F);
+ *(pTarget+6) = (char)((chb >> 8) & 0x7F);
+ *(pTarget+7) = (char)(chb & 0x7F);
+ pTarget += 8;
+ }
}
break;
-#if BIGENDIAN
- LongCodeWithMask32:
- // be careful about the sign extension
- ch = (int)(((uint)ch) >> 16);
- LongCodeWithMask16:
- ch = (int)(((uint)ch) >> 8);
-#else // BIGENDIAN
LongCodeWithMask32:
+ if (BitConverter.IsLittleEndian)
+ {
+ ch &= 0xFF;
+ }
+ else
+ {
+ // be careful about the sign extension
+ ch = (int)(((uint)ch) >> 16);
+ }
LongCodeWithMask16:
- ch &= 0xFF;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ ch &= 0xFF;
+ }
+ else
+ {
+ ch = (int)(((uint)ch) >> 8);
+ }
pSrc++;
if (ch <= 0x7F)
{
@@ -2173,7 +2239,7 @@ namespace System.Text
// extra byte, we're already planning 2 chars for 2 of these bytes,
// but the big loop is testing the target against pStop, so we need
- // to subtract 2 more or we risk overrunning the input. Subtract
+ // to subtract 2 more or we risk overrunning the input. Subtract
// one here and one below.
pStop--;
}
@@ -2323,11 +2389,17 @@ namespace System.Text
private unsafe int FallbackInvalidByteSequence(
byte* pSrc, int ch, DecoderFallbackBuffer fallback)
{
+ // Calling GetBytesUnknown can adjust the pSrc pointer but we need to pass the pointer before the adjustment
+ // to fallback.InternalFallback. The input pSrc to fallback.InternalFallback will only be used to calculate the
+ // index inside bytesUnknown and if we pass the adjusted pointer we can end up with negative index values.
+ // We store the original pSrc in pOriginalSrc and then pass pOriginalSrc to fallback.InternalFallback.
+ byte* pOriginalSrc = pSrc;
+
// Get our byte[]
byte[] bytesUnknown = GetBytesUnknown(ref pSrc, ch);
// Do the actual fallback
- int count = fallback.InternalFallback(bytesUnknown, pSrc);
+ int count = fallback.InternalFallback(bytesUnknown, pOriginalSrc);
// # of fallback chars expected.
// Note that we only get here for "long" sequences, and have already unreserved
@@ -2336,7 +2408,7 @@ namespace System.Text
}
// Note that some of these bytes may have come from a previous fallback, so we cannot
- // just decrement the pointer and use the values we read. In those cases we have
+ // just decrement the pointer and use the values we read. In those cases we have
// to regenerate the original values.
private unsafe byte[] GetBytesUnknown(ref byte* pSrc, int ch)
{
@@ -2481,7 +2553,7 @@ namespace System.Text
_emitUTF8Identifier ? s_preamble :
Array.Empty<byte>();
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
UTF8Encoding that = value as UTF8Encoding;
if (that != null)
diff --git a/src/System.Private.CoreLib/shared/System/Text/UnicodeEncoding.cs b/src/System.Private.CoreLib/shared/System/Text/UnicodeEncoding.cs
index 342bf53d6..6a27d2c85 100644
--- a/src/System.Private.CoreLib/shared/System/Text/UnicodeEncoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/UnicodeEncoding.cs
@@ -6,11 +6,17 @@
// Don't override IsAlwaysNormalized because it is just a Unicode Transformation and could be confused.
//
+// This define can be used to turn off the fast loops. Useful for finding whether
+// the problem is fastloop-specific.
+#define FASTLOOP
+
using System;
using System.Globalization;
using System.Diagnostics;
using System.Runtime.InteropServices;
+using Internal.Runtime.CompilerServices;
+
namespace System.Text
{
public class UnicodeEncoding : Encoding
@@ -23,15 +29,14 @@ namespace System.Text
private static readonly byte[] s_bigEndianPreamble = new byte[2] { 0xfe, 0xff };
private static readonly byte[] s_littleEndianPreamble = new byte[2] { 0xff, 0xfe };
- internal bool isThrowException = false;
+ private bool isThrowException = false;
- internal bool bigEndian = false;
- internal bool byteOrderMark = true;
+ private bool bigEndian = false;
+ private bool byteOrderMark = true;
// Unicode version 2.0 character size in bytes
public const int CharSize = 2;
-
public UnicodeEncoding()
: this(false, true)
{
@@ -56,7 +61,7 @@ namespace System.Text
SetDefaultFallbacks();
}
- internal override void SetDefaultFallbacks()
+ internal sealed override void SetDefaultFallbacks()
{
// For UTF-X encodings, we use a replacement fallback with an empty string
if (this.isThrowException)
@@ -89,13 +94,13 @@ namespace System.Text
{
// Validate input parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - index < count)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input, return 0, avoid fixed empty array problem
if (count == 0)
@@ -111,11 +116,11 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe int GetByteCount(String s)
+ public override unsafe int GetByteCount(string s)
{
// Validate input
if (s==null)
- throw new ArgumentNullException("s");
+ throw new ArgumentNullException(nameof(s));
fixed (char* pChars = s)
return GetByteCount(pChars, s.Length, null);
@@ -130,10 +135,10 @@ namespace System.Text
{
// Validate Parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
// Call it with empty encoder
return GetByteCount(chars, count, null);
@@ -144,20 +149,20 @@ namespace System.Text
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
- public override unsafe int GetBytes(String s, int charIndex, int charCount,
+ public override unsafe int GetBytes(string s, int charIndex, int charCount,
byte[] bytes, int byteIndex)
{
if (s == null || bytes == null)
- throw new ArgumentNullException((s == null ? "s" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((s == null ? nameof(s) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (s.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("s", SR.ArgumentOutOfRange_IndexCount);
+ throw new ArgumentOutOfRangeException(nameof(s), SR.ArgumentOutOfRange_IndexCount);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
int byteCount = bytes.Length - byteIndex;
@@ -184,16 +189,16 @@ namespace System.Text
{
// Validate parameters
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
// If nothing to encode return 0, avoid fixed problem
if (charCount == 0)
@@ -216,10 +221,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetBytes(chars, charCount, bytes, byteCount, null);
}
@@ -236,13 +241,13 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input just return 0, fixed doesn't like 0 length arrays
if (count == 0)
@@ -262,10 +267,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetCharCount(bytes, count, null);
}
@@ -280,16 +285,16 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if ( bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (charIndex < 0 || charIndex > chars.Length)
- throw new ArgumentOutOfRangeException("charIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index);
// If no input, return 0 & avoid fixed problem
if (byteCount == 0)
@@ -312,10 +317,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetChars(bytes, byteCount, chars, charCount, null);
}
@@ -332,19 +337,19 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// Avoid problems with empty input buffer
- if (count == 0) return String.Empty;
+ if (count == 0) return string.Empty;
fixed (byte* pBytes = bytes)
- return String.CreateStringFromEncoding(
+ return string.CreateStringFromEncoding(
pBytes + index, count, this);
}
@@ -352,7 +357,7 @@ namespace System.Text
// End of standard methods copied from EncodingNLS.cs
//
- internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS encoder)
+ internal sealed override unsafe int GetByteCount(char* chars, int count, EncoderNLS encoder)
{
Debug.Assert(chars != null, "[UnicodeEncoding.GetByteCount]chars!=null");
Debug.Assert(count >= 0, "[UnicodeEncoding.GetByteCount]count >=0");
@@ -372,11 +377,6 @@ namespace System.Text
bool wasHereBefore = false;
- // Need -1 to check 2 at a time. If we have an even #, longChars will go
- // from longEnd - 1/2 long to longEnd + 1/2 long. If we're odd, longChars
- // will go from longEnd - 1 long to longEnd. (Might not get to use this)
- ulong* longEnd = (ulong*)(charEnd - 3);
-
// For fallback we may need a fallback buffer
EncoderFallbackBuffer fallbackBuffer = null;
char* charsForFallback;
@@ -410,19 +410,21 @@ namespace System.Text
if (ch == 0)
{
// No fallback, maybe we can do it fast
-#if !NO_FAST_UNICODE_LOOP
-#if BIGENDIAN // If endianess is backwards then each pair of bytes would be backwards.
- if ( bigEndian &&
-#else
- if (!bigEndian &&
-#endif // BIGENDIAN
-
-#if BIT64 // 64 bit CPU needs to be long aligned for this to work.
- charLeftOver == 0 && (unchecked((long)chars) & 7) == 0)
+#if FASTLOOP
+ // If endianess is backwards then each pair of bytes would be backwards.
+ if ( (bigEndian ^ BitConverter.IsLittleEndian) &&
+#if BIT64
+ (unchecked((long)chars) & 7) == 0 &&
#else
- charLeftOver == 0 && (unchecked((int)chars) & 3) == 0)
+ (unchecked((int)chars) & 3) == 0 &&
#endif
+ charLeftOver == 0)
{
+ // Need -1 to check 2 at a time. If we have an even #, longChars will go
+ // from longEnd - 1/2 long to longEnd + 1/2 long. If we're odd, longChars
+ // will go from longEnd - 1 long to longEnd. (Might not get to use this)
+ ulong* longEnd = (ulong*)(charEnd - 3);
+
// Need new char* so we can check 4 at a time
ulong* longChars = (ulong*)chars;
@@ -453,11 +455,8 @@ namespace System.Text
// If they happen to be high/low/high/low, we may as well continue. Check the next
// bit to see if its set (low) or not (high) in the right pattern
-#if BIGENDIAN
- if (((0xfc00fc00fc00fc00 & *longChars) ^ 0xd800dc00d800dc00) != 0)
-#else
- if (((0xfc00fc00fc00fc00 & *longChars) ^ 0xdc00d800dc00d800) != 0)
-#endif
+ if ((0xfc00fc00fc00fc00 & *longChars) !=
+ (BitConverter.IsLittleEndian ? (ulong)0xdc00d800dc00d800 : (ulong)0xd800dc00d800dc00))
{
// Either there weren't 4 surrogates, or the 0x0400 bit was set when a high
// was hoped for or the 0x0400 bit wasn't set where a low was hoped for.
@@ -480,7 +479,7 @@ namespace System.Text
if (chars >= charEnd)
break;
}
-#endif // !NO_FAST_UNICODE_LOOP
+#endif // FASTLOOP
// No fallback, just get next char
ch = *chars;
@@ -651,8 +650,8 @@ namespace System.Text
return byteCount;
}
- internal override unsafe int GetBytes(char* chars, int charCount,
- byte* bytes, int byteCount, EncoderNLS encoder)
+ internal sealed override unsafe int GetBytes(
+ char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS encoder)
{
Debug.Assert(chars != null, "[UnicodeEncoding.GetBytes]chars!=null");
Debug.Assert(byteCount >= 0, "[UnicodeEncoding.GetBytes]byteCount >=0");
@@ -700,17 +699,14 @@ namespace System.Text
if (ch == 0)
{
// No fallback, maybe we can do it fast
-#if !NO_FAST_UNICODE_LOOP
-#if BIGENDIAN // If endianess is backwards then each pair of bytes would be backwards.
- if ( bigEndian &&
-#else
- if (!bigEndian &&
-#endif // BIGENDIAN
-#if BIT64 // 64 bit CPU needs to be long aligned for this to work, 32 bit CPU needs to be 32 bit aligned
- (unchecked((long)chars) & 7) == 0 && (unchecked((long)bytes) & 7) == 0 &&
+#if FASTLOOP
+ // If endianess is backwards then each pair of bytes would be backwards.
+ if ( (bigEndian ^ BitConverter.IsLittleEndian) &&
+#if BIT64
+ (unchecked((long)chars) & 7) == 0 &&
#else
- (unchecked((int)chars) & 3) == 0 && (unchecked((int)bytes) & 3) == 0 &&
-#endif // BIT64
+ (unchecked((int)chars) & 3) == 0 &&
+#endif
charLeftOver == 0)
{
// Need -1 to check 2 at a time. If we have an even #, longChars will go
@@ -752,11 +748,8 @@ namespace System.Text
// If they happen to be high/low/high/low, we may as well continue. Check the next
// bit to see if its set (low) or not (high) in the right pattern
-#if BIGENDIAN
- if (((0xfc00fc00fc00fc00 & *longChars) ^ 0xd800dc00d800dc00) != 0)
-#else
- if (((0xfc00fc00fc00fc00 & *longChars) ^ 0xdc00d800dc00d800) != 0)
-#endif
+ if ((0xfc00fc00fc00fc00 & *longChars) !=
+ (BitConverter.IsLittleEndian ? (ulong)0xdc00d800dc00d800 : (ulong)0xd800dc00d800dc00))
{
// Either there weren't 4 surrogates, or the 0x0400 bit was set when a high
// was hoped for or the 0x0400 bit wasn't set where a low was hoped for.
@@ -771,7 +764,7 @@ namespace System.Text
// else all < 0x8000 so we can use them
// We can use these 4 chars.
- *longBytes = *longChars;
+ Unsafe.WriteUnaligned<ulong>(longBytes, *longChars);
longChars++;
longBytes++;
}
@@ -782,66 +775,7 @@ namespace System.Text
if (chars >= charEnd)
break;
}
- // Not aligned, but maybe we can still be somewhat faster
- // Also somehow this optimizes the above loop? It seems to cause something above
- // to get enregistered, but I haven't figured out how to make that happen without this loop.
- else if ((charLeftOver == 0) &&
-#if BIGENDIAN
- bigEndian &&
-#else
- !bigEndian &&
-#endif // BIGENDIAN
-
-#if BIT64
- (unchecked((long)chars) & 7) != (unchecked((long)bytes) & 7) && // Only do this if chars & bytes are out of line, otherwise faster loop will be faster next time
-#else
- (unchecked((int)chars) & 3) != (unchecked((int)bytes) & 3) && // Only do this if chars & bytes are out of line, otherwise faster loop will be faster next time
-#endif // BIT64
- (unchecked((int)(bytes)) & 1) == 0)
- {
- // # to use
- long iCount = ((byteEnd - bytes) >> 1 < charEnd - chars) ?
- (byteEnd - bytes) >> 1 : charEnd - chars;
-
- // Need new char*
- char* charOut = ((char*)bytes); // a char* for our output
- char* tempEnd = chars + iCount - 1; // Our end pointer
-
- while (chars < tempEnd)
- {
- if (*chars >= (char)0xd800 && *chars <= (char)0xdfff)
- {
- // break for fallback for low surrogate
- if (*chars >= 0xdc00)
- break;
-
- // break if next one's not a low surrogate (will do fallback)
- if (*(chars + 1) < 0xdc00 || *(chars + 1) > 0xdfff)
- break;
-
- // They both exist, use them
- }
- // If 2nd char is surrogate & this one isn't then only add one
- else if (*(chars + 1) >= (char)0xd800 && *(chars + 1) <= 0xdfff)
- {
- *charOut = *chars;
- charOut++;
- chars++;
- continue;
- }
-
- *charOut = *chars;
- *(charOut + 1) = *(chars + 1);
- charOut += 2;
- chars += 2;
- }
-
- bytes = (byte*)charOut;
-
- if (chars >= charEnd)
- break;
- }
-#endif // !NO_FAST_UNICODE_LOOP
+#endif // FASTLOOP
// No fallback, just get next char
ch = *chars;
@@ -1070,13 +1004,10 @@ namespace System.Text
encoder == null || !encoder._throwOnOverflow,
"[UnicodeEncoding.GetBytes]Expected empty fallback buffer if not converting");
- // We used to copy it fast, but this doesn't check for surrogates
- // System.IO.__UnmanagedMemoryStream.memcpyimpl(bytes, (byte*)chars, usedByteCount);
-
return (int)(bytes - byteStart);
}
- internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
+ internal sealed override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
{
Debug.Assert(bytes != null, "[UnicodeEncoding.GetCharCount]bytes!=null");
Debug.Assert(count >= 0, "[UnicodeEncoding.GetCharCount]count >=0");
@@ -1093,11 +1024,6 @@ namespace System.Text
// Start by assuming same # of chars as bytes
int charCount = count >> 1;
- // Need -1 to check 2 at a time. If we have an even #, longBytes will go
- // from longEnd - 1/2 long to longEnd + 1/2 long. If we're odd, longBytes
- // will go from longEnd - 1 long to longEnd. (Might not get to use this)
- ulong* longEnd = (ulong*)(byteEnd - 7);
-
// For fallback we may need a fallback buffer
DecoderFallbackBuffer fallbackBuffer = null;
@@ -1126,19 +1052,20 @@ namespace System.Text
{
// If we're aligned then maybe we can do it fast
// That'll hurt if we're unaligned because we'll always test but never be aligned
-#if !NO_FAST_UNICODE_LOOP
-#if BIGENDIAN
- if (bigEndian &&
-#else // BIGENDIAN
- if (!bigEndian &&
-#endif // BIGENDIAN
-#if BIT64 // win64 has to be long aligned
+#if FASTLOOP
+ if ((bigEndian ^ BitConverter.IsLittleEndian) &&
+#if BIT64
(unchecked((long)bytes) & 7) == 0 &&
#else
(unchecked((int)bytes) & 3) == 0 &&
#endif // BIT64
lastByte == -1 && lastChar == 0)
{
+ // Need -1 to check 2 at a time. If we have an even #, longBytes will go
+ // from longEnd - 1/2 long to longEnd + 1/2 long. If we're odd, longBytes
+ // will go from longEnd - 1 long to longEnd. (Might not get to use this)
+ ulong* longEnd = (ulong*)(byteEnd - 7);
+
// Need new char* so we can check 4 at a time
ulong* longBytes = (ulong*)bytes;
@@ -1169,11 +1096,8 @@ namespace System.Text
// If they happen to be high/low/high/low, we may as well continue. Check the next
// bit to see if its set (low) or not (high) in the right pattern
-#if BIGENDIAN
- if (((0xfc00fc00fc00fc00 & *longBytes) ^ 0xd800dc00d800dc00) != 0)
-#else
- if (((0xfc00fc00fc00fc00 & *longBytes) ^ 0xdc00d800dc00d800) != 0)
-#endif
+ if ((0xfc00fc00fc00fc00 & *longBytes) !=
+ (BitConverter.IsLittleEndian ? (ulong)0xdc00d800dc00d800 : (ulong)0xd800dc00d800dc00))
{
// Either there weren't 4 surrogates, or the 0x0400 bit was set when a high
// was hoped for or the 0x0400 bit wasn't set where a low was hoped for.
@@ -1196,7 +1120,7 @@ namespace System.Text
if (bytes >= byteEnd)
break;
}
-#endif // !NO_FAST_UNICODE_LOOP
+#endif // FASTLOOP
// Get 1st byte
if (lastByte < 0)
@@ -1410,8 +1334,8 @@ namespace System.Text
return charCount;
}
- internal override unsafe int GetChars(byte* bytes, int byteCount,
- char* chars, int charCount, DecoderNLS baseDecoder)
+ internal sealed override unsafe int GetChars(
+ byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder)
{
Debug.Assert(chars != null, "[UnicodeEncoding.GetChars]chars!=null");
Debug.Assert(byteCount >= 0, "[UnicodeEncoding.GetChars]byteCount >=0");
@@ -1449,17 +1373,13 @@ namespace System.Text
{
// If we're aligned then maybe we can do it fast
// That'll hurt if we're unaligned because we'll always test but never be aligned
-#if !NO_FAST_UNICODE_LOOP
-#if BIGENDIAN
- if (bigEndian &&
-#else // BIGENDIAN
- if (!bigEndian &&
-#endif // BIGENDIAN
-#if BIT64 // win64 has to be long aligned
- (unchecked((long)chars) & 7) == 0 && (unchecked((long)bytes) & 7) == 0 &&
+#if FASTLOOP
+ if ((bigEndian ^ BitConverter.IsLittleEndian) &&
+#if BIT64
+ (unchecked((long)chars) & 7) == 0 &&
#else
- (unchecked((int)chars) & 3) == 0 && (unchecked((int)bytes) & 3) == 0 &&
-#endif // BIT64
+ (unchecked((int)chars) & 3) == 0 &&
+#endif
lastByte == -1 && lastChar == 0)
{
// Need -1 to check 2 at a time. If we have an even #, longChars will go
@@ -1501,11 +1421,8 @@ namespace System.Text
// If they happen to be high/low/high/low, we may as well continue. Check the next
// bit to see if its set (low) or not (high) in the right pattern
-#if BIGENDIAN
- if (((0xfc00fc00fc00fc00 & *longBytes) ^ 0xd800dc00d800dc00) != 0)
-#else
- if (((0xfc00fc00fc00fc00 & *longBytes) ^ 0xdc00d800dc00d800) != 0)
-#endif
+ if ((0xfc00fc00fc00fc00 & *longBytes) !=
+ (BitConverter.IsLittleEndian ? (ulong)0xdc00d800dc00d800 : (ulong)0xd800dc00d800dc00))
{
// Either there weren't 4 surrogates, or the 0x0400 bit was set when a high
// was hoped for or the 0x0400 bit wasn't set where a low was hoped for.
@@ -1520,7 +1437,7 @@ namespace System.Text
// else all < 0x8000 so we can use them
// We can use these 4 chars.
- *longChars = *longBytes;
+ Unsafe.WriteUnaligned<ulong>(longChars, *longBytes);
longBytes++;
longChars++;
}
@@ -1531,7 +1448,7 @@ namespace System.Text
if (bytes >= byteEnd)
break;
}
-#endif // !NO_FAST_UNICODE_LOOP
+#endif // FASTLOOP
// Get 1st byte
if (lastByte < 0)
@@ -1840,9 +1757,6 @@ namespace System.Text
decoder.lastByte = lastByte;
}
- // Used to do this the old way
- // System.IO.__UnmanagedMemoryStream.memcpyimpl((byte*)chars, bytes, byteCount);
-
// Shouldn't have anything in fallback buffer for GetChars
// (don't have to check _throwOnOverflow for count or chars)
Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
@@ -1875,7 +1789,7 @@ namespace System.Text
else
return new byte[2] { 0xff, 0xfe };
}
- return Array.Empty<Byte>();
+ return Array.Empty<byte>();
}
public override ReadOnlySpan<byte> Preamble =>
@@ -1928,7 +1842,7 @@ namespace System.Text
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
UnicodeEncoding that = value as UnicodeEncoding;
if (that != null)
diff --git a/src/System.Private.CoreLib/shared/System/Text/ValueStringBuilder.cs b/src/System.Private.CoreLib/shared/System/Text/ValueStringBuilder.cs
index 18d564867..74b5dacf9 100644
--- a/src/System.Private.CoreLib/shared/System/Text/ValueStringBuilder.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/ValueStringBuilder.cs
@@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
namespace System.Text
{
- internal ref struct ValueStringBuilder
+ internal ref partial struct ValueStringBuilder
{
private char[] _arrayToReturnToPool;
private Span<char> _chars;
@@ -22,11 +22,19 @@ namespace System.Text
_pos = 0;
}
+ public ValueStringBuilder(int initialCapacity)
+ {
+ _arrayToReturnToPool = ArrayPool<char>.Shared.Rent(initialCapacity);
+ _chars = _arrayToReturnToPool;
+ _pos = 0;
+ }
+
public int Length
{
get => _pos;
set
{
+ Debug.Assert(value >= 0);
Debug.Assert(value <= _chars.Length);
_pos = value;
}
@@ -40,7 +48,30 @@ namespace System.Text
Grow(capacity - _chars.Length);
}
- public ref char GetPinnableReference() => ref MemoryMarshal.GetReference(_chars);
+ /// <summary>
+ /// Get a pinnable reference to the builder.
+ /// Does not ensure there is a null char after <see cref="Length"/>
+ /// This overload is pattern matched in the C# 7.3+ compiler so you can omit
+ /// the explicit method call, and write eg "fixed (char* c = builder)"
+ /// </summary>
+ public ref char GetPinnableReference()
+ {
+ return ref MemoryMarshal.GetReference(_chars);
+ }
+
+ /// <summary>
+ /// Get a pinnable reference to the builder.
+ /// </summary>
+ /// <param name="terminate">Ensures that the builder has a null char after <see cref="Length"/></param>
+ public ref char GetPinnableReference(bool terminate)
+ {
+ if (terminate)
+ {
+ EnsureCapacity(Length + 1);
+ _chars[Length] = '\0';
+ }
+ return ref MemoryMarshal.GetReference(_chars);
+ }
public ref char this[int index]
{
@@ -53,12 +84,31 @@ namespace System.Text
public override string ToString()
{
- var s = new string(_chars.Slice(0, _pos));
+ var s = _chars.Slice(0, _pos).ToString();
Dispose();
return s;
}
+ /// <summary>Returns the underlying storage of the builder.</summary>
+ public Span<char> RawChars => _chars;
+
+ /// <summary>
+ /// Returns a span around the contents of the builder.
+ /// </summary>
+ /// <param name="terminate">Ensures that the builder has a null char after <see cref="Length"/></param>
+ public ReadOnlySpan<char> AsSpan(bool terminate)
+ {
+ if (terminate)
+ {
+ EnsureCapacity(Length + 1);
+ _chars[Length] = '\0';
+ }
+ return _chars.Slice(0, _pos);
+ }
+
public ReadOnlySpan<char> AsSpan() => _chars.Slice(0, _pos);
+ public ReadOnlySpan<char> AsSpan(int start) => _chars.Slice(start, _pos - start);
+ public ReadOnlySpan<char> AsSpan(int start, int length) => _chars.Slice(start, length);
public bool TryCopyTo(Span<char> destination, out int charsWritten)
{
@@ -93,7 +143,7 @@ namespace System.Text
public void Append(char c)
{
int pos = _pos;
- if (pos < _chars.Length)
+ if ((uint)pos < (uint)_chars.Length)
{
_chars[pos] = c;
_pos = pos + 1;
@@ -108,7 +158,7 @@ namespace System.Text
public void Append(string s)
{
int pos = _pos;
- if (s.Length == 1 && pos < _chars.Length) // very common case, e.g. appending strings from NumberFormatInfo like separators, percent symbols, etc.
+ if (s.Length == 1 && (uint)pos < (uint)_chars.Length) // very common case, e.g. appending strings from NumberFormatInfo like separators, percent symbols, etc.
{
_chars[pos] = s[0];
_pos = pos + 1;
diff --git a/src/System.Private.CoreLib/shared/System/Threading/AbandonedMutexException.cs b/src/System.Private.CoreLib/shared/System/Threading/AbandonedMutexException.cs
index c7e604f33..bd504dd27 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/AbandonedMutexException.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/AbandonedMutexException.cs
@@ -27,13 +27,13 @@ namespace System.Threading
HResult = HResults.COR_E_ABANDONEDMUTEX;
}
- public AbandonedMutexException(String message)
+ public AbandonedMutexException(string message)
: base(message)
{
HResult = HResults.COR_E_ABANDONEDMUTEX;
}
- public AbandonedMutexException(String message, Exception inner)
+ public AbandonedMutexException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_ABANDONEDMUTEX;
@@ -46,14 +46,14 @@ namespace System.Threading
SetupException(location, handle);
}
- public AbandonedMutexException(String message, int location, WaitHandle handle)
+ public AbandonedMutexException(string message, int location, WaitHandle handle)
: base(message)
{
HResult = HResults.COR_E_ABANDONEDMUTEX;
SetupException(location, handle);
}
- public AbandonedMutexException(String message, Exception inner, int location, WaitHandle handle)
+ public AbandonedMutexException(string message, Exception inner, int location, WaitHandle handle)
: base(message, inner)
{
HResult = HResults.COR_E_ABANDONEDMUTEX;
diff --git a/src/System.Private.CoreLib/shared/System/Threading/AsyncLocal.cs b/src/System.Private.CoreLib/shared/System/Threading/AsyncLocal.cs
index 3531265be..12d650243 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/AsyncLocal.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/AsyncLocal.cs
@@ -61,7 +61,7 @@ namespace System.Threading
get
{
object obj = ExecutionContext.GetLocalValue(this);
- return (obj == null) ? default(T) : (T)obj;
+ return (obj == null) ? default : (T)obj;
}
set
{
@@ -72,8 +72,8 @@ namespace System.Threading
void IAsyncLocal.OnValueChanged(object previousValueObj, object currentValueObj, bool contextChanged)
{
Debug.Assert(m_valueChangedHandler != null);
- T previousValue = previousValueObj == null ? default(T) : (T)previousValueObj;
- T currentValue = currentValueObj == null ? default(T) : (T)currentValueObj;
+ T previousValue = previousValueObj == null ? default : (T)previousValueObj;
+ T currentValue = currentValueObj == null ? default : (T)currentValueObj;
m_valueChangedHandler(new AsyncLocalValueChangedArgs<T>(previousValue, currentValue, contextChanged));
}
}
@@ -86,19 +86,18 @@ namespace System.Threading
void OnValueChanged(object previousValue, object currentValue, bool contextChanged);
}
- public struct AsyncLocalValueChangedArgs<T>
+ public readonly struct AsyncLocalValueChangedArgs<T>
{
- public T PreviousValue { get; private set; }
- public T CurrentValue { get; private set; }
+ public T PreviousValue { get; }
+ public T CurrentValue { get; }
//
// If the value changed because we changed to a different ExecutionContext, this is true. If it changed
// because someone set the Value property, this is false.
//
- public bool ThreadContextChanged { get; private set; }
+ public bool ThreadContextChanged { get; }
internal AsyncLocalValueChangedArgs(T previousValue, T currentValue, bool contextChanged)
- : this()
{
PreviousValue = previousValue;
CurrentValue = currentValue;
@@ -114,7 +113,7 @@ namespace System.Threading
internal interface IAsyncLocalValueMap
{
bool TryGetValue(IAsyncLocal key, out object value);
- IAsyncLocalValueMap Set(IAsyncLocal key, object value);
+ IAsyncLocalValueMap Set(IAsyncLocal key, object value, bool treatNullValueAsNonexistent);
}
//
@@ -124,14 +123,31 @@ namespace System.Threading
{
public static IAsyncLocalValueMap Empty { get; } = new EmptyAsyncLocalValueMap();
+ public static bool IsEmpty(IAsyncLocalValueMap asyncLocalValueMap)
+ {
+ Debug.Assert(asyncLocalValueMap != null);
+ Debug.Assert(asyncLocalValueMap == Empty || asyncLocalValueMap.GetType() != typeof(EmptyAsyncLocalValueMap));
+
+ return asyncLocalValueMap == Empty;
+ }
+
+ public static IAsyncLocalValueMap Create(IAsyncLocal key, object value, bool treatNullValueAsNonexistent)
+ {
+ // If the value isn't null or a null value may not be treated as nonexistent, then create a new one-element map
+ // to store the key/value pair. Otherwise, use the empty map.
+ return value != null || !treatNullValueAsNonexistent ?
+ new OneElementAsyncLocalValueMap(key, value) :
+ Empty;
+ }
+
// Instance without any key/value pairs. Used as a singleton/
- internal sealed class EmptyAsyncLocalValueMap : IAsyncLocalValueMap
+ private sealed class EmptyAsyncLocalValueMap : IAsyncLocalValueMap
{
- public IAsyncLocalValueMap Set(IAsyncLocal key, object value)
+ public IAsyncLocalValueMap Set(IAsyncLocal key, object value, bool treatNullValueAsNonexistent)
{
- // If the value isn't null, then create a new one-element map to store
- // the key/value pair. If it is null, then we're still empty.
- return value != null ?
+ // If the value isn't null or a null value may not be treated as nonexistent, then create a new one-element map
+ // to store the key/value pair. Otherwise, use the empty map.
+ return value != null || !treatNullValueAsNonexistent ?
new OneElementAsyncLocalValueMap(key, value) :
(IAsyncLocalValueMap)this;
}
@@ -144,7 +160,7 @@ namespace System.Threading
}
// Instance with one key/value pair.
- internal sealed class OneElementAsyncLocalValueMap : IAsyncLocalValueMap
+ private sealed class OneElementAsyncLocalValueMap : IAsyncLocalValueMap
{
private readonly IAsyncLocal _key1;
private readonly object _value1;
@@ -154,21 +170,20 @@ namespace System.Threading
_key1 = key; _value1 = value;
}
- public IAsyncLocalValueMap Set(IAsyncLocal key, object value)
+ public IAsyncLocalValueMap Set(IAsyncLocal key, object value, bool treatNullValueAsNonexistent)
{
- if (value != null)
+ if (value != null || !treatNullValueAsNonexistent)
{
- // The value is non-null. If the key matches one already contained in this map,
- // then create a new one-element map with the updated value, otherwise create
- // a two-element map with the additional key/value.
+ // If the key matches one already contained in this map, then create a new one-element map with the updated
+ // value, otherwise create a two-element map with the additional key/value.
return ReferenceEquals(key, _key1) ?
new OneElementAsyncLocalValueMap(key, value) :
(IAsyncLocalValueMap)new TwoElementAsyncLocalValueMap(_key1, _value1, key, value);
}
else
{
- // The value is null. If the key exists in this map, remove it by downgrading to an empty map.
- // Otherwise, there's nothing to add or remove, so just return this map.
+ // If the key exists in this map, remove it by downgrading to an empty map. Otherwise, there's nothing to
+ // add or remove, so just return this map.
return ReferenceEquals(key, _key1) ?
Empty :
(IAsyncLocalValueMap)this;
@@ -202,13 +217,12 @@ namespace System.Threading
_key2 = key2; _value2 = value2;
}
- public IAsyncLocalValueMap Set(IAsyncLocal key, object value)
+ public IAsyncLocalValueMap Set(IAsyncLocal key, object value, bool treatNullValueAsNonexistent)
{
- if (value != null)
+ if (value != null || !treatNullValueAsNonexistent)
{
- // The value is non-null. If the key matches one already contained in this map,
- // then create a new two-element map with the updated value, otherwise create
- // a three-element map with the additional key/value.
+ // If the key matches one already contained in this map, then create a new two-element map with the updated
+ // value, otherwise create a three-element map with the additional key/value.
return
ReferenceEquals(key, _key1) ? new TwoElementAsyncLocalValueMap(key, value, _key2, _value2) :
ReferenceEquals(key, _key2) ? new TwoElementAsyncLocalValueMap(_key1, _value1, key, value) :
@@ -216,8 +230,8 @@ namespace System.Threading
}
else
{
- // The value is null. If the key exists in this map, remove it by downgrading to a one-element map
- // without the key. Otherwise, there's nothing to add or remove, so just return this map.
+ // If the key exists in this map, remove it by downgrading to a one-element map without the key. Otherwise,
+ // there's nothing to add or remove, so just return this map.
return
ReferenceEquals(key, _key1) ? new OneElementAsyncLocalValueMap(_key2, _value2) :
ReferenceEquals(key, _key2) ? new OneElementAsyncLocalValueMap(_key1, _value1) :
@@ -258,12 +272,12 @@ namespace System.Threading
_key3 = key3; _value3 = value3;
}
- public IAsyncLocalValueMap Set(IAsyncLocal key, object value)
+ public IAsyncLocalValueMap Set(IAsyncLocal key, object value, bool treatNullValueAsNonexistent)
{
- if (value != null)
+ if (value != null || !treatNullValueAsNonexistent)
{
- // The value is non-null. If the key matches one already contained in this map,
- // then create a new three-element map with the updated value.
+ // If the key matches one already contained in this map, then create a new three-element map with the
+ // updated value.
if (ReferenceEquals(key, _key1)) return new ThreeElementAsyncLocalValueMap(key, value, _key2, _value2, _key3, _value3);
if (ReferenceEquals(key, _key2)) return new ThreeElementAsyncLocalValueMap(_key1, _value1, key, value, _key3, _value3);
if (ReferenceEquals(key, _key3)) return new ThreeElementAsyncLocalValueMap(_key1, _value1, _key2, _value2, key, value);
@@ -279,8 +293,8 @@ namespace System.Threading
}
else
{
- // The value is null. If the key exists in this map, remove it by downgrading to a two-element map
- // without the key. Otherwise, there's nothing to add or remove, so just return this map.
+ // If the key exists in this map, remove it by downgrading to a two-element map without the key. Otherwise,
+ // there's nothing to add or remove, so just return this map.
return
ReferenceEquals(key, _key1) ? new TwoElementAsyncLocalValueMap(_key2, _value2, _key3, _value3) :
ReferenceEquals(key, _key2) ? new TwoElementAsyncLocalValueMap(_key1, _value1, _key3, _value3) :
@@ -332,17 +346,18 @@ namespace System.Threading
_keyValues[index] = new KeyValuePair<IAsyncLocal, object>(key, value);
}
- public IAsyncLocalValueMap Set(IAsyncLocal key, object value)
+ public IAsyncLocalValueMap Set(IAsyncLocal key, object value, bool treatNullValueAsNonexistent)
{
// Find the key in this map.
for (int i = 0; i < _keyValues.Length; i++)
{
if (ReferenceEquals(key, _keyValues[i].Key))
{
- // The key is in the map. If the value isn't null, then create a new map of the same
- // size that has all of the same pairs, with this new key/value pair overwriting the old.
- if (value != null)
+ // The key is in the map.
+ if (value != null || !treatNullValueAsNonexistent)
{
+ // Create a new map of the same size that has all of the same pairs, with this new key/value pair
+ // overwriting the old.
var multi = new MultiElementAsyncLocalValueMap(_keyValues.Length);
Array.Copy(_keyValues, 0, multi._keyValues, 0, _keyValues.Length);
multi._keyValues[i] = new KeyValuePair<IAsyncLocal, object>(key, value);
@@ -350,8 +365,8 @@ namespace System.Threading
}
else if (_keyValues.Length == 4)
{
- // The value is null, and we only have four elements, one of which we're removing,
- // so downgrade to a three-element map, without the matching element.
+ // We only have four elements, one of which we're removing, so downgrade to a three-element map,
+ // without the matching element.
return
i == 0 ? new ThreeElementAsyncLocalValueMap(_keyValues[1].Key, _keyValues[1].Value, _keyValues[2].Key, _keyValues[2].Value, _keyValues[3].Key, _keyValues[3].Value) :
i == 1 ? new ThreeElementAsyncLocalValueMap(_keyValues[0].Key, _keyValues[0].Value, _keyValues[2].Key, _keyValues[2].Value, _keyValues[3].Key, _keyValues[3].Value) :
@@ -360,8 +375,8 @@ namespace System.Threading
}
else
{
- // The value is null, and we have enough elements remaining to warrant a multi map.
- // Create a new one and copy all of the elements from this one, except the one to be removed.
+ // We have enough elements remaining to warrant a multi map. Create a new one and copy all of the
+ // elements from this one, except the one to be removed.
var multi = new MultiElementAsyncLocalValueMap(_keyValues.Length - 1);
if (i != 0) Array.Copy(_keyValues, 0, multi._keyValues, 0, i);
if (i != _keyValues.Length - 1) Array.Copy(_keyValues, i + 1, multi._keyValues, i, _keyValues.Length - i - 1);
@@ -372,9 +387,9 @@ namespace System.Threading
// The key does not already exist in this map.
- // If the value is null, then we can simply return this same map, as there's nothing to add or remove.
- if (value == null)
+ if (value == null && treatNullValueAsNonexistent)
{
+ // We can simply return this same map, as there's nothing to add or remove.
return this;
}
@@ -418,14 +433,14 @@ namespace System.Threading
{
public ManyElementAsyncLocalValueMap(int capacity) : base(capacity) { }
- public IAsyncLocalValueMap Set(IAsyncLocal key, object value)
+ public IAsyncLocalValueMap Set(IAsyncLocal key, object value, bool treatNullValueAsNonexistent)
{
int count = Count;
bool containsKey = ContainsKey(key);
// If the value being set exists, create a new many map, copy all of the elements from this one,
// and then store the new key/value pair into it. This is the most common case.
- if (value != null)
+ if (value != null || !treatNullValueAsNonexistent)
{
var map = new ManyElementAsyncLocalValueMap(count + (containsKey ? 0 : 1));
foreach (KeyValuePair<IAsyncLocal, object> pair in this)
@@ -436,15 +451,14 @@ namespace System.Threading
return map;
}
- // Otherwise, the value is null, which means null is being stored into an AsyncLocal.Value.
- // Since there's no observable difference at the API level between storing null and the key
- // not existing at all, we can downgrade to a smaller map rather than storing null.
+ // Otherwise, the value is null and a null value may be treated as nonexistent. We can downgrade to a smaller
+ // map rather than storing null.
// If the key is contained in this map, we're going to create a new map that's one pair smaller.
if (containsKey)
{
// If the new count would be within range of a multi map instead of a many map,
- // downgrade to the many map, which uses less memory and is faster to access.
+ // downgrade to the multi map, which uses less memory and is faster to access.
// Otherwise, just create a new many map that's missing this key.
if (count == MultiElementAsyncLocalValueMap.MaxMultiElements + 1)
{
@@ -475,8 +489,8 @@ namespace System.Threading
}
}
- // We were storing null, but the key wasn't in the map, so there's nothing to change.
- // Just return this instance.
+ // We were storing null and a null value may be treated as nonexistent, but the key wasn't in the map, so
+ // there's nothing to change. Just return this instance.
return this;
}
}
diff --git a/src/System.Private.CoreLib/src/System/Threading/CancellationToken.cs b/src/System.Private.CoreLib/shared/System/Threading/CancellationToken.cs
index e3495aeb4..68e6971a5 100644
--- a/src/System.Private.CoreLib/src/System/Threading/CancellationToken.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/CancellationToken.cs
@@ -2,15 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-//
-
-////////////////////////////////////////////////////////////////////////////////
-
-#pragma warning disable 0420 // turn off 'a reference to a volatile field will not be treated as volatile' during CAS.
-
-
using System.Diagnostics;
-using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
namespace System.Threading
@@ -41,10 +33,10 @@ namespace System.Threading
// The backing TokenSource.
// if null, it implicitly represents the same thing as new CancellationToken(false).
// When required, it will be instantiated to reflect this.
- private readonly CancellationTokenSource m_source;
+ private readonly CancellationTokenSource _source;
//!! warning. If more fields are added, the assumptions in CreateLinkedToken may no longer be valid
- /* Properties */
+ private readonly static Action<object> s_actionToActionObjShunt = obj => ((Action)obj)();
/// <summary>
/// Returns an empty CancellationToken value.
@@ -52,10 +44,7 @@ namespace System.Threading
/// <remarks>
/// The <see cref="CancellationToken"/> value returned by this property will be non-cancelable by default.
/// </remarks>
- public static CancellationToken None
- {
- get { return default(CancellationToken); }
- }
+ public static CancellationToken None => default;
/// <summary>
/// Gets whether cancellation has been requested for this token.
@@ -64,7 +53,7 @@ namespace System.Threading
/// <remarks>
/// <para>
/// This property indicates whether cancellation has been requested for this token,
- /// either through the token initially being construted in a canceled state, or through
+ /// either through the token initially being constructed in a canceled state, or through
/// calling <see cref="System.Threading.CancellationTokenSource.Cancel()">Cancel</see>
/// on the token's associated <see cref="CancellationTokenSource"/>.
/// </para>
@@ -76,13 +65,7 @@ namespace System.Threading
/// particularly in situations where related objects are being canceled concurrently.
/// </para>
/// </remarks>
- public bool IsCancellationRequested
- {
- get
- {
- return m_source != null && m_source.IsCancellationRequested;
- }
- }
+ public bool IsCancellationRequested => _source != null && _source.IsCancellationRequested;
/// <summary>
/// Gets whether this token is capable of being in the canceled state.
@@ -92,13 +75,7 @@ namespace System.Threading
/// into a canceled state, meaning that <see cref="IsCancellationRequested"/> will never
/// return true.
/// </remarks>
- public bool CanBeCanceled
- {
- get
- {
- return m_source != null && m_source.CanBeCanceled;
- }
- }
+ public bool CanBeCanceled => _source != null;
/// <summary>
/// Gets a <see cref="T:System.Threading.WaitHandle"/> that is signaled when the token is canceled.</summary>
@@ -110,7 +87,7 @@ namespace System.Threading
/// </remarks>
/// <exception cref="T:System.ObjectDisposedException">The associated <see
/// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
- public WaitHandle WaitHandle => (m_source ?? CancellationTokenSource.InternalGetStaticSource(false)).WaitHandle;
+ public WaitHandle WaitHandle => (_source ?? CancellationTokenSource.s_neverCanceledSource).WaitHandle;
// public CancellationToken()
// this constructor is implicit for structs
@@ -119,10 +96,7 @@ namespace System.Threading
/// <summary>
/// Internal constructor only a CancellationTokenSource should create a CancellationToken
/// </summary>
- internal CancellationToken(CancellationTokenSource source)
- {
- m_source = source;
- }
+ internal CancellationToken(CancellationTokenSource source) => _source = source;
/// <summary>
/// Initializes the <see cref="T:System.Threading.CancellationToken">CancellationToken</see>.
@@ -137,22 +111,8 @@ namespace System.Threading
/// If <paramref name="canceled"/> is true,
/// both <see cref="CanBeCanceled"/> and <see cref="IsCancellationRequested"/> will be true.
/// </remarks>
- public CancellationToken(bool canceled) :
- this()
+ public CancellationToken(bool canceled) : this(canceled ? CancellationTokenSource.s_canceledSource : null)
{
- if (canceled)
- m_source = CancellationTokenSource.InternalGetStaticSource(canceled);
- }
-
- /* Methods */
-
-
- private static readonly Action<Object> s_ActionToActionObjShunt = new Action<Object>(ActionToActionObjShunt);
- private static void ActionToActionObjShunt(object obj)
- {
- Action action = obj as Action;
- Debug.Assert(action != null, "Expected an Action here");
- action();
}
/// <summary>
@@ -164,25 +124,21 @@ namespace System.Threading
/// delegate will be run immediately and synchronously. Any exception the delegate generates will be
/// propagated out of this method call.
/// </para>
+ /// <para>
+ /// The current <see cref="System.Threading.ExecutionContext">ExecutionContext</see>, if one exists, will be captured
+ /// along with the delegate and will be used when executing it.
+ /// </para>
/// </remarks>
/// <param name="callback">The delegate to be executed when the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.</param>
/// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
- /// be used to deregister the callback.</returns>
+ /// be used to unregister the callback.</returns>
/// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
- /// <exception cref="T:System.ObjectDisposedException">The associated <see
- /// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
- public CancellationTokenRegistration Register(Action callback)
- {
- if (callback == null)
- throw new ArgumentNullException(nameof(callback));
-
- return Register(
- s_ActionToActionObjShunt,
- callback,
- false, // useSync=false
- true // useExecutionContext=true
- );
- }
+ public CancellationTokenRegistration Register(Action callback) =>
+ Register(
+ s_actionToActionObjShunt,
+ callback ?? throw new ArgumentNullException(nameof(callback)),
+ useSynchronizationContext: false,
+ useExecutionContext: true);
/// <summary>
/// Registers a delegate that will be called when this
@@ -194,26 +150,24 @@ namespace System.Threading
/// delegate will be run immediately and synchronously. Any exception the delegate generates will be
/// propagated out of this method call.
/// </para>
+ /// <para>
+ /// The current <see cref="System.Threading.ExecutionContext">ExecutionContext</see>, if one exists, will be captured
+ /// along with the delegate and will be used when executing it.
+ /// </para>
/// </remarks>
/// <param name="callback">The delegate to be executed when the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.</param>
/// <param name="useSynchronizationContext">A Boolean value that indicates whether to capture
/// the current <see cref="T:System.Threading.SynchronizationContext">SynchronizationContext</see> and use it
/// when invoking the <paramref name="callback"/>.</param>
/// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
- /// be used to deregister the callback.</returns>
+ /// be used to unregister the callback.</returns>
/// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
- public CancellationTokenRegistration Register(Action callback, bool useSynchronizationContext)
- {
- if (callback == null)
- throw new ArgumentNullException(nameof(callback));
-
- return Register(
- s_ActionToActionObjShunt,
- callback,
+ public CancellationTokenRegistration Register(Action callback, bool useSynchronizationContext) =>
+ Register(
+ s_actionToActionObjShunt,
+ callback ?? throw new ArgumentNullException(nameof(callback)),
useSynchronizationContext,
- true // useExecutionContext=true
- );
- }
+ useExecutionContext: true);
/// <summary>
/// Registers a delegate that will be called when this
@@ -225,24 +179,18 @@ namespace System.Threading
/// delegate will be run immediately and synchronously. Any exception the delegate generates will be
/// propagated out of this method call.
/// </para>
+ /// <para>
+ /// The current <see cref="System.Threading.ExecutionContext">ExecutionContext</see>, if one exists, will be captured
+ /// along with the delegate and will be used when executing it.
+ /// </para>
/// </remarks>
/// <param name="callback">The delegate to be executed when the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.</param>
/// <param name="state">The state to pass to the <paramref name="callback"/> when the delegate is invoked. This may be null.</param>
/// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
- /// be used to deregister the callback.</returns>
+ /// be used to unregister the callback.</returns>
/// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
- public CancellationTokenRegistration Register(Action<Object> callback, Object state)
- {
- if (callback == null)
- throw new ArgumentNullException(nameof(callback));
-
- return Register(
- callback,
- state,
- false, // useSync=false
- true // useExecutionContext=true
- );
- }
+ public CancellationTokenRegistration Register(Action<object> callback, object state) =>
+ Register(callback, state, useSynchronizationContext: false, useExecutionContext: true);
/// <summary>
/// Registers a delegate that will be called when this
@@ -265,31 +213,17 @@ namespace System.Threading
/// the current <see cref="T:System.Threading.SynchronizationContext">SynchronizationContext</see> and use it
/// when invoking the <paramref name="callback"/>.</param>
/// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
- /// be used to deregister the callback.</returns>
+ /// be used to unregister the callback.</returns>
/// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
/// <exception cref="T:System.ObjectDisposedException">The associated <see
/// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
- public CancellationTokenRegistration Register(Action<Object> callback, Object state, bool useSynchronizationContext)
- {
- return Register(
- callback,
- state,
- useSynchronizationContext,
- true // useExecutionContext=true
- );
- }
+ public CancellationTokenRegistration Register(Action<object> callback, object state, bool useSynchronizationContext) =>
+ Register(callback, state, useSynchronizationContext, useExecutionContext: true);
// helper for internal registration needs that don't require an EC capture (e.g. creating linked token sources, or registering unstarted TPL tasks)
// has a handy signature, and skips capturing execution context.
- internal CancellationTokenRegistration InternalRegisterWithoutEC(Action<object> callback, Object state)
- {
- return Register(
- callback,
- state,
- false, // useSyncContext=false
- false // useExecutionContext=false
- );
- }
+ internal CancellationTokenRegistration InternalRegisterWithoutEC(Action<object> callback, object state) =>
+ Register(callback, state, useSynchronizationContext: false, useExecutionContext: false);
/// <summary>
/// Registers a delegate that will be called when this
@@ -308,37 +242,25 @@ namespace System.Threading
/// the current <see cref="T:System.Threading.SynchronizationContext">SynchronizationContext</see> and use it
/// when invoking the <paramref name="callback"/>.</param>
/// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
- /// be used to deregister the callback.</returns>
+ /// be used to unregister the callback.</returns>
/// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
/// <exception cref="T:System.ObjectDisposedException">The associated <see
/// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
+#if CORECLR
+ private
+#else
[MethodImpl(MethodImplOptions.NoInlining)]
- public CancellationTokenRegistration Register(Action<Object> callback, Object state, bool useSynchronizationContext, bool useExecutionContext)
+ public
+#endif
+ CancellationTokenRegistration Register(Action<object> callback, object state, bool useSynchronizationContext, bool useExecutionContext)
{
if (callback == null)
throw new ArgumentNullException(nameof(callback));
- if (CanBeCanceled == false)
- {
- return new CancellationTokenRegistration(); // nothing to do for tokens than can never reach the canceled state. Give them a dummy registration.
- }
-
- // Capture sync/execution contexts if required.
- // Note: Only capture sync/execution contexts if IsCancellationRequested = false
- // as we know that if it is true that the callback will just be called synchronously.
-
- SynchronizationContext capturedSyncContext = null;
- ExecutionContext capturedExecutionContext = null;
- if (!IsCancellationRequested)
- {
- if (useSynchronizationContext)
- capturedSyncContext = SynchronizationContext.Current;
- if (useExecutionContext)
- capturedExecutionContext = ExecutionContext.Capture();
- }
-
- // Register the callback with the source.
- return m_source.InternalRegister(callback, state, capturedSyncContext, capturedExecutionContext);
+ CancellationTokenSource source = _source;
+ return source != null ?
+ source.InternalRegister(callback, state, useSynchronizationContext ? SynchronizationContext.Current : null, useExecutionContext ? ExecutionContext.Capture() : null) :
+ default; // Nothing to do for tokens than can never reach the canceled state. Give back a dummy registration.
}
/// <summary>
@@ -350,30 +272,7 @@ namespace System.Threading
/// <returns>True if the instances are equal; otherwise, false. Two tokens are equal if they are associated
/// with the same <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> or if they were both constructed
/// from public CancellationToken constructors and their <see cref="IsCancellationRequested"/> values are equal.</returns>
- public bool Equals(CancellationToken other)
- {
- //if both sources are null, then both tokens represent the Empty token.
- if (m_source == null && other.m_source == null)
- {
- return true;
- }
-
- // one is null but other has inflated the default source
- // these are only equal if the inflated one is the staticSource(false)
- if (m_source == null)
- {
- return other.m_source == CancellationTokenSource.InternalGetStaticSource(false);
- }
-
- if (other.m_source == null)
- {
- return m_source == CancellationTokenSource.InternalGetStaticSource(false);
- }
-
- // general case, we check if the sources are identical
-
- return m_source == other.m_source;
- }
+ public bool Equals(CancellationToken other) => _source == other._source;
/// <summary>
/// Determines whether the current <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instance is equal to the
@@ -386,30 +285,13 @@ namespace System.Threading
/// from public CancellationToken constructors and their <see cref="IsCancellationRequested"/> values are equal.</returns>
/// <exception cref="T:System.ObjectDisposedException">An associated <see
/// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
- public override bool Equals(Object other)
- {
- if (other is CancellationToken)
- {
- return Equals((CancellationToken)other);
- }
-
- return false;
- }
+ public override bool Equals(object other) => other is CancellationToken && Equals((CancellationToken)other);
/// <summary>
/// Serves as a hash function for a <see cref="T:System.Threading.CancellationToken">CancellationToken</see>.
/// </summary>
/// <returns>A hash code for the current <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instance.</returns>
- public override Int32 GetHashCode()
- {
- if (m_source == null)
- {
- // link to the common source so that we have a source to interrogate.
- return CancellationTokenSource.InternalGetStaticSource(false).GetHashCode();
- }
-
- return m_source.GetHashCode();
- }
+ public override int GetHashCode() => (_source ?? CancellationTokenSource.s_neverCanceledSource).GetHashCode();
/// <summary>
/// Determines whether two <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instances are equal.
@@ -419,10 +301,7 @@ namespace System.Threading
/// <returns>True if the instances are equal; otherwise, false.</returns>
/// <exception cref="T:System.ObjectDisposedException">An associated <see
/// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
- public static bool operator ==(CancellationToken left, CancellationToken right)
- {
- return left.Equals(right);
- }
+ public static bool operator ==(CancellationToken left, CancellationToken right) => left.Equals(right);
/// <summary>
/// Determines whether two <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instances are not equal.
@@ -432,10 +311,7 @@ namespace System.Threading
/// <returns>True if the instances are not equal; otherwise, false.</returns>
/// <exception cref="T:System.ObjectDisposedException">An associated <see
/// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
- public static bool operator !=(CancellationToken left, CancellationToken right)
- {
- return !left.Equals(right);
- }
+ public static bool operator !=(CancellationToken left, CancellationToken right) => !left.Equals(right);
/// <summary>
/// Throws a <see cref="T:System.OperationCanceledException">OperationCanceledException</see> if
@@ -457,22 +333,8 @@ namespace System.Threading
ThrowOperationCanceledException();
}
- // Throw an ODE if this CancellationToken's source is disposed.
- internal void ThrowIfSourceDisposed()
- {
- if ((m_source != null) && m_source.IsDisposed)
- ThrowObjectDisposedException();
- }
-
// Throws an OCE; separated out to enable better inlining of ThrowIfCancellationRequested
- private void ThrowOperationCanceledException()
- {
+ private void ThrowOperationCanceledException() =>
throw new OperationCanceledException(SR.OperationCanceled, this);
- }
-
- private static void ThrowObjectDisposedException()
- {
- throw new ObjectDisposedException(null, SR.CancellationToken_SourceDisposed);
- }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.Windows.cs b/src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.Windows.cs
new file mode 100644
index 000000000..2da53b2b8
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.Windows.cs
@@ -0,0 +1,93 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using Microsoft.Win32.SafeHandles;
+
+namespace System.Threading
+{
+ public partial class EventWaitHandle
+ {
+ private const uint AccessRights = (uint)Interop.Kernel32.MAXIMUM_ALLOWED | Interop.Kernel32.SYNCHRONIZE | Interop.Kernel32.EVENT_MODIFY_STATE;
+
+ private EventWaitHandle(SafeWaitHandle handle)
+ {
+ SafeWaitHandle = handle;
+ }
+
+ private void CreateEventCore(bool initialState, EventResetMode mode, string name, out bool createdNew)
+ {
+#if !PLATFORM_WINDOWS
+ if (name != null)
+ throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
+#endif
+ uint eventFlags = initialState ? Interop.Kernel32.CREATE_EVENT_INITIAL_SET : 0;
+ if (mode == EventResetMode.ManualReset)
+ eventFlags |= (uint)Interop.Kernel32.CREATE_EVENT_MANUAL_RESET;
+
+ SafeWaitHandle handle = Interop.Kernel32.CreateEventEx(IntPtr.Zero, name, eventFlags, AccessRights);
+
+ int errorCode = Marshal.GetLastWin32Error();
+ if (handle.IsInvalid)
+ {
+ handle.SetHandleAsInvalid();
+ if (name != null && name.Length != 0 && errorCode == Interop.Errors.ERROR_INVALID_HANDLE)
+ throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
+
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, name);
+ }
+ createdNew = errorCode != Interop.Errors.ERROR_ALREADY_EXISTS;
+ SafeWaitHandle = handle;
+ }
+
+ private static OpenExistingResult OpenExistingWorker(string name, out EventWaitHandle result)
+ {
+#if PLATFORM_WINDOWS
+ if (name == null)
+ throw new ArgumentNullException(nameof(name));
+ if (name.Length == 0)
+ throw new ArgumentException(SR.Argument_EmptyName, nameof(name));
+
+ result = null;
+ SafeWaitHandle myHandle = Interop.Kernel32.OpenEvent(AccessRights, false, name);
+
+ if (myHandle.IsInvalid)
+ {
+ int errorCode = Marshal.GetLastWin32Error();
+
+ if (errorCode == Interop.Errors.ERROR_FILE_NOT_FOUND || errorCode == Interop.Errors.ERROR_INVALID_NAME)
+ return OpenExistingResult.NameNotFound;
+ if (errorCode == Interop.Errors.ERROR_PATH_NOT_FOUND)
+ return OpenExistingResult.PathNotFound;
+ if (name != null && name.Length != 0 && errorCode == Interop.Errors.ERROR_INVALID_HANDLE)
+ return OpenExistingResult.NameInvalid;
+
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, name);
+ }
+ result = new EventWaitHandle(myHandle);
+ return OpenExistingResult.Success;
+#else
+ throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
+#endif
+ }
+
+ public bool Reset()
+ {
+ bool res = Interop.Kernel32.ResetEvent(_waitHandle);
+ if (!res)
+ throw Win32Marshal.GetExceptionForLastWin32Error();
+ return res;
+ }
+
+ public bool Set()
+ {
+ bool res = Interop.Kernel32.SetEvent(_waitHandle);
+ if (!res)
+ throw Win32Marshal.GetExceptionForLastWin32Error();
+ return res;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.cs b/src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.cs
new file mode 100644
index 000000000..4cd733b9b
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Threading/EventWaitHandle.cs
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.IO;
+
+namespace System.Threading
+{
+ public partial class EventWaitHandle : WaitHandle
+ {
+ public EventWaitHandle(bool initialState, EventResetMode mode) :
+ this(initialState, mode, null, out _)
+ {
+ }
+
+ public EventWaitHandle(bool initialState, EventResetMode mode, string name) :
+ this(initialState, mode, name, out _)
+ {
+ }
+
+ public EventWaitHandle(bool initialState, EventResetMode mode, string name, out bool createdNew)
+ {
+ if (mode != EventResetMode.AutoReset && mode != EventResetMode.ManualReset)
+ throw new ArgumentException(SR.Argument_InvalidFlag, nameof(mode));
+
+ CreateEventCore(initialState, mode, name, out createdNew);
+ }
+
+ public static EventWaitHandle OpenExisting(string name)
+ {
+ EventWaitHandle result;
+ switch (OpenExistingWorker(name, out result))
+ {
+ case OpenExistingResult.NameNotFound:
+ throw new WaitHandleCannotBeOpenedException();
+ case OpenExistingResult.NameInvalid:
+ throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
+ case OpenExistingResult.PathNotFound:
+ throw new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, name));
+ default:
+ return result;
+ }
+ }
+
+ public static bool TryOpenExisting(string name, out EventWaitHandle result)
+ {
+ return OpenExistingWorker(name, out result) == OpenExistingResult.Success;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs b/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs
index 9f27c6dcb..694514ef0 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs
@@ -19,11 +19,12 @@ using Thread = Internal.Runtime.Augments.RuntimeThread;
namespace System.Threading
{
- public delegate void ContextCallback(Object state);
+ public delegate void ContextCallback(object state);
public sealed class ExecutionContext : IDisposable, ISerializable
{
internal static readonly ExecutionContext Default = new ExecutionContext(isDefault: true);
+ internal static readonly ExecutionContext DefaultFlowSuppressed = new ExecutionContext(AsyncLocalValueMap.Empty, Array.Empty<IAsyncLocal>(), isFlowSuppressed: true);
private readonly IAsyncLocalValueMap m_localValues;
private readonly IAsyncLocal[] m_localChangeNotifications;
@@ -63,15 +64,14 @@ namespace System.Threading
{
Debug.Assert(isFlowSuppressed != m_isFlowSuppressed);
- if (!isFlowSuppressed &&
- (m_localValues == null ||
- m_localValues.GetType() == typeof(AsyncLocalValueMap.EmptyAsyncLocalValueMap))
- )
+ if (m_localValues == null || AsyncLocalValueMap.IsEmpty(m_localValues))
{
- return null; // implies the default context
+ return isFlowSuppressed ?
+ DefaultFlowSuppressed :
+ null; // implies the default context
}
- // Flow suppressing a Default context will have null values, set them to Empty
- return new ExecutionContext(m_localValues ?? AsyncLocalValueMap.Empty, m_localChangeNotifications ?? Array.Empty<IAsyncLocal>(), isFlowSuppressed);
+
+ return new ExecutionContext(m_localValues, m_localChangeNotifications, isFlowSuppressed);
}
public static AsyncFlowControl SuppressFlow()
@@ -112,7 +112,7 @@ namespace System.Threading
internal bool IsDefault => m_isDefault;
- public static void Run(ExecutionContext executionContext, ContextCallback callback, Object state)
+ public static void Run(ExecutionContext executionContext, ContextCallback callback, object state)
{
// Note: ExecutionContext.Run is an extremely hot function and used by every await, ThreadPool execution, etc.
if (executionContext == null)
@@ -123,7 +123,7 @@ namespace System.Threading
RunInternal(executionContext, callback, state);
}
- internal static void RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
+ internal static void RunInternal(ExecutionContext executionContext, ContextCallback callback, object state)
{
// Note: ExecutionContext.RunInternal is an extremely hot function and used by every await, ThreadPool execution, etc.
// Note: Manual enregistering may be addressed by "Exception Handling Write Through Optimization"
@@ -321,19 +321,26 @@ namespace System.Threading
return;
}
+ // Regarding 'treatNullValueAsNonexistent: !needChangeNotifications' below:
+ // - When change notifications are not necessary for this IAsyncLocal, there is no observable difference between
+ // storing a null value and removing the IAsyncLocal from 'm_localValues'
+ // - When change notifications are necessary for this IAsyncLocal, the IAsyncLocal's absence in 'm_localValues'
+ // indicates that this is the first value change for the IAsyncLocal and it needs to be registered for change
+ // notifications. So in this case, a null value must be stored in 'm_localValues' to indicate that the IAsyncLocal
+ // is already registered for change notifications.
IAsyncLocal[] newChangeNotifications = null;
IAsyncLocalValueMap newValues;
bool isFlowSuppressed = false;
if (current != null)
{
isFlowSuppressed = current.m_isFlowSuppressed;
- newValues = current.m_localValues.Set(local, newValue);
+ newValues = current.m_localValues.Set(local, newValue, treatNullValueAsNonexistent: !needChangeNotifications);
newChangeNotifications = current.m_localChangeNotifications;
}
else
{
// First AsyncLocal
- newValues = new AsyncLocalValueMap.OneElementAsyncLocalValueMap(local, newValue);
+ newValues = AsyncLocalValueMap.Create(local, newValue, treatNullValueAsNonexistent: !needChangeNotifications);
}
//
@@ -359,7 +366,7 @@ namespace System.Threading
}
Thread.CurrentThread.ExecutionContext =
- (!isFlowSuppressed && newValues.GetType() == typeof(AsyncLocalValueMap.EmptyAsyncLocalValueMap)) ?
+ (!isFlowSuppressed && AsyncLocalValueMap.IsEmpty(newValues)) ?
null : // No values, return to Default context
new ExecutionContext(newValues, newChangeNotifications, isFlowSuppressed);
diff --git a/src/System.Private.CoreLib/shared/System/Threading/ManualResetEventSlim.cs b/src/System.Private.CoreLib/shared/System/Threading/ManualResetEventSlim.cs
new file mode 100644
index 000000000..dc65f6f16
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Threading/ManualResetEventSlim.cs
@@ -0,0 +1,759 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+
+namespace System.Threading
+{
+ // ManualResetEventSlim wraps a manual-reset event internally with a little bit of
+ // spinning. When an event will be set imminently, it is often advantageous to avoid
+ // a 4k+ cycle context switch in favor of briefly spinning. Therefore we layer on to
+ // a brief amount of spinning that should, on the average, make using the slim event
+ // cheaper than using Win32 events directly. This can be reset manually, much like
+ // a Win32 manual-reset would be.
+ //
+ // Notes:
+ // We lazily allocate the Win32 event internally. Therefore, the caller should
+ // always call Dispose to clean it up, just in case. This API is a no-op of the
+ // event wasn't allocated, but if it was, ensures that the event goes away
+ // eagerly, instead of waiting for finalization.
+
+ /// <summary>
+ /// Provides a slimmed down version of <see cref="T:System.Threading.ManualResetEvent"/>.
+ /// </summary>
+ /// <remarks>
+ /// All public and protected members of <see cref="ManualResetEventSlim"/> are thread-safe and may be used
+ /// concurrently from multiple threads, with the exception of Dispose, which
+ /// must only be used when all other operations on the <see cref="ManualResetEventSlim"/> have
+ /// completed, and Reset, which should only be used when no other threads are
+ /// accessing the event.
+ /// </remarks>
+ [DebuggerDisplay("Set = {IsSet}")]
+ public class ManualResetEventSlim : IDisposable
+ {
+ // These are the default spin counts we use on single-proc and MP machines.
+ private const int DEFAULT_SPIN_SP = 1;
+
+ private volatile object m_lock;
+ // A lock used for waiting and pulsing. Lazily initialized via EnsureLockObjectCreated()
+
+ private volatile ManualResetEvent m_eventObj; // A true Win32 event used for waiting.
+
+ // -- State -- //
+ //For a packed word a uint would seem better, but Interlocked.* doesn't support them as uint isn't CLS-compliant.
+ private volatile int m_combinedState; //ie a uint. Used for the state items listed below.
+
+ //1-bit for signalled state
+ private const int SignalledState_BitMask = unchecked((int)0x80000000);//1000 0000 0000 0000 0000 0000 0000 0000
+ private const int SignalledState_ShiftCount = 31;
+
+ //1-bit for disposed state
+ private const int Dispose_BitMask = unchecked((int)0x40000000);//0100 0000 0000 0000 0000 0000 0000 0000
+
+ //11-bits for m_spinCount
+ private const int SpinCountState_BitMask = unchecked((int)0x3FF80000); //0011 1111 1111 1000 0000 0000 0000 0000
+ private const int SpinCountState_ShiftCount = 19;
+ private const int SpinCountState_MaxValue = (1 << 11) - 1; //2047
+
+ //19-bits for m_waiters. This allows support of 512K threads waiting which should be ample
+ private const int NumWaitersState_BitMask = unchecked((int)0x0007FFFF); // 0000 0000 0000 0111 1111 1111 1111 1111
+ private const int NumWaitersState_ShiftCount = 0;
+ private const int NumWaitersState_MaxValue = (1 << 19) - 1; //512K-1
+ // ----------- //
+
+#if DEBUG
+ private static int s_nextId; // The next id that will be given out.
+ private int m_id = Interlocked.Increment(ref s_nextId); // A unique id for debugging purposes only.
+ private long m_lastSetTime;
+ private long m_lastResetTime;
+#endif
+
+ /// <summary>
+ /// Gets the underlying <see cref="T:System.Threading.WaitHandle"/> object for this <see
+ /// cref="ManualResetEventSlim"/>.
+ /// </summary>
+ /// <value>The underlying <see cref="T:System.Threading.WaitHandle"/> event object fore this <see
+ /// cref="ManualResetEventSlim"/>.</value>
+ /// <remarks>
+ /// Accessing this property forces initialization of an underlying event object if one hasn't
+ /// already been created. To simply wait on this <see cref="ManualResetEventSlim"/>,
+ /// the public Wait methods should be preferred.
+ /// </remarks>
+ public WaitHandle WaitHandle
+ {
+ get
+ {
+ ThrowIfDisposed();
+ if (m_eventObj == null)
+ {
+ // Lazily initialize the event object if needed.
+ LazyInitializeEvent();
+ }
+
+ return m_eventObj;
+ }
+ }
+
+ /// <summary>
+ /// Gets whether the event is set.
+ /// </summary>
+ /// <value>true if the event has is set; otherwise, false.</value>
+ public bool IsSet
+ {
+ get
+ {
+ return 0 != ExtractStatePortion(m_combinedState, SignalledState_BitMask);
+ }
+
+ private set
+ {
+ UpdateStateAtomically(((value) ? 1 : 0) << SignalledState_ShiftCount, SignalledState_BitMask);
+ }
+ }
+
+ /// <summary>
+ /// Gets the number of spin waits that will be occur before falling back to a true wait.
+ /// </summary>
+ public int SpinCount
+ {
+ get
+ {
+ return ExtractStatePortionAndShiftRight(m_combinedState, SpinCountState_BitMask, SpinCountState_ShiftCount);
+ }
+
+ private set
+ {
+ Debug.Assert(value >= 0, "SpinCount is a restricted-width integer. The value supplied is outside the legal range.");
+ Debug.Assert(value <= SpinCountState_MaxValue, "SpinCount is a restricted-width integer. The value supplied is outside the legal range.");
+ // Don't worry about thread safety because it's set one time from the constructor
+ m_combinedState = (m_combinedState & ~SpinCountState_BitMask) | (value << SpinCountState_ShiftCount);
+ }
+ }
+
+ /// <summary>
+ /// How many threads are waiting.
+ /// </summary>
+ private int Waiters
+ {
+ get
+ {
+ return ExtractStatePortionAndShiftRight(m_combinedState, NumWaitersState_BitMask, NumWaitersState_ShiftCount);
+ }
+
+ set
+ {
+ //setting to <0 would indicate an internal flaw, hence Assert is appropriate.
+ Debug.Assert(value >= 0, "NumWaiters should never be less than zero. This indicates an internal error.");
+
+ // it is possible for the max number of waiters to be exceeded via user-code, hence we use a real exception here.
+ if (value >= NumWaitersState_MaxValue)
+ throw new InvalidOperationException(string.Format(SR.ManualResetEventSlim_ctor_TooManyWaiters, NumWaitersState_MaxValue));
+
+ UpdateStateAtomically(value << NumWaitersState_ShiftCount, NumWaitersState_BitMask);
+ }
+ }
+
+ //-----------------------------------------------------------------------------------
+ // Constructs a new event, optionally specifying the initial state and spin count.
+ // The defaults are that the event is unsignaled and some reasonable default spin.
+ //
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ManualResetEventSlim"/>
+ /// class with an initial state of nonsignaled.
+ /// </summary>
+ public ManualResetEventSlim()
+ : this(false)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ManualResetEventSlim"/>
+ /// class with a boolean value indicating whether to set the initial state to signaled.
+ /// </summary>
+ /// <param name="initialState">true to set the initial state signaled; false to set the initial state
+ /// to nonsignaled.</param>
+ public ManualResetEventSlim(bool initialState)
+ {
+ // Specify the default spin count, and use default spin if we're
+ // on a multi-processor machine. Otherwise, we won't.
+ Initialize(initialState, SpinWait.SpinCountforSpinBeforeWait);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ManualResetEventSlim"/>
+ /// class with a Boolean value indicating whether to set the initial state to signaled and a specified
+ /// spin count.
+ /// </summary>
+ /// <param name="initialState">true to set the initial state to signaled; false to set the initial state
+ /// to nonsignaled.</param>
+ /// <param name="spinCount">The number of spin waits that will occur before falling back to a true
+ /// wait.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="spinCount"/> is less than
+ /// 0 or greater than the maximum allowed value.</exception>
+ public ManualResetEventSlim(bool initialState, int spinCount)
+ {
+ if (spinCount < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(spinCount));
+ }
+
+ if (spinCount > SpinCountState_MaxValue)
+ {
+ throw new ArgumentOutOfRangeException(
+ nameof(spinCount),
+ string.Format(SR.ManualResetEventSlim_ctor_SpinCountOutOfRange, SpinCountState_MaxValue));
+ }
+
+ // We will suppress default spin because the user specified a count.
+ Initialize(initialState, spinCount);
+ }
+
+ /// <summary>
+ /// Initializes the internal state of the event.
+ /// </summary>
+ /// <param name="initialState">Whether the event is set initially or not.</param>
+ /// <param name="spinCount">The spin count that decides when the event will block.</param>
+ private void Initialize(bool initialState, int spinCount)
+ {
+ m_combinedState = initialState ? (1 << SignalledState_ShiftCount) : 0;
+ //the spinCount argument has been validated by the ctors.
+ //but we now sanity check our predefined constants.
+ Debug.Assert(DEFAULT_SPIN_SP >= 0, "Internal error - DEFAULT_SPIN_SP is outside the legal range.");
+ Debug.Assert(DEFAULT_SPIN_SP <= SpinCountState_MaxValue, "Internal error - DEFAULT_SPIN_SP is outside the legal range.");
+
+ SpinCount = PlatformHelper.IsSingleProcessor ? DEFAULT_SPIN_SP : spinCount;
+ }
+
+ /// <summary>
+ /// Helper to ensure the lock object is created before first use.
+ /// </summary>
+ private void EnsureLockObjectCreated()
+ {
+ if (m_lock != null)
+ return;
+
+ object newObj = new object();
+ Interlocked.CompareExchange(ref m_lock, newObj, null); // failure is benign. Someone else set the value.
+ }
+
+ /// <summary>
+ /// This method lazily initializes the event object. It uses CAS to guarantee that
+ /// many threads racing to call this at once don't result in more than one event
+ /// being stored and used. The event will be signaled or unsignaled depending on
+ /// the state of the thin-event itself, with synchronization taken into account.
+ /// </summary>
+ /// <returns>True if a new event was created and stored, false otherwise.</returns>
+ private bool LazyInitializeEvent()
+ {
+ bool preInitializeIsSet = IsSet;
+ ManualResetEvent newEventObj = new ManualResetEvent(preInitializeIsSet);
+
+ // We have to CAS this in case we are racing with another thread. We must
+ // guarantee only one event is actually stored in this field.
+ if (Interlocked.CompareExchange(ref m_eventObj, newEventObj, null) != null)
+ {
+ // Someone else set the value due to a race condition. Destroy the garbage event.
+ newEventObj.Dispose();
+
+ return false;
+ }
+ else
+ {
+ // Now that the event is published, verify that the state hasn't changed since
+ // we snapped the preInitializeState. Another thread could have done that
+ // between our initial observation above and here. The barrier incurred from
+ // the CAS above (in addition to m_state being volatile) prevents this read
+ // from moving earlier and being collapsed with our original one.
+ bool currentIsSet = IsSet;
+ if (currentIsSet != preInitializeIsSet)
+ {
+ Debug.Assert(currentIsSet,
+ "The only safe concurrent transition is from unset->set: detected set->unset.");
+
+ // We saw it as unsignaled, but it has since become set.
+ lock (newEventObj)
+ {
+ // If our event hasn't already been disposed of, we must set it.
+ if (m_eventObj == newEventObj)
+ {
+ newEventObj.Set();
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+
+ /// <summary>
+ /// Sets the state of the event to signaled, which allows one or more threads waiting on the event to
+ /// proceed.
+ /// </summary>
+ public void Set()
+ {
+ Set(false);
+ }
+
+ /// <summary>
+ /// Private helper to actually perform the Set.
+ /// </summary>
+ /// <param name="duringCancellation">Indicates whether we are calling Set() during cancellation.</param>
+ /// <exception cref="T:System.OperationCanceledException">The object has been canceled.</exception>
+ private void Set(bool duringCancellation)
+ {
+ // We need to ensure that IsSet=true does not get reordered past the read of m_eventObj
+ // This would be a legal movement according to the .NET memory model.
+ // The code is safe as IsSet involves an Interlocked.CompareExchange which provides a full memory barrier.
+ IsSet = true;
+
+ // If there are waiting threads, we need to pulse them.
+ if (Waiters > 0)
+ {
+ Debug.Assert(m_lock != null); //if waiters>0, then m_lock has already been created.
+ lock (m_lock)
+ {
+ Monitor.PulseAll(m_lock);
+ }
+ }
+
+ ManualResetEvent eventObj = m_eventObj;
+
+ //Design-decision: do not set the event if we are in cancellation -> better to deadlock than to wake up waiters incorrectly
+ //It would be preferable to wake up the event and have it throw OCE. This requires MRE to implement cancellation logic
+
+ if (eventObj != null && !duringCancellation)
+ {
+ // We must surround this call to Set in a lock. The reason is fairly subtle.
+ // Sometimes a thread will issue a Wait and wake up after we have set m_state,
+ // but before we have gotten around to setting m_eventObj (just below). That's
+ // because Wait first checks m_state and will only access the event if absolutely
+ // necessary. However, the coding pattern { event.Wait(); event.Dispose() } is
+ // quite common, and we must support it. If the waiter woke up and disposed of
+ // the event object before the setter has finished, however, we would try to set a
+ // now-disposed Win32 event. Crash! To deal with this race condition, we use a lock to
+ // protect access to the event object when setting and disposing of it. We also
+ // double-check that the event has not become null in the meantime when in the lock.
+
+ lock (eventObj)
+ {
+ if (m_eventObj != null)
+ {
+ // If somebody is waiting, we must set the event.
+ m_eventObj.Set();
+ }
+ }
+ }
+
+#if DEBUG
+ m_lastSetTime = DateTime.UtcNow.Ticks;
+#endif
+ }
+
+ /// <summary>
+ /// Sets the state of the event to nonsignaled, which causes threads to block.
+ /// </summary>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="ManualResetEventSlim"/>, <see cref="Reset()"/> is not
+ /// thread-safe and may not be used concurrently with other members of this instance.
+ /// </remarks>
+ public void Reset()
+ {
+ ThrowIfDisposed();
+ // If there's an event, reset it.
+ if (m_eventObj != null)
+ {
+ m_eventObj.Reset();
+ }
+
+ // There is a race condition here. If another thread Sets the event, we will get into a state
+ // where m_state will be unsignaled, yet the Win32 event object will have been signaled.
+ // This could cause waiting threads to wake up even though the event is in an
+ // unsignaled state. This is fine -- those that are calling Reset concurrently are
+ // responsible for doing "the right thing" -- e.g. rechecking the condition and
+ // resetting the event manually.
+
+ // And finally set our state back to unsignaled.
+ IsSet = false;
+
+#if DEBUG
+ m_lastResetTime = DateTime.UtcNow.Ticks;
+#endif
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the current <see cref="ManualResetEventSlim"/> is set.
+ /// </summary>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The maximum number of waiters has been exceeded.
+ /// </exception>
+ /// <remarks>
+ /// The caller of this method blocks indefinitely until the current instance is set. The caller will
+ /// return immediately if the event is currently in a set state.
+ /// </remarks>
+ public void Wait()
+ {
+ Wait(Timeout.Infinite, new CancellationToken());
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the current <see cref="ManualResetEventSlim"/> receives a signal,
+ /// while observing a <see cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to
+ /// observe.</param>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The maximum number of waiters has been exceeded.
+ /// </exception>
+ /// <exception cref="T:System.OperationCanceledExcepton"><paramref name="cancellationToken"/> was
+ /// canceled.</exception>
+ /// <remarks>
+ /// The caller of this method blocks indefinitely until the current instance is set. The caller will
+ /// return immediately if the event is currently in a set state.
+ /// </remarks>
+ public void Wait(CancellationToken cancellationToken)
+ {
+ Wait(Timeout.Infinite, cancellationToken);
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the current <see cref="ManualResetEventSlim"/> is set, using a
+ /// <see cref="T:System.TimeSpan"/> to measure the time interval.
+ /// </summary>
+ /// <param name="timeout">A <see cref="System.TimeSpan"/> that represents the number of milliseconds
+ /// to wait, or a <see cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
+ /// </param>
+ /// <returns>true if the <see cref="System.Threading.ManualResetEventSlim"/> was set; otherwise,
+ /// false.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> is a negative
+ /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater
+ /// than <see cref="System.Int32.MaxValue"/>.</exception>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The maximum number of waiters has been exceeded.
+ /// </exception>
+ public bool Wait(TimeSpan timeout)
+ {
+ long totalMilliseconds = (long)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
+ {
+ throw new ArgumentOutOfRangeException(nameof(timeout));
+ }
+
+ return Wait((int)totalMilliseconds, new CancellationToken());
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the current <see cref="ManualResetEventSlim"/> is set, using a
+ /// <see cref="T:System.TimeSpan"/> to measure the time interval, while observing a <see
+ /// cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="timeout">A <see cref="System.TimeSpan"/> that represents the number of milliseconds
+ /// to wait, or a <see cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
+ /// </param>
+ /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to
+ /// observe.</param>
+ /// <returns>true if the <see cref="System.Threading.ManualResetEventSlim"/> was set; otherwise,
+ /// false.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> is a negative
+ /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater
+ /// than <see cref="System.Int32.MaxValue"/>.</exception>
+ /// <exception cref="T:System.Threading.OperationCanceledException"><paramref
+ /// name="cancellationToken"/> was canceled.</exception>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The maximum number of waiters has been exceeded.
+ /// </exception>
+ public bool Wait(TimeSpan timeout, CancellationToken cancellationToken)
+ {
+ long totalMilliseconds = (long)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
+ {
+ throw new ArgumentOutOfRangeException(nameof(timeout));
+ }
+
+ return Wait((int)totalMilliseconds, cancellationToken);
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the current <see cref="ManualResetEventSlim"/> is set, using a
+ /// 32-bit signed integer to measure the time interval.
+ /// </summary>
+ /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see
+ /// cref="Timeout.Infinite"/>(-1) to wait indefinitely.</param>
+ /// <returns>true if the <see cref="System.Threading.ManualResetEventSlim"/> was set; otherwise,
+ /// false.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a
+ /// negative number other than -1, which represents an infinite time-out.</exception>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The maximum number of waiters has been exceeded.
+ /// </exception>
+ public bool Wait(int millisecondsTimeout)
+ {
+ return Wait(millisecondsTimeout, new CancellationToken());
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the current <see cref="ManualResetEventSlim"/> is set, using a
+ /// 32-bit signed integer to measure the time interval, while observing a <see
+ /// cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see
+ /// cref="Timeout.Infinite"/>(-1) to wait indefinitely.</param>
+ /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to
+ /// observe.</param>
+ /// <returns>true if the <see cref="System.Threading.ManualResetEventSlim"/> was set; otherwise,
+ /// false.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a
+ /// negative number other than -1, which represents an infinite time-out.</exception>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The maximum number of waiters has been exceeded.
+ /// </exception>
+ /// <exception cref="T:System.Threading.OperationCanceledException"><paramref
+ /// name="cancellationToken"/> was canceled.</exception>
+ public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
+ {
+ ThrowIfDisposed();
+ cancellationToken.ThrowIfCancellationRequested(); // an early convenience check
+
+ if (millisecondsTimeout < -1)
+ {
+ throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout));
+ }
+
+ if (!IsSet)
+ {
+ if (millisecondsTimeout == 0)
+ {
+ // For 0-timeouts, we just return immediately.
+ return false;
+ }
+
+
+ // We spin briefly before falling back to allocating and/or waiting on a true event.
+ uint startTime = 0;
+ bool bNeedTimeoutAdjustment = false;
+ int realMillisecondsTimeout = millisecondsTimeout; //this will be adjusted if necessary.
+
+ if (millisecondsTimeout != Timeout.Infinite)
+ {
+ // We will account for time spent spinning, so that we can decrement it from our
+ // timeout. In most cases the time spent in this section will be negligible. But
+ // we can't discount the possibility of our thread being switched out for a lengthy
+ // period of time. The timeout adjustments only take effect when and if we actually
+ // decide to block in the kernel below.
+
+ startTime = TimeoutHelper.GetTime();
+ bNeedTimeoutAdjustment = true;
+ }
+
+ // Spin
+ int spinCount = SpinCount;
+ var spinner = new SpinWait();
+ while (spinner.Count < spinCount)
+ {
+ spinner.SpinOnce(SpinWait.Sleep1ThresholdForLongSpinBeforeWait);
+
+ if (IsSet)
+ {
+ return true;
+ }
+
+ if (spinner.Count >= 100 && spinner.Count % 10 == 0) // check the cancellation token if the user passed a very large spin count
+ cancellationToken.ThrowIfCancellationRequested();
+ }
+
+ // Now enter the lock and wait.
+ EnsureLockObjectCreated();
+
+ // We must register and unregister the token outside of the lock, to avoid deadlocks.
+ using (cancellationToken.InternalRegisterWithoutEC(s_cancellationTokenCallback, this))
+ {
+ lock (m_lock)
+ {
+ // Loop to cope with spurious wakeups from other waits being canceled
+ while (!IsSet)
+ {
+ // If our token was canceled, we must throw and exit.
+ cancellationToken.ThrowIfCancellationRequested();
+
+ //update timeout (delays in wait commencement are due to spinning and/or spurious wakeups from other waits being canceled)
+ if (bNeedTimeoutAdjustment)
+ {
+ realMillisecondsTimeout = TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout);
+ if (realMillisecondsTimeout <= 0)
+ return false;
+ }
+
+ // There is a race condition that Set will fail to see that there are waiters as Set does not take the lock,
+ // so after updating waiters, we must check IsSet again.
+ // Also, we must ensure there cannot be any reordering of the assignment to Waiters and the
+ // read from IsSet. This is guaranteed as Waiters{set;} involves an Interlocked.CompareExchange
+ // operation which provides a full memory barrier.
+ // If we see IsSet=false, then we are guaranteed that Set() will see that we are
+ // waiting and will pulse the monitor correctly.
+
+ Waiters = Waiters + 1;
+
+ if (IsSet) //This check must occur after updating Waiters.
+ {
+ Waiters--; //revert the increment.
+ return true;
+ }
+
+ // Now finally perform the wait.
+ try
+ {
+ // ** the actual wait **
+ if (!Monitor.Wait(m_lock, realMillisecondsTimeout))
+ return false; //return immediately if the timeout has expired.
+ }
+ finally
+ {
+ // Clean up: we're done waiting.
+ Waiters = Waiters - 1;
+ }
+ // Now just loop back around, and the right thing will happen. Either:
+ // 1. We had a spurious wake-up due to some other wait being canceled via a different cancellationToken (rewait)
+ // or 2. the wait was successful. (the loop will break)
+ }
+ }
+ }
+ } // automatically disposes (and unregisters) the callback
+
+ return true; //done. The wait was satisfied.
+ }
+
+ /// <summary>
+ /// Releases all resources used by the current instance of <see cref="ManualResetEventSlim"/>.
+ /// </summary>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="ManualResetEventSlim"/>, <see cref="Dispose()"/> is not
+ /// thread-safe and may not be used concurrently with other members of this instance.
+ /// </remarks>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// When overridden in a derived class, releases the unmanaged resources used by the
+ /// <see cref="ManualResetEventSlim"/>, and optionally releases the managed resources.
+ /// </summary>
+ /// <param name="disposing">true to release both managed and unmanaged resources;
+ /// false to release only unmanaged resources.</param>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="ManualResetEventSlim"/>, <see cref="Dispose(bool)"/> is not
+ /// thread-safe and may not be used concurrently with other members of this instance.
+ /// </remarks>
+ protected virtual void Dispose(bool disposing)
+ {
+ if ((m_combinedState & Dispose_BitMask) != 0)
+ return; // already disposed
+
+ m_combinedState |= Dispose_BitMask; //set the dispose bit
+ if (disposing)
+ {
+ // We will dispose of the event object. We do this under a lock to protect
+ // against the race condition outlined in the Set method above.
+ ManualResetEvent eventObj = m_eventObj;
+ if (eventObj != null)
+ {
+ lock (eventObj)
+ {
+ eventObj.Dispose();
+ m_eventObj = null;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Throw ObjectDisposedException if the MRES is disposed
+ /// </summary>
+ private void ThrowIfDisposed()
+ {
+ if ((m_combinedState & Dispose_BitMask) != 0)
+ throw new ObjectDisposedException(SR.ManualResetEventSlim_Disposed);
+ }
+
+ /// <summary>
+ /// Private helper method to wake up waiters when a cancellationToken gets canceled.
+ /// </summary>
+ private static Action<object> s_cancellationTokenCallback = new Action<object>(CancellationTokenCallback);
+ private static void CancellationTokenCallback(object obj)
+ {
+ ManualResetEventSlim mre = obj as ManualResetEventSlim;
+ Debug.Assert(mre != null, "Expected a ManualResetEventSlim");
+ Debug.Assert(mre.m_lock != null); //the lock should have been created before this callback is registered for use.
+ lock (mre.m_lock)
+ {
+ Monitor.PulseAll(mre.m_lock); // awaken all waiters
+ }
+ }
+
+ /// <summary>
+ /// Private helper method for updating parts of a bit-string state value.
+ /// Mainly called from the IsSet and Waiters properties setters
+ /// </summary>
+ /// <remarks>
+ /// Note: the parameter types must be int as CompareExchange cannot take a Uint
+ /// </remarks>
+ /// <param name="newBits">The new value</param>
+ /// <param name="updateBitsMask">The mask used to set the bits</param>
+ private void UpdateStateAtomically(int newBits, int updateBitsMask)
+ {
+ SpinWait sw = new SpinWait();
+
+ Debug.Assert((newBits | updateBitsMask) == updateBitsMask, "newBits do not fall within the updateBitsMask.");
+
+ do
+ {
+ int oldState = m_combinedState; // cache the old value for testing in CAS
+
+ // Procedure:(1) zero the updateBits. eg oldState = [11111111] flag= [00111000] newState = [11000111]
+ // then (2) map in the newBits. eg [11000111] newBits=00101000, newState=[11101111]
+ int newState = (oldState & ~updateBitsMask) | newBits;
+
+ if (Interlocked.CompareExchange(ref m_combinedState, newState, oldState) == oldState)
+ {
+ return;
+ }
+
+ sw.SpinOnce();
+ } while (true);
+ }
+
+ /// <summary>
+ /// Private helper method - performs Mask and shift, particular helpful to extract a field from a packed word.
+ /// eg ExtractStatePortionAndShiftRight(0x12345678, 0xFF000000, 24) => 0x12, ie extracting the top 8-bits as a simple integer
+ ///
+ /// ?? is there a common place to put this rather than being private to MRES?
+ /// </summary>
+ /// <param name="state"></param>
+ /// <param name="mask"></param>
+ /// <param name="rightBitShiftCount"></param>
+ /// <returns></returns>
+ private static int ExtractStatePortionAndShiftRight(int state, int mask, int rightBitShiftCount)
+ {
+ //convert to uint before shifting so that right-shift does not replicate the sign-bit,
+ //then convert back to int.
+ return unchecked((int)(((uint)(state & mask)) >> rightBitShiftCount));
+ }
+
+ /// <summary>
+ /// Performs a Mask operation, but does not perform the shift.
+ /// This is acceptable for boolean values for which the shift is unnecessary
+ /// eg (val &amp; Mask) != 0 is an appropriate way to extract a boolean rather than using
+ /// ((val &amp; Mask) &gt;&gt; shiftAmount) == 1
+ ///
+ /// ?? is there a common place to put this rather than being private to MRES?
+ /// </summary>
+ /// <param name="state"></param>
+ /// <param name="mask"></param>
+ private static int ExtractStatePortion(int state, int mask)
+ {
+ return state & mask;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Mutex.Windows.cs b/src/System.Private.CoreLib/shared/System/Threading/Mutex.Windows.cs
new file mode 100644
index 000000000..212eb9dc3
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Threading/Mutex.Windows.cs
@@ -0,0 +1,100 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.IO;
+using Microsoft.Win32;
+using Microsoft.Win32.SafeHandles;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+
+namespace System.Threading
+{
+ /// <summary>
+ /// Synchronization primitive that can also be used for interprocess synchronization
+ /// </summary>
+ public sealed partial class Mutex : WaitHandle
+ {
+ private const uint AccessRights =
+ (uint)Interop.Kernel32.MAXIMUM_ALLOWED | Interop.Kernel32.SYNCHRONIZE | Interop.Kernel32.MUTEX_MODIFY_STATE;
+
+ private void CreateMutexCore(bool initiallyOwned, string name, out bool createdNew)
+ {
+ uint mutexFlags = initiallyOwned ? Interop.Kernel32.CREATE_MUTEX_INITIAL_OWNER : 0;
+ SafeWaitHandle mutexHandle = Interop.Kernel32.CreateMutexEx(IntPtr.Zero, name, mutexFlags, AccessRights);
+ int errorCode = Marshal.GetLastWin32Error();
+
+ if (mutexHandle.IsInvalid)
+ {
+ mutexHandle.SetHandleAsInvalid();
+#if !PLATFORM_WINDOWS
+ if (errorCode == Interop.Errors.ERROR_FILENAME_EXCED_RANGE)
+ // On Unix, length validation is done by CoreCLR's PAL after converting to utf-8
+ throw new ArgumentException(SR.Argument_WaitHandleNameTooLong, nameof(name));
+#endif
+ if (errorCode == Interop.Errors.ERROR_INVALID_HANDLE)
+ throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
+
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, name);
+ }
+
+ createdNew = errorCode != Interop.Errors.ERROR_ALREADY_EXISTS;
+ SafeWaitHandle = mutexHandle;
+ }
+
+ private static OpenExistingResult OpenExistingWorker(string name, out Mutex result)
+ {
+ if (name == null)
+ {
+ throw new ArgumentNullException(nameof(name));
+ }
+
+ if (name.Length == 0)
+ {
+ throw new ArgumentException(SR.Argument_EmptyName, nameof(name));
+ }
+
+ result = null;
+ // To allow users to view & edit the ACL's, call OpenMutex
+ // with parameters to allow us to view & edit the ACL. This will
+ // fail if we don't have permission to view or edit the ACL's.
+ // If that happens, ask for less permissions.
+ SafeWaitHandle myHandle = Interop.Kernel32.OpenMutex(AccessRights, false, name);
+
+ if (myHandle.IsInvalid)
+ {
+ int errorCode = Marshal.GetLastWin32Error();
+#if !PLATFORM_WINDOWS
+ if (errorCode == Interop.Errors.ERROR_FILENAME_EXCED_RANGE)
+ {
+ // On Unix, length validation is done by CoreCLR's PAL after converting to utf-8
+ throw new ArgumentException(SR.Argument_WaitHandleNameTooLong, nameof(name));
+ }
+#endif
+ if (Interop.Errors.ERROR_FILE_NOT_FOUND == errorCode || Interop.Errors.ERROR_INVALID_NAME == errorCode)
+ return OpenExistingResult.NameNotFound;
+ if (Interop.Errors.ERROR_PATH_NOT_FOUND == errorCode)
+ return OpenExistingResult.PathNotFound;
+ if (Interop.Errors.ERROR_INVALID_HANDLE == errorCode)
+ return OpenExistingResult.NameInvalid;
+
+ // this is for passed through Win32Native Errors
+ throw Win32Marshal.GetExceptionForWin32Error(errorCode, name);
+ }
+
+ result = new Mutex(myHandle);
+ return OpenExistingResult.Success;
+ }
+
+ // Note: To call ReleaseMutex, you must have an ACL granting you
+ // MUTEX_MODIFY_STATE rights (0x0001). The other interesting value
+ // in a Mutex's ACL is MUTEX_ALL_ACCESS (0x1F0001).
+ public void ReleaseMutex()
+ {
+ if (!Interop.Kernel32.ReleaseMutex(_waitHandle))
+ {
+ throw new ApplicationException(SR.Arg_SynchronizationLockException);
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Mutex.cs b/src/System.Private.CoreLib/shared/System/Threading/Mutex.cs
new file mode 100644
index 000000000..d85242892
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Threading/Mutex.cs
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.IO;
+using Microsoft.Win32;
+using Microsoft.Win32.SafeHandles;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+
+namespace System.Threading
+{
+ /// <summary>
+ /// Synchronization primitive that can also be used for interprocess synchronization
+ /// </summary>
+ public sealed partial class Mutex : WaitHandle
+ {
+ public Mutex(bool initiallyOwned, string name, out bool createdNew)
+ {
+ CreateMutexCore(initiallyOwned, name, out createdNew);
+ }
+
+ public Mutex(bool initiallyOwned, string name)
+ {
+ CreateMutexCore(initiallyOwned, name, out _);
+ }
+
+ public Mutex(bool initiallyOwned)
+ {
+ CreateMutexCore(initiallyOwned, null, out _);
+ }
+
+ public Mutex()
+ {
+ CreateMutexCore(false, null, out _);
+ }
+
+ private Mutex(SafeWaitHandle handle)
+ {
+ SafeWaitHandle = handle;
+ }
+
+ public static Mutex OpenExisting(string name)
+ {
+ switch (OpenExistingWorker(name, out Mutex result))
+ {
+ case OpenExistingResult.NameNotFound:
+ throw new WaitHandleCannotBeOpenedException();
+ case OpenExistingResult.NameInvalid:
+ throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
+ case OpenExistingResult.PathNotFound:
+ throw new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, name));
+
+ default:
+ return result;
+ }
+ }
+
+ public static bool TryOpenExisting(string name, out Mutex result) =>
+ OpenExistingWorker(name, out result) == OpenExistingResult.Success;
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Threading/NativeOverlapped.cs b/src/System.Private.CoreLib/shared/System/Threading/NativeOverlapped.cs
index 933cb81ec..933cb81ec 100644
--- a/src/System.Private.CoreLib/src/System/Threading/NativeOverlapped.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/NativeOverlapped.cs
diff --git a/src/System.Private.CoreLib/shared/System/Threading/ReaderWriterLockSlim.cs b/src/System.Private.CoreLib/shared/System/Threading/ReaderWriterLockSlim.cs
index 45175488e..9424fbd5b 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/ReaderWriterLockSlim.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/ReaderWriterLockSlim.cs
@@ -241,7 +241,7 @@ namespace System.Threading
public TimeoutTracker(TimeSpan timeout)
{
long ltm = (long)timeout.TotalMilliseconds;
- if (ltm < -1 || ltm > (long)Int32.MaxValue)
+ if (ltm < -1 || ltm > (long)int.MaxValue)
throw new ArgumentOutOfRangeException(nameof(timeout));
_total = (int)ltm;
if (_total != -1 && _total != 0)
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Semaphore.Windows.cs b/src/System.Private.CoreLib/shared/System/Threading/Semaphore.Windows.cs
new file mode 100644
index 000000000..8a14f5ef3
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Threading/Semaphore.Windows.cs
@@ -0,0 +1,88 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Win32.SafeHandles;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace System.Threading
+{
+ public sealed partial class Semaphore
+ {
+ private const uint AccessRights = (uint)Interop.Kernel32.MAXIMUM_ALLOWED | Interop.Kernel32.SYNCHRONIZE | Interop.Kernel32.SEMAPHORE_MODIFY_STATE;
+
+ private Semaphore(SafeWaitHandle handle)
+ {
+ SafeWaitHandle = handle;
+ }
+
+ private void CreateSemaphoreCore(int initialCount, int maximumCount, string name, out bool createdNew)
+ {
+ Debug.Assert(initialCount >= 0);
+ Debug.Assert(maximumCount >= 1);
+ Debug.Assert(initialCount <= maximumCount);
+
+#if !PLATFORM_WINDOWS
+ if (name != null)
+ throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
+#endif
+ SafeWaitHandle myHandle = Interop.Kernel32.CreateSemaphoreEx(IntPtr.Zero, initialCount, maximumCount, name, 0, AccessRights);
+
+ int errorCode = Marshal.GetLastWin32Error();
+ if (myHandle.IsInvalid)
+ {
+ if (name != null && name.Length != 0 && errorCode == Interop.Errors.ERROR_INVALID_HANDLE)
+ throw new WaitHandleCannotBeOpenedException(
+ SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
+
+ throw Win32Marshal.GetExceptionForLastWin32Error();
+ }
+ createdNew = errorCode != Interop.Errors.ERROR_ALREADY_EXISTS;
+ this.SafeWaitHandle = myHandle;
+ }
+
+ private static OpenExistingResult OpenExistingWorker(string name, out Semaphore result)
+ {
+#if PLATFORM_WINDOWS
+ if (name == null)
+ throw new ArgumentNullException(nameof(name));
+ if (name.Length == 0)
+ throw new ArgumentException(SR.Argument_EmptyName, nameof(name));
+
+ // Pass false to OpenSemaphore to prevent inheritedHandles
+ SafeWaitHandle myHandle = Interop.Kernel32.OpenSemaphore(AccessRights, false, name);
+
+ if (myHandle.IsInvalid)
+ {
+ result = null;
+ int errorCode = Marshal.GetLastWin32Error();
+
+ if (errorCode == Interop.Errors.ERROR_FILE_NOT_FOUND || errorCode == Interop.Errors.ERROR_INVALID_NAME)
+ return OpenExistingResult.NameNotFound;
+ if (errorCode == Interop.Errors.ERROR_PATH_NOT_FOUND)
+ return OpenExistingResult.PathNotFound;
+ if (name != null && name.Length != 0 && errorCode == Interop.Errors.ERROR_INVALID_HANDLE)
+ return OpenExistingResult.NameInvalid;
+ // this is for passed through NativeMethods Errors
+ throw Win32Marshal.GetExceptionForLastWin32Error();
+ }
+
+ result = new Semaphore(myHandle);
+ return OpenExistingResult.Success;
+#else
+ throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
+#endif
+ }
+
+ private int ReleaseCore(int releaseCount)
+ {
+ int previousCount;
+ if (!Interop.Kernel32.ReleaseSemaphore(SafeWaitHandle, releaseCount, out previousCount))
+ throw new SemaphoreFullException();
+
+ return previousCount;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Threading/Semaphore.cs b/src/System.Private.CoreLib/shared/System/Threading/Semaphore.cs
index 9e7a7796a..6014fcd1c 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Semaphore.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Semaphore.cs
@@ -2,60 +2,36 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.IO;
using Microsoft.Win32;
using Microsoft.Win32.SafeHandles;
+using System.IO;
using System.Runtime.InteropServices;
-using System.Threading;
-using System.Runtime.Versioning;
namespace System.Threading
{
public sealed partial class Semaphore : WaitHandle
{
// creates a nameless semaphore object
- // Win32 only takes maximum count of Int32.MaxValue
- public Semaphore(int initialCount, int maximumCount)
- {
- VerifyCounts(initialCount, maximumCount);
-
- bool createdNew;
- CreateSemaphoreCore(initialCount, maximumCount, null, out createdNew);
- }
+ // Win32 only takes maximum count of int.MaxValue
+ public Semaphore(int initialCount, int maximumCount) : this(initialCount, maximumCount, null) { }
- public Semaphore(int initialCount, int maximumCount, string name)
+ public Semaphore(int initialCount, int maximumCount, string name) :
+ this(initialCount, maximumCount, name, out _)
{
- VerifyCounts(initialCount, maximumCount);
- VerifyNameForCreate(name);
-
- bool createdNew;
- CreateSemaphoreCore(initialCount, maximumCount, name, out createdNew);
}
public Semaphore(int initialCount, int maximumCount, string name, out bool createdNew)
{
- VerifyCounts(initialCount, maximumCount);
- VerifyNameForCreate(name);
-
- CreateSemaphoreCore(initialCount, maximumCount, name, out createdNew);
- }
-
- private static void VerifyCounts(int initialCount, int maximumCount)
- {
if (initialCount < 0)
- {
- throw new ArgumentOutOfRangeException(nameof(initialCount), SR.ArgumentOutOfRange_NeedNonNegNumRequired);
- }
+ throw new ArgumentOutOfRangeException(nameof(initialCount), SR.ArgumentOutOfRange_NeedNonNegNum);
if (maximumCount < 1)
- {
- throw new ArgumentOutOfRangeException(nameof(maximumCount), SR.ArgumentOutOfRange_NeedNonNegNumRequired);
- }
+ throw new ArgumentOutOfRangeException(nameof(maximumCount), SR.ArgumentOutOfRange_NeedPosNum);
if (initialCount > maximumCount)
- {
throw new ArgumentException(SR.Argument_SemaphoreInitialMaximum);
- }
+
+ CreateSemaphoreCore(initialCount, maximumCount, name, out createdNew);
}
public static Semaphore OpenExisting(string name)
@@ -77,40 +53,15 @@ namespace System.Threading
public static bool TryOpenExisting(string name, out Semaphore result) =>
OpenExistingWorker(name, out result) == OpenExistingResult.Success;
- // increase the count on a semaphore, returns previous count
public int Release() => ReleaseCore(1);
// increase the count on a semaphore, returns previous count
public int Release(int releaseCount)
{
if (releaseCount < 1)
- {
- throw new ArgumentOutOfRangeException(nameof(releaseCount), SR.ArgumentOutOfRange_NeedNonNegNumRequired);
- }
+ throw new ArgumentOutOfRangeException(nameof(releaseCount), SR.ArgumentOutOfRange_NeedNonNegNum);
return ReleaseCore(releaseCount);
}
-
- private int ReleaseCore(int releaseCount)
- {
- // The field value is modifiable via the public <see cref="WaitHandle.SafeWaitHandle"/> property, save it locally
- // to ensure that one instance is used in all places in this method
- SafeWaitHandle waitHandle = _waitHandle;
- if (waitHandle == null)
- {
- ThrowInvalidHandleException();
- }
-
- waitHandle.DangerousAddRef();
- try
- {
- return ReleaseCore(waitHandle.DangerousGetHandle(), releaseCount);
- }
- finally
- {
- waitHandle.DangerousRelease();
- }
- }
}
}
-
diff --git a/src/System.Private.CoreLib/shared/System/Threading/SemaphoreFullException.cs b/src/System.Private.CoreLib/shared/System/Threading/SemaphoreFullException.cs
index 18558b19e..a6cff781d 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/SemaphoreFullException.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/SemaphoreFullException.cs
@@ -15,11 +15,11 @@ namespace System.Threading
{
}
- public SemaphoreFullException(String message) : base(message)
+ public SemaphoreFullException(string message) : base(message)
{
}
- public SemaphoreFullException(String message, Exception innerException) : base(message, innerException)
+ public SemaphoreFullException(string message, Exception innerException) : base(message, innerException)
{
}
diff --git a/src/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs b/src/System.Private.CoreLib/shared/System/Threading/SemaphoreSlim.cs
index ba2c0ecd9..83f5f1d28 100644
--- a/src/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/SemaphoreSlim.cs
@@ -1,23 +1,14 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
-//
-//
-
-//
-// A lightweight semahore class that contains the basic semaphore functions plus some useful functions like interrupt
-// and wait handle exposing to allow waiting on multiple semaphores.
-//
-// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+using System;
+using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
-// The class will be part of the current System.Threading namespace
-
namespace System.Threading
{
/// <summary>
@@ -52,11 +43,16 @@ namespace System.Threading
// The number of synchronously waiting threads, it is set to zero in the constructor and increments before blocking the
// threading and decrements it back after that. It is used as flag for the release call to know if there are
// waiting threads in the monitor or not.
- private volatile int m_waitCount;
+ private int m_waitCount;
+
+ /// <summary>
+ /// This is used to help prevent waking more waiters than necessary. It's not perfect and sometimes more waiters than
+ /// necessary may still be woken, see <see cref="WaitUntilCountOrTimeout"/>.
+ /// </summary>
+ private int m_countOfWaitersPulsedToWake;
// Dummy object used to in lock statements to protect the semaphore count, wait handle and cancelation
- private Lock m_lock;
- private Condition m_condition;
+ private object m_lockObj;
// Act as the semaphore wait handle, it's lazily initialized if needed, the first WaitHandle call initialize it
// and wait an release sets and resets it respectively as long as it is not null
@@ -70,13 +66,13 @@ namespace System.Threading
// A pre-completed task with Result==true
private static readonly Task<bool> s_trueTask =
- new Task<bool>(false, true, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default(CancellationToken));
+ new Task<bool>(false, true, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default);
// A pre-completed task with Result==false
private readonly static Task<bool> s_falseTask =
- new Task<bool>(false, false, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default(CancellationToken));
+ new Task<bool>(false, false, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default);
// No maximum constant
- private const int NO_MAXIMUM = Int32.MaxValue;
+ private const int NO_MAXIMUM = int.MaxValue;
// Task in a linked list of asynchronous waiters
private sealed class TaskNode : Task<bool>, IThreadPoolWorkItem
@@ -89,6 +85,9 @@ namespace System.Threading
bool setSuccessfully = TrySetResult(true);
Debug.Assert(setSuccessfully, "Should have been able to complete task");
}
+#if CORECLR
+ void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae) { /* nop */ }
+#endif
}
#endregion
@@ -127,7 +126,7 @@ namespace System.Threading
return m_waitHandle;
//lock the count to avoid multiple threads initializing the handle if it is null
- using (LockHolder.Hold(m_lock))
+ lock (m_lockObj)
{
if (m_waitHandle == null)
{
@@ -183,8 +182,7 @@ namespace System.Threading
}
m_maxCount = maxCount;
- m_lock = new Lock();
- m_condition = new Condition(m_lock);
+ m_lockObj = new object();
m_currentCount = initialCount;
}
@@ -233,8 +231,8 @@ namespace System.Threading
public bool Wait(TimeSpan timeout)
{
// Validate the timeout
- Int64 totalMilliseconds = (Int64)timeout.TotalMilliseconds;
- if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ long totalMilliseconds = (long)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
{
throw new System.ArgumentOutOfRangeException(
nameof(timeout), timeout, SR.SemaphoreSlim_Wait_TimeoutWrong);
@@ -263,8 +261,8 @@ namespace System.Threading
public bool Wait(TimeSpan timeout, CancellationToken cancellationToken)
{
// Validate the timeout
- Int64 totalMilliseconds = (Int64)timeout.TotalMilliseconds;
- if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ long totalMilliseconds = (long)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
{
throw new System.ArgumentOutOfRangeException(
nameof(timeout), timeout, SR.SemaphoreSlim_Wait_TimeoutWrong);
@@ -333,27 +331,38 @@ namespace System.Threading
bool lockTaken = false;
//Register for cancellation outside of the main lock.
- //NOTE: Register/deregister inside the lock can deadlock as different lock acquisition orders could
+ //NOTE: Register/unregister inside the lock can deadlock as different lock acquisition orders could
// occur for (1)this.m_lockObj and (2)cts.internalLock
CancellationTokenRegistration cancellationTokenRegistration = cancellationToken.InternalRegisterWithoutEC(s_cancellationTokenCanceledEventHandler, this);
try
{
- // Perf: first spin wait for the count to be positive, but only up to the first planned yield.
- // This additional amount of spinwaiting in addition
- // to Monitor.Enter()’s spinwaiting has shown measurable perf gains in test scenarios.
- //
- SpinWait spin = new SpinWait();
- while (m_currentCount == 0 && !spin.NextSpinWillYield)
+ // Perf: first spin wait for the count to be positive.
+ // This additional amount of spinwaiting in addition
+ // to Monitor.Enter()’s spinwaiting has shown measurable perf gains in test scenarios.
+ if (m_currentCount == 0)
{
- spin.SpinOnce();
+ // Monitor.Enter followed by Monitor.Wait is much more expensive than waiting on an event as it involves another
+ // spin, contention, etc. The usual number of spin iterations that would otherwise be used here is increased to
+ // lessen that extra expense of doing a proper wait.
+ int spinCount = SpinWait.SpinCountforSpinBeforeWait * 4;
+
+ var spinner = new SpinWait();
+ while (spinner.Count < spinCount)
+ {
+ spinner.SpinOnce(sleep1Threshold: -1);
+
+ if (m_currentCount != 0)
+ {
+ break;
+ }
+ }
}
// entering the lock and incrementing waiters must not suffer a thread-abort, else we cannot
// clean up m_waitCount correctly, which may lead to deadlock due to non-woken waiters.
try { }
finally
{
- m_lock.Acquire();
- lockTaken = true;
+ Monitor.Enter(m_lockObj, ref lockTaken);
if (lockTaken)
{
m_waitCount++;
@@ -422,7 +431,7 @@ namespace System.Threading
if (lockTaken)
{
m_waitCount--;
- m_lock.Release();
+ Monitor.Exit(m_lockObj);
}
// Unregister the cancellation callback.
@@ -439,13 +448,13 @@ namespace System.Threading
}
/// <summary>
- /// Local helper function, waits on the monitor until the monitor recieves signal or the
+ /// Local helper function, waits on the monitor until the monitor receives signal or the
/// timeout is expired
/// </summary>
/// <param name="millisecondsTimeout">The maximum timeout</param>
/// <param name="startTime">The start ticks to calculate the elapsed time</param>
/// <param name="cancellationToken">The CancellationToken to observe.</param>
- /// <returns>true if the monitor recieved a signal, false if the timeout expired</returns>
+ /// <returns>true if the monitor received a signal, false if the timeout expired</returns>
private bool WaitUntilCountOrTimeout(int millisecondsTimeout, uint startTime, CancellationToken cancellationToken)
{
int remainingWaitMilliseconds = Timeout.Infinite;
@@ -466,7 +475,20 @@ namespace System.Threading
}
}
// ** the actual wait **
- if (!m_condition.Wait(remainingWaitMilliseconds))
+ bool waitSuccessful = Monitor.Wait(m_lockObj, remainingWaitMilliseconds);
+
+ // This waiter has woken up and this needs to be reflected in the count of waiters pulsed to wake. Since we
+ // don't have thread-specific pulse state, there is not enough information to tell whether this thread woke up
+ // because it was pulsed. For instance, this thread may have timed out and may have been waiting to reacquire
+ // the lock before returning from Monitor.Wait, in which case we don't know whether this thread got pulsed. So
+ // in any woken case, decrement the count if possible. As such, timeouts could cause more waiters to wake than
+ // necessary.
+ if (m_countOfWaitersPulsedToWake != 0)
+ {
+ --m_countOfWaitersPulsedToWake;
+ }
+
+ if (!waitSuccessful)
{
return false;
}
@@ -481,7 +503,7 @@ namespace System.Threading
/// <returns>A task that will complete when the semaphore has been entered.</returns>
public Task WaitAsync()
{
- return WaitAsync(Timeout.Infinite, default(CancellationToken));
+ return WaitAsync(Timeout.Infinite, default);
}
/// <summary>
@@ -518,7 +540,7 @@ namespace System.Threading
/// </exception>
public Task<bool> WaitAsync(int millisecondsTimeout)
{
- return WaitAsync(millisecondsTimeout, default(CancellationToken));
+ return WaitAsync(millisecondsTimeout, default);
}
/// <summary>
@@ -546,7 +568,7 @@ namespace System.Threading
/// </exception>
public Task<bool> WaitAsync(TimeSpan timeout)
{
- return WaitAsync(timeout, default(CancellationToken));
+ return WaitAsync(timeout, default);
}
/// <summary>
@@ -568,8 +590,8 @@ namespace System.Threading
public Task<bool> WaitAsync(TimeSpan timeout, CancellationToken cancellationToken)
{
// Validate the timeout
- Int64 totalMilliseconds = (Int64)timeout.TotalMilliseconds;
- if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ long totalMilliseconds = (long)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
{
throw new System.ArgumentOutOfRangeException(
nameof(timeout), timeout, SR.SemaphoreSlim_Wait_TimeoutWrong);
@@ -610,9 +632,9 @@ namespace System.Threading
// Bail early for cancellation
if (cancellationToken.IsCancellationRequested)
- return Task.FromCancellation<bool>(cancellationToken);
+ return Task.FromCanceled<bool>(cancellationToken);
- using (LockHolder.Hold(m_lock))
+ lock (m_lockObj)
{
// If there are counts available, allow this waiter to succeed.
if (m_currentCount > 0)
@@ -644,7 +666,7 @@ namespace System.Threading
/// <returns>The created task.</returns>
private TaskNode CreateAndAddAsyncWaiter()
{
- Debug.Assert(m_lock.IsAcquired, "Requires the lock be held");
+ Debug.Assert(Monitor.IsEntered(m_lockObj), "Requires the lock be held");
// Create the task
var task = new TaskNode();
@@ -674,7 +696,7 @@ namespace System.Threading
private bool RemoveAsyncWaiter(TaskNode task)
{
Debug.Assert(task != null, "Expected non-null task");
- Debug.Assert(m_lock.IsAcquired, "Requires the lock be held");
+ Debug.Assert(Monitor.IsEntered(m_lockObj), "Requires the lock be held");
// Is the task in the list? To be in the list, either it's the head or it has a predecessor that's in the list.
bool wasInList = m_asyncHead == task || task.Prev != null;
@@ -700,14 +722,14 @@ namespace System.Threading
private async Task<bool> WaitUntilCountOrTimeoutAsync(TaskNode asyncWaiter, int millisecondsTimeout, CancellationToken cancellationToken)
{
Debug.Assert(asyncWaiter != null, "Waiter should have been constructed");
- Debug.Assert(m_lock.IsAcquired, "Requires the lock be held");
+ Debug.Assert(Monitor.IsEntered(m_lockObj), "Requires the lock be held");
// Wait until either the task is completed, timeout occurs, or cancellation is requested.
// We need to ensure that the Task.Delay task is appropriately cleaned up if the await
// completes due to the asyncWaiter completing, so we use our own token that we can explicitly
// cancel, and we chain the caller's supplied token into it.
using (var cts = cancellationToken.CanBeCanceled ?
- CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, default(CancellationToken)) :
+ CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, default) :
new CancellationTokenSource())
{
var waitCompleted = Task.WhenAny(asyncWaiter, Task.Delay(millisecondsTimeout, cts.Token));
@@ -722,7 +744,7 @@ namespace System.Threading
// If the await completed synchronously, we still hold the lock. If it didn't,
// we no longer hold the lock. As such, acquire it.
- using (LockHolder.Hold(m_lock))
+ lock (m_lockObj)
{
// Remove the task from the list. If we're successful in doing so,
// we know that no one else has tried to complete this waiter yet,
@@ -773,7 +795,7 @@ namespace System.Threading
}
int returnCount;
- using (LockHolder.Hold(m_lock))
+ lock (m_lockObj)
{
// Read the m_currentCount into a local variable to avoid unnecessary volatile accesses inside the lock.
int currentCount = m_currentCount;
@@ -788,13 +810,27 @@ namespace System.Threading
// Increment the count by the actual release count
currentCount += releaseCount;
- // Signal to any synchronous waiters
+ // Signal to any synchronous waiters, taking into account how many waiters have previously been pulsed to wake
+ // but have not yet woken
int waitCount = m_waitCount;
-
- int waitersToNotify = Math.Min(releaseCount, waitCount);
- for (int i = 0; i < waitersToNotify; i++)
+ Debug.Assert(m_countOfWaitersPulsedToWake <= waitCount);
+ int waitersToNotify = Math.Min(currentCount, waitCount) - m_countOfWaitersPulsedToWake;
+ if (waitersToNotify > 0)
{
- m_condition.SignalOne();
+ // Ideally, limiting to a maximum of releaseCount would not be necessary and could be an assert instead, but
+ // since WaitUntilCountOrTimeout() does not have enough information to tell whether a woken thread was
+ // pulsed, it's possible for m_countOfWaitersPulsedToWake to be less than the number of threads that have
+ // actually been pulsed to wake.
+ if (waitersToNotify > releaseCount)
+ {
+ waitersToNotify = releaseCount;
+ }
+
+ m_countOfWaitersPulsedToWake += waitersToNotify;
+ for (int i = 0; i < waitersToNotify; i++)
+ {
+ Monitor.Pulse(m_lockObj);
+ }
}
// Now signal to any asynchronous waiters, if there are any. While we've already
@@ -861,7 +897,7 @@ namespace System.Threading
/// <param name="disposing">true to release both managed and unmanaged resources;
/// false to release only unmanaged resources.</param>
/// <remarks>
- /// Unlike most of the members of <see cref="SemaphoreSlim"/>, <see cref="Dispose(Boolean)"/> is not
+ /// Unlike most of the members of <see cref="SemaphoreSlim"/>, <see cref="Dispose(bool)"/> is not
/// thread-safe and may not be used concurrently with other members of this instance.
/// </remarks>
protected virtual void Dispose(bool disposing)
@@ -873,15 +909,12 @@ namespace System.Threading
m_waitHandle.Dispose();
m_waitHandle = null;
}
- m_lock = null;
- m_condition = null;
+ m_lockObj = null;
m_asyncHead = null;
m_asyncTail = null;
}
}
-
-
/// <summary>
/// Private helper method to wake up waiters when a cancellationToken gets canceled.
/// </summary>
@@ -890,9 +923,9 @@ namespace System.Threading
{
SemaphoreSlim semaphore = obj as SemaphoreSlim;
Debug.Assert(semaphore != null, "Expected a SemaphoreSlim");
- using (LockHolder.Hold(semaphore.m_lock))
+ lock (semaphore.m_lockObj)
{
- semaphore.m_condition.SignalAll(); //wake up all waiters.
+ Monitor.PulseAll(semaphore.m_lockObj); //wake up all waiters.
}
}
@@ -902,15 +935,11 @@ namespace System.Threading
/// </summary>
private void CheckDispose()
{
- if (m_lock == null)
+ if (m_lockObj == null)
{
throw new ObjectDisposedException(null, SR.SemaphoreSlim_Disposed);
}
}
- /// <summary>
- /// local helper function to retrieve the exception string message from the resource file
- /// </summary>
- /// <param name="str">The key string</param>
#endregion
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/SendOrPostCallback.cs b/src/System.Private.CoreLib/shared/System/Threading/SendOrPostCallback.cs
index 6692d35ab..b96914ab2 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/SendOrPostCallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/SendOrPostCallback.cs
@@ -4,5 +4,5 @@
namespace System.Threading
{
- public delegate void SendOrPostCallback(Object state);
+ public delegate void SendOrPostCallback(object state);
}
diff --git a/src/System.Private.CoreLib/src/System/Threading/SpinLock.cs b/src/System.Private.CoreLib/shared/System/Threading/SpinLock.cs
index f949896e2..2b0610539 100644
--- a/src/System.Private.CoreLib/src/System/Threading/SpinLock.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/SpinLock.cs
@@ -12,12 +12,8 @@
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
using System.Diagnostics;
-using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
-using Internal.Runtime.Augments;
-using Internal.Threading.Tracing;
-
namespace System.Threading
{
/// <summary>
@@ -66,35 +62,28 @@ namespace System.Threading
//
// There are several masks and constants below for convenience.
- private volatile int m_owner;
-
- // The multiplier factor for the each spinning iteration
- // This number has been chosen after trying different numbers on different CPUs (4, 8 and 16 ) and this provided the best results
- private const int SPINNING_FACTOR = 100;
+ private volatile int _owner;
// After how many yields, call Sleep(1)
private const int SLEEP_ONE_FREQUENCY = 40;
- // After how many yields, call Sleep(0)
- private const int SLEEP_ZERO_FREQUENCY = 10;
-
// After how many yields, check the timeout
private const int TIMEOUT_CHECK_FREQUENCY = 10;
// Thr thread tracking disabled mask
- private const int LOCK_ID_DISABLE_MASK = unchecked((int)0x80000000); //1000 0000 0000 0000 0000 0000 0000 0000
+ private const int LOCK_ID_DISABLE_MASK = unchecked((int)0x80000000); // 1000 0000 0000 0000 0000 0000 0000 0000
//the lock is held by some thread, but we don't know which
- private const int LOCK_ANONYMOUS_OWNED = 0x1; //0000 0000 0000 0000 0000 0000 0000 0001
+ private const int LOCK_ANONYMOUS_OWNED = 0x1; // 0000 0000 0000 0000 0000 0000 0000 0001
// Waiters mask if the thread tracking is disabled
- private const int WAITERS_MASK = ~(LOCK_ID_DISABLE_MASK | 1); //0111 1111 1111 1111 1111 1111 1111 1110
+ private const int WAITERS_MASK = ~(LOCK_ID_DISABLE_MASK | 1); // 0111 1111 1111 1111 1111 1111 1111 1110
// The Thread tacking is disabled and the lock bit is set, used in Enter fast path to make sure the id is disabled and lock is available
- private const int ID_DISABLED_AND_ANONYMOUS_OWNED = unchecked((int)0x80000001); //1000 0000 0000 0000 0000 0000 0000 0001
+ private const int ID_DISABLED_AND_ANONYMOUS_OWNED = unchecked((int)0x80000001); // 1000 0000 0000 0000 0000 0000 0000 0001
// If the thread is unowned if:
- // m_owner zero and the threa tracking is enabled
+ // m_owner zero and the thread tracking is enabled
// m_owner & LOCK_ANONYMOUS_OWNED = zero and the thread tracking is disabled
private const int LOCK_UNOWNED = 0;
@@ -104,7 +93,7 @@ namespace System.Threading
private static int MAXIMUM_WAITERS = WAITERS_MASK;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private int CompareExchange(ref int location, int value, int comparand, ref bool success)
+ private static int CompareExchange(ref int location, int value, int comparand, ref bool success)
{
int result = Interlocked.CompareExchange(ref location, value, comparand);
success = (result == comparand);
@@ -122,10 +111,10 @@ namespace System.Threading
/// purposes.</param>
public SpinLock(bool enableThreadOwnerTracking)
{
- m_owner = LOCK_UNOWNED;
+ _owner = LOCK_UNOWNED;
if (!enableThreadOwnerTracking)
{
- m_owner |= LOCK_ID_DISABLE_MASK;
+ _owner |= LOCK_ID_DISABLE_MASK;
Debug.Assert(!IsThreadOwnerTrackingEnabled, "property should be false by now");
}
}
@@ -159,11 +148,11 @@ namespace System.Threading
/// </exception>
public void Enter(ref bool lockTaken)
{
- //Try to keep the code and branching in this method as small as possible in order to inline the method
- int observedOwner = m_owner;
- if (lockTaken || //invalid parameter
- (observedOwner & ID_DISABLED_AND_ANONYMOUS_OWNED) != LOCK_ID_DISABLE_MASK || //thread tracking is enabled or the lock is already acquired
- CompareExchange(ref m_owner, observedOwner | LOCK_ANONYMOUS_OWNED, observedOwner, ref lockTaken) != observedOwner) //acquiring the lock failed
+ // Try to keep the code and branching in this method as small as possible in order to inline the method
+ int observedOwner = _owner;
+ if (lockTaken || // invalid parameter
+ (observedOwner & ID_DISABLED_AND_ANONYMOUS_OWNED) != LOCK_ID_DISABLE_MASK || // thread tracking is enabled or the lock is already acquired
+ CompareExchange(ref _owner, observedOwner | LOCK_ANONYMOUS_OWNED, observedOwner, ref lockTaken) != observedOwner) //acquiring the lock failed
ContinueTryEnter(Timeout.Infinite, ref lockTaken); // Then try the slow path if any of the above conditions is met
}
@@ -187,7 +176,7 @@ namespace System.Threading
/// </exception>
public void TryEnter(ref bool lockTaken)
{
- int observedOwner = m_owner;
+ int observedOwner = _owner;
if (((observedOwner & LOCK_ID_DISABLE_MASK) == 0) | lockTaken)
{
// Thread tracking enabled or invalid arg. Take slow path.
@@ -201,7 +190,7 @@ namespace System.Threading
else
{
// Lock wasn't held; try to acquire it.
- CompareExchange(ref m_owner, observedOwner | LOCK_ANONYMOUS_OWNED, observedOwner, ref lockTaken);
+ CompareExchange(ref _owner, observedOwner | LOCK_ANONYMOUS_OWNED, observedOwner, ref lockTaken);
}
}
@@ -234,7 +223,7 @@ namespace System.Threading
public void TryEnter(TimeSpan timeout, ref bool lockTaken)
{
// Validate the timeout
- Int64 totalMilliseconds = (Int64)timeout.TotalMilliseconds;
+ long totalMilliseconds = (long)timeout.TotalMilliseconds;
if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
{
throw new System.ArgumentOutOfRangeException(
@@ -269,18 +258,18 @@ namespace System.Threading
/// a negative number other than -1, which represents an infinite time-out.</exception>
public void TryEnter(int millisecondsTimeout, ref bool lockTaken)
{
- int observedOwner = m_owner;
+ int observedOwner = _owner;
if (millisecondsTimeout < -1 || //invalid parameter
lockTaken || //invalid parameter
(observedOwner & ID_DISABLED_AND_ANONYMOUS_OWNED) != LOCK_ID_DISABLE_MASK || //thread tracking is enabled or the lock is already acquired
- CompareExchange(ref m_owner, observedOwner | LOCK_ANONYMOUS_OWNED, observedOwner, ref lockTaken) != observedOwner) // acquiring the lock failed
+ CompareExchange(ref _owner, observedOwner | LOCK_ANONYMOUS_OWNED, observedOwner, ref lockTaken) != observedOwner) // acquiring the lock failed
ContinueTryEnter(millisecondsTimeout, ref lockTaken); // The call the slow pth
}
/// <summary>
/// Try acquire the lock with long path, this is usually called after the first path in Enter and
/// TryEnter failed The reason for short path is to make it inline in the run time which improves the
- /// performance. This method assumed that the parameter are validated in Enter ir TryENter method
+ /// performance. This method assumed that the parameter are validated in Enter or TryEnter method.
/// </summary>
/// <param name="millisecondsTimeout">The timeout milliseconds</param>
/// <param name="lockTaken">The lockTaken param</param>
@@ -290,7 +279,7 @@ namespace System.Threading
if (lockTaken)
{
lockTaken = false;
- throw new System.ArgumentException(SR.SpinLock_TryReliableEnter_ArgumentException);
+ throw new ArgumentException(SR.SpinLock_TryReliableEnter_ArgumentException);
}
if (millisecondsTimeout < -1)
@@ -305,11 +294,6 @@ namespace System.Threading
startTime = TimeoutHelper.GetTime();
}
- if (SpinLockTrace.Enabled)
- {
- SpinLockTrace.SpinLock_FastPathFailed(m_owner);
- }
-
if (IsThreadOwnerTrackingEnabled)
{
// Slow path for enabled thread tracking mode
@@ -332,10 +316,10 @@ namespace System.Threading
//***Step 1, take the lock or update the waiters
// try to acquire the lock directly if possible or update the waiters count
- observedOwner = m_owner;
+ observedOwner = _owner;
if ((observedOwner & LOCK_ANONYMOUS_OWNED) == LOCK_UNOWNED)
{
- if (CompareExchange(ref m_owner, observedOwner | 1, observedOwner, ref lockTaken) == observedOwner)
+ if (CompareExchange(ref _owner, observedOwner | 1, observedOwner, ref lockTaken) == observedOwner)
{
// Acquired lock
return;
@@ -352,89 +336,50 @@ namespace System.Threading
// Did not acquire lock as owned and timeout is 0 so fail fast
return;
}
- else //failed to acquire the lock,then try to update the waiters. If the waiters count reached the maximum, jsut break the loop to avoid overflow
+ else //failed to acquire the lock, then try to update the waiters. If the waiters count reached the maximum, just break the loop to avoid overflow
{
if ((observedOwner & WAITERS_MASK) != MAXIMUM_WAITERS)
- turn = (Interlocked.Add(ref m_owner, 2) & WAITERS_MASK) >> 1;
- }
-
- //***Step 2. Spinning
- //lock acquired failed and waiters updated
- int processorCount = PlatformHelper.ProcessorCount;
- if (turn < processorCount)
- {
- int processFactor = 1;
- for (int i = 1; i <= turn * SPINNING_FACTOR; i++)
- {
- RuntimeThread.SpinWait((turn + i) * SPINNING_FACTOR * processFactor);
- if (processFactor < processorCount)
- processFactor++;
- observedOwner = m_owner;
- if ((observedOwner & LOCK_ANONYMOUS_OWNED) == LOCK_UNOWNED)
- {
- int newOwner = (observedOwner & WAITERS_MASK) == 0 ? // Gets the number of waiters, if zero
- observedOwner | 1 // don't decrement it. just set the lock bit, it is zzero because a previous call of Exit(false) ehich corrupted the waiters
- : (observedOwner - 2) | 1; // otherwise decrement the waiters and set the lock bit
- Debug.Assert((newOwner & WAITERS_MASK) >= 0);
-
- if (CompareExchange(ref m_owner, newOwner, observedOwner, ref lockTaken) == observedOwner)
- {
- return;
- }
- }
- }
-
- // Check the timeout.
- if (millisecondsTimeout != Timeout.Infinite && TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) <= 0)
{
- DecrementWaiters();
- return;
+ // This can still overflow, but maybe there will never be that many waiters
+ turn = (Interlocked.Add(ref _owner, 2) & WAITERS_MASK) >> 1;
}
}
- //*** Step 3, Yielding
- //Sleep(1) every 50 yields
- int yieldsoFar = 0;
+ // lock acquired failed and waiters updated
+
+ //*** Step 2, Spinning and Yielding
+ var spinner = new SpinWait();
+ if (turn > PlatformHelper.ProcessorCount)
+ {
+ spinner.Count = SpinWait.YieldThreshold;
+ }
while (true)
{
- observedOwner = m_owner;
+ spinner.SpinOnce(SLEEP_ONE_FREQUENCY);
+
+ observedOwner = _owner;
if ((observedOwner & LOCK_ANONYMOUS_OWNED) == LOCK_UNOWNED)
{
int newOwner = (observedOwner & WAITERS_MASK) == 0 ? // Gets the number of waiters, if zero
- observedOwner | 1 // don't decrement it. just set the lock bit, it is zzero because a previous call of Exit(false) ehich corrupted the waiters
+ observedOwner | 1 // don't decrement it. just set the lock bit, it is zero because a previous call of Exit(false) which corrupted the waiters
: (observedOwner - 2) | 1; // otherwise decrement the waiters and set the lock bit
Debug.Assert((newOwner & WAITERS_MASK) >= 0);
- if (CompareExchange(ref m_owner, newOwner, observedOwner, ref lockTaken) == observedOwner)
+ if (CompareExchange(ref _owner, newOwner, observedOwner, ref lockTaken) == observedOwner)
{
return;
}
}
- if (yieldsoFar % SLEEP_ONE_FREQUENCY == 0)
- {
- RuntimeThread.Sleep(1);
- }
- else if (yieldsoFar % SLEEP_ZERO_FREQUENCY == 0)
- {
- RuntimeThread.Sleep(0);
- }
- else
- {
- RuntimeThread.Yield();
- }
-
- if (yieldsoFar % TIMEOUT_CHECK_FREQUENCY == 0)
+ if (spinner.Count % TIMEOUT_CHECK_FREQUENCY == 0)
{
- //Check the timeout.
+ // Check the timeout.
if (millisecondsTimeout != Timeout.Infinite && TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) <= 0)
{
DecrementWaiters();
return;
}
}
-
- yieldsoFar++;
}
}
@@ -446,9 +391,9 @@ namespace System.Threading
SpinWait spinner = new SpinWait();
while (true)
{
- int observedOwner = m_owner;
+ int observedOwner = _owner;
if ((observedOwner & WAITERS_MASK) == 0) return; // don't decrement the waiters if it's corrupted by previous call of Exit(false)
- if (Interlocked.CompareExchange(ref m_owner, observedOwner - 2, observedOwner) == observedOwner)
+ if (Interlocked.CompareExchange(ref _owner, observedOwner - 2, observedOwner) == observedOwner)
{
Debug.Assert(!IsThreadOwnerTrackingEnabled); // Make sure the waiters never be negative which will cause the thread tracking bit to be flipped
break;
@@ -467,8 +412,8 @@ namespace System.Threading
int lockUnowned = 0;
// We are using thread IDs to mark ownership. Snap the thread ID and check for recursion.
// We also must or the ID enablement bit, to ensure we propagate when we CAS it in.
- int m_newOwner = Environment.CurrentManagedThreadId;
- if (m_owner == m_newOwner)
+ int newOwner = Environment.CurrentManagedThreadId;
+ if (_owner == newOwner)
{
// We don't allow lock recursion.
throw new LockRecursionException(SR.SpinLock_TryEnter_LockRecursionException);
@@ -486,9 +431,9 @@ namespace System.Threading
// Test before trying to CAS, to avoid acquiring the line exclusively unnecessarily.
- if (m_owner == lockUnowned)
+ if (_owner == lockUnowned)
{
- if (CompareExchange(ref m_owner, m_newOwner, lockUnowned, ref lockTaken) == lockUnowned)
+ if (CompareExchange(ref _owner, newOwner, lockUnowned, ref lockTaken) == lockUnowned)
{
return;
}
@@ -508,7 +453,7 @@ namespace System.Threading
/// </summary>
/// <remarks>
/// The default overload of <see cref="Exit()"/> provides the same behavior as if calling <see
- /// cref="Exit(Boolean)"/> using true as the argument, but Exit() could be slightly faster than Exit(true).
+ /// cref="Exit(bool)"/> using true as the argument, but Exit() could be slightly faster than Exit(true).
/// </remarks>
/// <exception cref="SynchronizationLockException">
/// Thread ownership tracking is enabled, and the current thread is not the owner of this lock.
@@ -516,10 +461,10 @@ namespace System.Threading
public void Exit()
{
//This is the fast path for the thread tracking is disabled, otherwise go to the slow path
- if ((m_owner & LOCK_ID_DISABLE_MASK) == 0)
+ if ((_owner & LOCK_ID_DISABLE_MASK) == 0)
ExitSlowPath(true);
else
- Interlocked.Decrement(ref m_owner);
+ Interlocked.Decrement(ref _owner);
}
/// <summary>
@@ -530,7 +475,7 @@ namespace System.Threading
/// publish the exit operation to other threads.
/// </param>
/// <remarks>
- /// Calling <see cref="Exit(Boolean)"/> with the <paramref name="useMemoryBarrier"/> argument set to
+ /// Calling <see cref="Exit(bool)"/> with the <paramref name="useMemoryBarrier"/> argument set to
/// true will improve the fairness of the lock at the expense of some performance. The default <see
/// cref="Enter"/>
/// overload behaves as if specifying true for <paramref name="useMemoryBarrier"/>.
@@ -540,16 +485,18 @@ namespace System.Threading
/// </exception>
public void Exit(bool useMemoryBarrier)
{
- // This is the fast path for the thread tracking is diabled and not to use memory barrier, otherwise go to the slow path
- // The reason not to add else statement if the usememorybarrier is that it will add more barnching in the code and will prevent
+ // This is the fast path for the thread tracking is disabled and not to use memory barrier, otherwise go to the slow path
+ // The reason not to add else statement if the usememorybarrier is that it will add more branching in the code and will prevent
// method inlining, so this is optimized for useMemoryBarrier=false and Exit() overload optimized for useMemoryBarrier=true.
- int tmpOwner = m_owner;
+ int tmpOwner = _owner;
if ((tmpOwner & LOCK_ID_DISABLE_MASK) != 0 & !useMemoryBarrier)
{
- m_owner = tmpOwner & (~LOCK_ANONYMOUS_OWNED);
+ _owner = tmpOwner & (~LOCK_ANONYMOUS_OWNED);
}
else
+ {
ExitSlowPath(useMemoryBarrier);
+ }
}
/// <summary>
@@ -561,28 +508,33 @@ namespace System.Threading
/// </param>
private void ExitSlowPath(bool useMemoryBarrier)
{
- bool threadTrackingEnabled = (m_owner & LOCK_ID_DISABLE_MASK) == 0;
+ bool threadTrackingEnabled = (_owner & LOCK_ID_DISABLE_MASK) == 0;
if (threadTrackingEnabled && !IsHeldByCurrentThread)
{
- throw new System.Threading.SynchronizationLockException(
- SR.SpinLock_Exit_SynchronizationLockException);
+ throw new SynchronizationLockException(SR.SpinLock_Exit_SynchronizationLockException);
}
if (useMemoryBarrier)
{
if (threadTrackingEnabled)
- Interlocked.Exchange(ref m_owner, LOCK_UNOWNED);
+ {
+ Interlocked.Exchange(ref _owner, LOCK_UNOWNED);
+ }
else
- Interlocked.Decrement(ref m_owner);
+ {
+ Interlocked.Decrement(ref _owner);
+ }
}
else
{
if (threadTrackingEnabled)
- m_owner = LOCK_UNOWNED;
+ {
+ _owner = LOCK_UNOWNED;
+ }
else
{
- int tmpOwner = m_owner;
- m_owner = tmpOwner & (~LOCK_ANONYMOUS_OWNED);
+ int tmpOwner = _owner;
+ _owner = tmpOwner & (~LOCK_ANONYMOUS_OWNED);
}
}
}
@@ -595,9 +547,9 @@ namespace System.Threading
get
{
if (IsThreadOwnerTrackingEnabled)
- return m_owner != LOCK_UNOWNED;
+ return _owner != LOCK_UNOWNED;
- return (m_owner & LOCK_ANONYMOUS_OWNED) != LOCK_UNOWNED;
+ return (_owner & LOCK_ANONYMOUS_OWNED) != LOCK_UNOWNED;
}
}
@@ -623,15 +575,12 @@ namespace System.Threading
{
throw new InvalidOperationException(SR.SpinLock_IsHeldByCurrentThread);
}
- return ((m_owner & (~LOCK_ID_DISABLE_MASK)) == Environment.CurrentManagedThreadId);
+ return ((_owner & (~LOCK_ID_DISABLE_MASK)) == Environment.CurrentManagedThreadId);
}
}
/// <summary>Gets whether thread ownership tracking is enabled for this instance.</summary>
- public bool IsThreadOwnerTrackingEnabled
- {
- get { return (m_owner & LOCK_ID_DISABLE_MASK) == 0; }
- }
+ public bool IsThreadOwnerTrackingEnabled => (_owner & LOCK_ID_DISABLE_MASK) == 0;
#region Debugger proxy class
/// <summary>
@@ -640,7 +589,7 @@ namespace System.Threading
internal class SystemThreading_SpinLockDebugView
{
// SpinLock object
- private SpinLock m_spinLock;
+ private SpinLock _spinLock;
/// <summary>
/// SystemThreading_SpinLockDebugView constructor
@@ -649,7 +598,7 @@ namespace System.Threading
public SystemThreading_SpinLockDebugView(SpinLock spinLock)
{
// Note that this makes a copy of the SpinLock (struct). It doesn't hold a reference to it.
- m_spinLock = spinLock;
+ _spinLock = spinLock;
}
/// <summary>
@@ -661,7 +610,7 @@ namespace System.Threading
{
try
{
- return m_spinLock.IsHeldByCurrentThread;
+ return _spinLock.IsHeldByCurrentThread;
}
catch (InvalidOperationException)
{
@@ -677,9 +626,9 @@ namespace System.Threading
{
get
{
- if (m_spinLock.IsThreadOwnerTrackingEnabled)
+ if (_spinLock.IsThreadOwnerTrackingEnabled)
{
- return m_spinLock.m_owner;
+ return _spinLock._owner;
}
else
{
@@ -692,10 +641,7 @@ namespace System.Threading
/// <summary>
/// Gets whether the lock is currently held by any thread or not.
/// </summary>
- public bool IsHeld
- {
- get { return m_spinLock.IsHeld; }
- }
+ public bool IsHeld => _spinLock.IsHeld;
}
#endregion
diff --git a/src/System.Private.CoreLib/shared/System/Threading/SpinWait.cs b/src/System.Private.CoreLib/shared/System/Threading/SpinWait.cs
index 414ad1852..54857c322 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/SpinWait.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/SpinWait.cs
@@ -88,7 +88,16 @@ namespace System.Threading
/// for here.
/// </remarks>
internal static readonly int SpinCountforSpinBeforeWait = PlatformHelper.IsSingleProcessor ? 1 : 35;
- internal const int Sleep1ThresholdForSpinBeforeWait = 40; // should be greater than SpinCountforSpinBeforeWait
+
+ /// <summary>
+ /// Typically, Sleep(1) should not be issued for a spin-wait before a proper wait because it is usually more beneficial
+ /// to just issue the proper wait. For longer spin-waits (when the spin count is configurable), this value may be used as
+ /// a threshold for issuing Sleep(1).
+ /// </summary>
+ /// <remarks>
+ /// Should be greater than <see cref="SpinCountforSpinBeforeWait"/> so that Sleep(1) would not be used by default.
+ /// </remarks>
+ internal const int Sleep1ThresholdForLongSpinBeforeWait = 40;
// The number of times we've spun already.
private int _count;
@@ -127,12 +136,42 @@ namespace System.Threading
/// </remarks>
public void SpinOnce()
{
- SpinOnce(DefaultSleep1Threshold);
+ SpinOnceCore(DefaultSleep1Threshold);
+ }
+
+ /// <summary>
+ /// Performs a single spin.
+ /// </summary>
+ /// <param name="sleep1Threshold">
+ /// A minimum spin count after which <code>Thread.Sleep(1)</code> may be used. A value of <code>-1</code> may be used to
+ /// disable the use of <code>Thread.Sleep(1)</code>.
+ /// </param>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// <paramref name="sleep1Threshold"/> is less than <code>-1</code>.
+ /// </exception>
+ /// <remarks>
+ /// This is typically called in a loop, and may change in behavior based on the number of times a
+ /// <see cref="SpinOnce"/> has been called thus far on this instance.
+ /// </remarks>
+ public void SpinOnce(int sleep1Threshold)
+ {
+ if (sleep1Threshold < -1)
+ {
+ throw new ArgumentOutOfRangeException(nameof(sleep1Threshold), sleep1Threshold, SR.ArgumentOutOfRange_NeedNonNegOrNegative1);
+ }
+
+ if (sleep1Threshold >= 0 && sleep1Threshold < YieldThreshold)
+ {
+ sleep1Threshold = YieldThreshold;
+ }
+
+ SpinOnceCore(sleep1Threshold);
}
- internal void SpinOnce(int sleep1Threshold)
+ private void SpinOnceCore(int sleep1Threshold)
{
- Debug.Assert(sleep1Threshold >= YieldThreshold || PlatformHelper.IsSingleProcessor); // so that NextSpinWillYield behaves as requested
+ Debug.Assert(sleep1Threshold >= -1);
+ Debug.Assert(sleep1Threshold < 0 || sleep1Threshold >= YieldThreshold);
// (_count - YieldThreshold) % 2 == 0: The purpose of this check is to interleave Thread.Yield/Sleep(0) with
// Thread.SpinWait. Otherwise, the following issues occur:
@@ -145,7 +184,7 @@ namespace System.Threading
// contention), they may switch between one another, delaying work that can make progress.
if ((
_count >= YieldThreshold &&
- (_count >= sleep1Threshold || (_count - YieldThreshold) % 2 == 0)
+ ((_count >= sleep1Threshold && sleep1Threshold >= 0) || (_count - YieldThreshold) % 2 == 0)
) ||
PlatformHelper.IsSingleProcessor)
{
@@ -164,7 +203,7 @@ namespace System.Threading
// configured to use the (default) coarse-grained system timer.
//
- if (_count >= sleep1Threshold)
+ if (_count >= sleep1Threshold && sleep1Threshold >= 0)
{
RuntimeThread.Sleep(1);
}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/SynchronizationLockException.cs b/src/System.Private.CoreLib/shared/System/Threading/SynchronizationLockException.cs
index e050e1539..3b5d31f3c 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/SynchronizationLockException.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/SynchronizationLockException.cs
@@ -26,13 +26,13 @@ namespace System.Threading
HResult = HResults.COR_E_SYNCHRONIZATIONLOCK;
}
- public SynchronizationLockException(String message)
+ public SynchronizationLockException(string message)
: base(message)
{
HResult = HResults.COR_E_SYNCHRONIZATIONLOCK;
}
- public SynchronizationLockException(String message, Exception innerException)
+ public SynchronizationLockException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_SYNCHRONIZATIONLOCK;
diff --git a/src/System.Private.CoreLib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs
index b30ff63db..baf0a5025 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs
@@ -5,7 +5,6 @@
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
//
-
//
// A pair of schedulers that together support concurrent (reader) / exclusive (writer)
// task scheduling. Using just the exclusive scheduler can be used to simulate a serial
@@ -19,6 +18,8 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
+using Thread = Internal.Runtime.Augments.RuntimeThread;
+
namespace System.Threading.Tasks
{
/// <summary>
@@ -39,10 +40,10 @@ namespace System.Threading.Tasks
private readonly TaskScheduler m_underlyingTaskScheduler;
/// <summary>
/// The maximum number of tasks allowed to run concurrently. This only applies to concurrent tasks,
- /// since exlusive tasks are inherently limited to 1.
+ /// since exclusive tasks are inherently limited to 1.
/// </summary>
private readonly int m_maxConcurrencyLevel;
- /// <summary>The maximum number of tasks we can process before recyling our runner tasks.</summary>
+ /// <summary>The maximum number of tasks we can process before recycling our runner tasks.</summary>
private readonly int m_maxItemsPerTask;
/// <summary>
/// If positive, it represents the number of concurrently running concurrent tasks.
@@ -61,10 +62,10 @@ namespace System.Threading.Tasks
/// <summary>Default MaxItemsPerTask to use for processing if none is specified.</summary>
private const int DEFAULT_MAXITEMSPERTASK = UNLIMITED_PROCESSING;
/// <summary>Default MaxConcurrencyLevel is the processor count if not otherwise specified.</summary>
- private static Int32 DefaultMaxConcurrencyLevel { get { return Environment.ProcessorCount; } }
+ private static int DefaultMaxConcurrencyLevel { get { return Environment.ProcessorCount; } }
/// <summary>Gets the sync obj used to protect all state on this instance.</summary>
- private readonly Lock ValueLock = new Lock();
+ private object ValueLock { get { return m_threadProcessingMode; } }
/// <summary>
/// Initializes the ConcurrentExclusiveSchedulerPair.
@@ -115,8 +116,8 @@ namespace System.Threading.Tasks
// Treat UNLIMITED_PROCESSING/-1 for both MCL and MIPT as the biggest possible value so that we don't
// have to special case UNLIMITED_PROCESSING later on in processing.
- if (m_maxConcurrencyLevel == UNLIMITED_PROCESSING) m_maxConcurrencyLevel = Int32.MaxValue;
- if (m_maxItemsPerTask == UNLIMITED_PROCESSING) m_maxItemsPerTask = Int32.MaxValue;
+ if (m_maxConcurrencyLevel == UNLIMITED_PROCESSING) m_maxConcurrencyLevel = int.MaxValue;
+ if (m_maxItemsPerTask == UNLIMITED_PROCESSING) m_maxItemsPerTask = int.MaxValue;
// Create the concurrent/exclusive schedulers for this pair
m_exclusiveTaskScheduler = new ConcurrentExclusiveTaskScheduler(this, 1, ProcessingMode.ProcessingExclusiveTask);
@@ -130,7 +131,7 @@ namespace System.Threading.Tasks
/// </remarks>
public void Complete()
{
- using (LockHolder.Hold(ValueLock))
+ lock (ValueLock)
{
if (!CompletionRequested)
{
@@ -210,19 +211,21 @@ namespace System.Threading.Tasks
cs.m_completionQueued = true;
ThreadPool.QueueUserWorkItem(state =>
{
- var localCs = (CompletionState)state; // don't use 'cs', as it'll force a closure
- Debug.Assert(!localCs.Task.IsCompleted, "Completion should only happen once.");
+ var localThis = (ConcurrentExclusiveSchedulerPair)state;
+ Debug.Assert(!localThis.m_completionState.Task.IsCompleted, "Completion should only happen once.");
- var exceptions = localCs.m_exceptions;
+ List<Exception> exceptions = localThis.m_completionState.m_exceptions;
bool success = (exceptions != null && exceptions.Count > 0) ?
- localCs.TrySetException(exceptions) :
- localCs.TrySetResult(default(VoidTaskResult));
+ localThis.m_completionState.TrySetException(exceptions) :
+ localThis.m_completionState.TrySetResult(default);
Debug.Assert(success, "Expected to complete completion task.");
- }, cs);
+
+ localThis.m_threadProcessingMode.Dispose();
+ }, this);
}
}
- /// <summary>Initiatites scheduler shutdown due to a worker task faulting..</summary>
+ /// <summary>Initiates scheduler shutdown due to a worker task faulting.</summary>
/// <param name="faultedTask">The faulted worker task that's initiating the shutdown.</param>
private void FaultWithTask(Task faultedTask)
{
@@ -232,7 +235,7 @@ namespace System.Threading.Tasks
// Store the faulted task's exceptions
var cs = EnsureCompletionStateInitialized();
- if (cs.m_exceptions == null) cs.m_exceptions = new LowLevelListWithIList<Exception>();
+ if (cs.m_exceptions == null) cs.m_exceptions = new List<Exception>();
cs.m_exceptions.AddRange(faultedTask.Exception.InnerExceptions);
// Now that we're doomed, request completion
@@ -292,7 +295,7 @@ namespace System.Threading.Tasks
try
{
processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair).ProcessExclusiveTasks(), this,
- default(CancellationToken), GetCreationOptionsForTask(fairly));
+ default, GetCreationOptionsForTask(fairly));
processingTask.Start(m_underlyingTaskScheduler);
// When we call Start, if the underlying scheduler throws in QueueTask, TPL will fault the task and rethrow
// the exception. To deal with that, we need a reference to the task object, so that we can observe its exception.
@@ -319,7 +322,7 @@ namespace System.Threading.Tasks
try
{
processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair).ProcessConcurrentTasks(), this,
- default(CancellationToken), GetCreationOptionsForTask(fairly));
+ default, GetCreationOptionsForTask(fairly));
processingTask.Start(m_underlyingTaskScheduler); // See above logic for why we use new + Start rather than StartNew
}
catch
@@ -372,7 +375,7 @@ namespace System.Threading.Tasks
"Somehow we ended up escaping exclusive mode.");
m_threadProcessingMode.Value = ProcessingMode.NotCurrentlyProcessing;
- using (LockHolder.Hold(ValueLock))
+ lock (ValueLock)
{
// When this task was launched, we tracked it by setting m_processingCount to WRITER_IN_PROGRESS.
// now reset it to 0. Then check to see whether there's more processing to be done.
@@ -419,7 +422,7 @@ namespace System.Threading.Tasks
// before entering the loop an exclusive task arrives. If we didn't execute at
// least one task, we would have spent all of the overhead to launch a
// task but with none of the benefit. There's of course also an inherent
- // race here with regards to exclusive tasks arriving, and we're ok with
+ // race condition here with regards to exclusive tasks arriving, and we're ok with
// executing one more concurrent task than we should before giving priority to exclusive tasks.
if (!m_exclusiveTaskScheduler.m_tasks.IsEmpty) break;
}
@@ -431,7 +434,7 @@ namespace System.Threading.Tasks
"Somehow we ended up escaping concurrent mode.");
m_threadProcessingMode.Value = ProcessingMode.NotCurrentlyProcessing;
- using (LockHolder.Hold(ValueLock))
+ lock (ValueLock)
{
// When this task was launched, we tracked it with a positive processing count;
// decrement that count. Then check to see whether there's more processing to be done.
@@ -461,7 +464,7 @@ namespace System.Threading.Tasks
/// <summary>Whether completion processing has been queued.</summary>
internal bool m_completionQueued;
/// <summary>Unrecoverable exceptions incurred while processing.</summary>
- internal LowLevelListWithIList<Exception> m_exceptions;
+ internal List<Exception> m_exceptions;
}
/// <summary>
@@ -512,7 +515,7 @@ namespace System.Threading.Tasks
protected internal override void QueueTask(Task task)
{
Debug.Assert(task != null, "Infrastructure should have provided a non-null task.");
- using (LockHolder.Hold(m_pair.ValueLock))
+ lock (m_pair.ValueLock)
{
// If the scheduler has already had completion requested, no new work is allowed to be scheduled
if (m_pair.CompletionRequested) throw new InvalidOperationException(GetType().ToString());
@@ -557,7 +560,7 @@ namespace System.Threading.Tasks
// since it'll only allow inlining if it can find the task in the local queue).
// As such, if we're not on a thread pool thread, we know for sure the
// task won't be inlined, so let's not even try.
- if (isDefaultScheduler && taskWasPreviouslyQueued && !ThreadPool.IsThreadPoolThread)
+ if (isDefaultScheduler && taskWasPreviouslyQueued && !Thread.CurrentThread.IsThreadPoolThread)
{
return false;
}
@@ -612,6 +615,7 @@ namespace System.Threading.Tasks
var ignored = t.Exception;
throw;
}
+ finally { t.Dispose(); }
}
/// <summary>Shim used to invoke this.TryExecuteTask(task).</summary>
@@ -705,15 +709,15 @@ namespace System.Threading.Tasks
}
}
- /// <summary>Asserts that a given Lock object is either held or not held.</summary>
- /// <param name="syncObj">The Lock object to check.</param>
+ /// <summary>Asserts that a given synchronization object is either held or not held.</summary>
+ /// <param name="syncObj">The monitor to check.</param>
/// <param name="held">Whether we want to assert that it's currently held or not held.</param>
[Conditional("DEBUG")]
- private static void ContractAssertMonitorStatus(Lock syncObj, bool held)
+ private static void ContractAssertMonitorStatus(object syncObj, bool held)
{
- Debug.Assert(syncObj != null, "The Lock object to check must be provided.");
+ Debug.Assert(syncObj != null, "The monitor object to check must be provided.");
#if !MONO
- Debug.Assert(syncObj.IsAcquired == held, "The locking scheme was not correctly followed.");
+ Debug.Assert(Monitor.IsEntered(syncObj) == held, "The locking scheme was not correctly followed.");
#endif
}
@@ -726,16 +730,14 @@ namespace System.Threading.Tasks
/// <returns>The options to use.</returns>
internal static TaskCreationOptions GetCreationOptionsForTask(bool isReplacementReplica = false)
{
- TaskCreationOptions options =
- TaskCreationOptions.DenyChildAttach;
-
+ TaskCreationOptions options = TaskCreationOptions.DenyChildAttach;
if (isReplacementReplica) options |= TaskCreationOptions.PreferFairness;
return options;
}
/// <summary>Provides an enumeration that represents the current state of the scheduler pair.</summary>
[Flags]
- internal enum ProcessingMode : byte
+ private enum ProcessingMode : byte
{
/// <summary>The scheduler pair is currently dormant, with no work scheduled.</summary>
NotCurrentlyProcessing = 0x0,
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCanceledException.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCanceledException.cs
index a6ec03045..c3ee31a53 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCanceledException.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCanceledException.cs
@@ -54,6 +54,18 @@ namespace System.Threading.Tasks
}
/// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.Tasks.TaskCanceledException"/>
+ /// class with a specified error message, a reference to the inner exception that is the cause of
+ /// this exception, and the <see cref="CancellationToken"/> that triggered the cancellation.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception.</param>
+ /// <param name="token">The <see cref="CancellationToken"/> that triggered the cancellation.</param>
+ public TaskCanceledException(string message, Exception innerException, CancellationToken token) : base(message, innerException, token)
+ {
+ }
+
+ /// <summary>
/// Initializes a new instance of the <see cref="T:System.Threading.Tasks.TaskCanceledException"/> class
/// with a reference to the <see cref="T:System.Threading.Tasks.Task"/> that has been canceled.
/// </summary>
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCompletionSource.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCompletionSource.cs
index 992e9db76..11ba26d89 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCompletionSource.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskCompletionSource.cs
@@ -315,7 +315,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The <see cref="Task"/> was disposed.</exception>
public bool TrySetCanceled()
{
- return TrySetCanceled(default(CancellationToken));
+ return TrySetCanceled(default);
}
// Enables a token to be stored into the canceled task
diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs
index 18e4a27a4..4d6a75960 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ValueTask.cs
@@ -14,17 +14,59 @@ using Internal.Runtime.CompilerServices;
namespace System.Threading.Tasks
{
+ // TYPE SAFETY WARNING:
+ // This code uses Unsafe.As to cast _obj. This is done in order to minimize the costs associated with
+ // casting _obj to a variety of different types that can be stored in a ValueTask, e.g. Task<TResult>
+ // vs IValueTaskSource<TResult>. Previous attempts at this were faulty due to using a separate field
+ // to store information about the type of the object in _obj; this is faulty because if the ValueTask
+ // is stored into a field, concurrent read/writes can result in tearing the _obj from the type information
+ // stored in a separate field. This means we can rely only on the _obj field to determine how to handle
+ // it. As such, the pattern employed is to copy _obj into a local obj, and then check it for null and
+ // type test against Task/Task<TResult>. Since the ValueTask can only be constructed with null, Task,
+ // or IValueTaskSource, we can then be confident in knowing that if it doesn't match one of those values,
+ // it must be an IValueTaskSource, and we can use Unsafe.As. This could be defeated by other unsafe means,
+ // like private reflection or using Unsafe.As manually, but at that point you're already doing things
+ // that can violate type safety; we only care about getting correct behaviors when using "safe" code.
+ // There are still other race conditions in user's code that can result in errors, but such errors don't
+ // cause ValueTask to violate type safety.
+
/// <summary>Provides an awaitable result of an asynchronous operation.</summary>
/// <remarks>
- /// <see cref="ValueTask"/>s are meant to be directly awaited. To do more complicated operations with them, a <see cref="Task"/>
- /// should be extracted using <see cref="AsTask"/>. Such operations might include caching an instance to be awaited later,
- /// registering multiple continuations with a single operation, awaiting the same task multiple times, and using combinators over
- /// multiple operations.
+ /// <see cref="ValueTask"/> instances are meant to be directly awaited. To do more complicated operations with them, a <see cref="Task"/>
+ /// should be extracted using <see cref="AsTask"/>. Such operations might include caching a task instance to be awaited later,
+ /// registering multiple continuations with a single task, awaiting the same task multiple times, and using combinators over
+ /// multiple operations:
+ /// <list type="bullet">
+ /// <item>
+ /// Once the result of a <see cref="ValueTask"/> instance has been retrieved, do not attempt to retrieve it again.
+ /// <see cref="ValueTask"/> instances may be backed by <see cref="IValueTaskSource"/> instances that are reusable, and such
+ /// instances may use the act of retrieving the instances result as a notification that the instance may now be reused for
+ /// a different operation. Attempting to then reuse that same <see cref="ValueTask"/> results in undefined behavior.
+ /// </item>
+ /// <item>
+ /// Do not attempt to add multiple continuations to the same <see cref="ValueTask"/>. While this might work if the
+ /// <see cref="ValueTask"/> wraps a <code>T</code> or a <see cref="Task"/>, it may not work if the <see cref="ValueTask"/>
+ /// was constructed from an <see cref="IValueTaskSource"/>.
+ /// </item>
+ /// <item>
+ /// Some operations that return a <see cref="ValueTask"/> may invalidate it based on some subsequent operation being performed.
+ /// Unless otherwise documented, assume that a <see cref="ValueTask"/> should be awaited prior to performing any additional operations
+ /// on the instance from which it was retrieved.
+ /// </item>
+ /// </list>
/// </remarks>
[AsyncMethodBuilder(typeof(AsyncValueTaskMethodBuilder))]
[StructLayout(LayoutKind.Auto)]
public readonly struct ValueTask : IEquatable<ValueTask>
{
+ /// <summary>A task canceled using `new CancellationToken(true)`.</summary>
+ private static readonly Task s_canceledTask =
+#if netstandard
+ Task.Delay(Timeout.Infinite, new CancellationToken(canceled: true));
+#else
+ Task.FromCanceled(new CancellationToken(canceled: true));
+#endif
+ /// <summary>A successfully completed task.</summary>
internal static Task CompletedTask
#if netstandard
{ get; } = Task.Delay(0);
@@ -34,10 +76,11 @@ namespace System.Threading.Tasks
/// <summary>null if representing a successful synchronous completion, otherwise a <see cref="Task"/> or a <see cref="IValueTaskSource"/>.</summary>
internal readonly object _obj;
- /// <summary>Flags providing additional details about the ValueTask's contents and behavior.</summary>
- internal readonly ValueTaskFlags _flags;
/// <summary>Opaque value passed through to the <see cref="IValueTaskSource"/>.</summary>
internal readonly short _token;
+ /// <summary>true to continue on the capture context; otherwise, true.</summary>
+ /// <remarks>Stored in the <see cref="ValueTask"/> rather than in the configured awaiter to utilize otherwise padding space.</remarks>
+ internal readonly bool _continueOnCapturedContext;
// An instance created with the default ctor (a zero init'd struct) represents a synchronously, successfully completed operation.
@@ -53,7 +96,7 @@ namespace System.Threading.Tasks
_obj = task;
- _flags = ValueTaskFlags.ObjectIsTask;
+ _continueOnCapturedContext = true;
_token = 0;
}
@@ -71,51 +114,15 @@ namespace System.Threading.Tasks
_obj = source;
_token = token;
- _flags = 0;
+ _continueOnCapturedContext = true;
}
- /// <summary>Non-verified initialization of the struct to the specified values.</summary>
- /// <param name="obj">The object.</param>
- /// <param name="token">The token.</param>
- /// <param name="flags">The flags.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private ValueTask(object obj, short token, ValueTaskFlags flags)
+ private ValueTask(object obj, short token, bool continueOnCapturedContext)
{
_obj = obj;
_token = token;
- _flags = flags;
- }
-
- /// <summary>Gets whether the contination should be scheduled to the current context.</summary>
- internal bool ContinueOnCapturedContext
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => (_flags & ValueTaskFlags.AvoidCapturedContext) == 0;
- }
-
- /// <summary>Gets whether the object in the <see cref="_obj"/> field is a <see cref="Task"/>.</summary>
- internal bool ObjectIsTask
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => (_flags & ValueTaskFlags.ObjectIsTask) != 0;
- }
-
- /// <summary>Returns the <see cref="Task"/> stored in <see cref="_obj"/>. This uses <see cref="Unsafe"/>.</summary>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal Task UnsafeGetTask()
- {
- Debug.Assert(ObjectIsTask);
- Debug.Assert(_obj is Task);
- return Unsafe.As<Task>(_obj);
- }
-
- /// <summary>Returns the <see cref="IValueTaskSource"/> stored in <see cref="_obj"/>. This uses <see cref="Unsafe"/>.</summary>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal IValueTaskSource UnsafeGetValueTaskSource()
- {
- Debug.Assert(!ObjectIsTask);
- Debug.Assert(_obj is IValueTaskSource);
- return Unsafe.As<IValueTaskSource>(_obj);
+ _continueOnCapturedContext = continueOnCapturedContext;
}
/// <summary>Returns the hash code for this instance.</summary>
@@ -144,18 +151,26 @@ namespace System.Threading.Tasks
/// It will either return the wrapped task object if one exists, or it'll
/// manufacture a new task object to represent the result.
/// </remarks>
- public Task AsTask() =>
- _obj == null ? ValueTask.CompletedTask :
- ObjectIsTask ? UnsafeGetTask() :
- GetTaskForValueTaskSource();
+ public Task AsTask()
+ {
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+ return
+ obj == null ? CompletedTask :
+ obj as Task ??
+ GetTaskForValueTaskSource(Unsafe.As<IValueTaskSource>(obj));
+ }
/// <summary>Gets a <see cref="ValueTask"/> that may be used at any point in the future.</summary>
public ValueTask Preserve() => _obj == null ? this : new ValueTask(AsTask());
/// <summary>Creates a <see cref="Task"/> to represent the <see cref="IValueTaskSource"/>.</summary>
- private Task GetTaskForValueTaskSource()
+ /// <remarks>
+ /// The <see cref="IValueTaskSource"/> is passed in rather than reading and casting <see cref="_obj"/>
+ /// so that the caller can pass in an object it's already validated.
+ /// </remarks>
+ private Task GetTaskForValueTaskSource(IValueTaskSource t)
{
- IValueTaskSource t = UnsafeGetValueTaskSource();
ValueTaskSourceStatus status = t.GetStatus(_token);
if (status != ValueTaskSourceStatus.Pending)
{
@@ -164,7 +179,7 @@ namespace System.Threading.Tasks
// Propagate any exceptions that may have occurred, then return
// an already successfully completed task.
t.GetResult(_token);
- return ValueTask.CompletedTask;
+ return CompletedTask;
// If status is Faulted or Canceled, GetResult should throw. But
// we can't guarantee every implementation will do the "right thing".
@@ -175,22 +190,15 @@ namespace System.Threading.Tasks
{
if (status == ValueTaskSourceStatus.Canceled)
{
-#if netstandard
- var tcs = new TaskCompletionSource<bool>();
- tcs.TrySetCanceled();
- return tcs.Task;
-#else
+#if !netstandard
if (exc is OperationCanceledException oce)
{
var task = new Task<VoidTaskResult>();
task.TrySetCanceled(oce.CancellationToken, oce);
return task;
}
- else
- {
- return Task.FromCanceled(new CancellationToken(true));
- }
#endif
+ return s_canceledTask;
}
else
{
@@ -205,7 +213,7 @@ namespace System.Threading.Tasks
}
}
- var m = new ValueTaskSourceTask(t, _token);
+ var m = new ValueTaskSourceAsTask(t, _token);
return
#if netstandard
m.Task;
@@ -215,7 +223,7 @@ namespace System.Threading.Tasks
}
/// <summary>Type used to create a <see cref="Task"/> to represent a <see cref="IValueTaskSource"/>.</summary>
- private sealed class ValueTaskSourceTask :
+ private sealed class ValueTaskSourceAsTask :
#if netstandard
TaskCompletionSource<bool>
#else
@@ -224,7 +232,7 @@ namespace System.Threading.Tasks
{
private static readonly Action<object> s_completionAction = state =>
{
- if (!(state is ValueTaskSourceTask vtst) ||
+ if (!(state is ValueTaskSourceAsTask vtst) ||
!(vtst._source is IValueTaskSource source))
{
// This could only happen if the IValueTaskSource passed the wrong state
@@ -270,7 +278,7 @@ namespace System.Threading.Tasks
/// <summary>The token to pass through to operations on <see cref="_source"/></summary>
private readonly short _token;
- public ValueTaskSourceTask(IValueTaskSource source, short token)
+ public ValueTaskSourceAsTask(IValueTaskSource source, short token)
{
_token = token;
_source = source;
@@ -282,30 +290,73 @@ namespace System.Threading.Tasks
public bool IsCompleted
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => _obj == null || (ObjectIsTask ? UnsafeGetTask().IsCompleted : UnsafeGetValueTaskSource().GetStatus(_token) != ValueTaskSourceStatus.Pending);
+ get
+ {
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj == null)
+ {
+ return true;
+ }
+
+ if (obj is Task t)
+ {
+ return t.IsCompleted;
+ }
+
+ return Unsafe.As<IValueTaskSource>(obj).GetStatus(_token) != ValueTaskSourceStatus.Pending;
+ }
}
/// <summary>Gets whether the <see cref="ValueTask"/> represents a successfully completed operation.</summary>
public bool IsCompletedSuccessfully
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get =>
- _obj == null ||
- (ObjectIsTask ?
+ get
+ {
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj == null)
+ {
+ return true;
+ }
+
+ if (obj is Task t)
+ {
+ return
#if netstandard
- UnsafeTask.Status == TaskStatus.RanToCompletion :
+ t.Status == TaskStatus.RanToCompletion;
#else
- UnsafeGetTask().IsCompletedSuccessfully :
+ t.IsCompletedSuccessfully;
#endif
- UnsafeGetValueTaskSource().GetStatus(_token) == ValueTaskSourceStatus.Succeeded);
+ }
+
+ return Unsafe.As<IValueTaskSource>(obj).GetStatus(_token) == ValueTaskSourceStatus.Succeeded;
+ }
}
/// <summary>Gets whether the <see cref="ValueTask"/> represents a failed operation.</summary>
public bool IsFaulted
{
- get =>
- _obj != null &&
- (ObjectIsTask ? UnsafeGetTask().IsFaulted : UnsafeGetValueTaskSource().GetStatus(_token) == ValueTaskSourceStatus.Faulted);
+ get
+ {
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj == null)
+ {
+ return false;
+ }
+
+ if (obj is Task t)
+ {
+ return t.IsFaulted;
+ }
+
+ return Unsafe.As<IValueTaskSource>(obj).GetStatus(_token) == ValueTaskSourceStatus.Faulted;
+ }
}
/// <summary>Gets whether the <see cref="ValueTask"/> represents a canceled operation.</summary>
@@ -316,9 +367,23 @@ namespace System.Threading.Tasks
/// </remarks>
public bool IsCanceled
{
- get =>
- _obj != null &&
- (ObjectIsTask ? UnsafeGetTask().IsCanceled : UnsafeGetValueTaskSource().GetStatus(_token) == ValueTaskSourceStatus.Canceled);
+ get
+ {
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj == null)
+ {
+ return false;
+ }
+
+ if (obj is Task t)
+ {
+ return t.IsCanceled;
+ }
+
+ return Unsafe.As<IValueTaskSource>(obj).GetStatus(_token) == ValueTaskSourceStatus.Canceled;
+ }
}
/// <summary>Throws the exception that caused the <see cref="ValueTask"/> to fail. If it completed successfully, nothing is thrown.</summary>
@@ -326,19 +391,22 @@ namespace System.Threading.Tasks
[StackTraceHidden]
internal void ThrowIfCompletedUnsuccessfully()
{
- if (_obj != null)
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task || obj is IValueTaskSource);
+
+ if (obj != null)
{
- if (ObjectIsTask)
+ if (obj is Task t)
{
#if netstandard
- UnsafeTask.GetAwaiter().GetResult();
+ t.GetAwaiter().GetResult();
#else
- TaskAwaiter.ValidateEnd(UnsafeGetTask());
+ TaskAwaiter.ValidateEnd(t);
#endif
}
else
{
- UnsafeGetValueTaskSource().GetResult(_token);
+ Unsafe.As<IValueTaskSource>(obj).GetResult(_token);
}
}
}
@@ -351,34 +419,51 @@ namespace System.Threading.Tasks
/// true to attempt to marshal the continuation back to the captured context; otherwise, false.
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public ConfiguredValueTaskAwaitable ConfigureAwait(bool continueOnCapturedContext)
- {
- // TODO: Simplify once https://github.com/dotnet/coreclr/pull/16138 is fixed.
- bool avoidCapture = !continueOnCapturedContext;
- return new ConfiguredValueTaskAwaitable(new ValueTask(_obj, _token, _flags | Unsafe.As<bool, ValueTaskFlags>(ref avoidCapture)));
- }
+ public ConfiguredValueTaskAwaitable ConfigureAwait(bool continueOnCapturedContext) =>
+ new ConfiguredValueTaskAwaitable(new ValueTask(_obj, _token, continueOnCapturedContext));
}
/// <summary>Provides a value type that can represent a synchronously available value or a task object.</summary>
/// <typeparam name="TResult">Specifies the type of the result.</typeparam>
/// <remarks>
- /// <see cref="ValueTask{TResult}"/>s are meant to be directly awaited. To do more complicated operations with them, a <see cref="Task"/>
- /// should be extracted using <see cref="AsTask"/> or <see cref="Preserve"/>. Such operations might include caching an instance to
- /// be awaited later, registering multiple continuations with a single operation, awaiting the same task multiple times, and using
- /// combinators over multiple operations.
+ /// <see cref="ValueTask{TResult}"/> instances are meant to be directly awaited. To do more complicated operations with them, a <see cref="Task{TResult}"/>
+ /// should be extracted using <see cref="AsTask"/>. Such operations might include caching a task instance to be awaited later,
+ /// registering multiple continuations with a single task, awaiting the same task multiple times, and using combinators over
+ /// multiple operations:
+ /// <list type="bullet">
+ /// <item>
+ /// Once the result of a <see cref="ValueTask{TResult}"/> instance has been retrieved, do not attempt to retrieve it again.
+ /// <see cref="ValueTask{TResult}"/> instances may be backed by <see cref="IValueTaskSource{TResult}"/> instances that are reusable, and such
+ /// instances may use the act of retrieving the instances result as a notification that the instance may now be reused for
+ /// a different operation. Attempting to then reuse that same <see cref="ValueTask{TResult}"/> results in undefined behavior.
+ /// </item>
+ /// <item>
+ /// Do not attempt to add multiple continuations to the same <see cref="ValueTask{TResult}"/>. While this might work if the
+ /// <see cref="ValueTask{TResult}"/> wraps a <code>T</code> or a <see cref="Task{TResult}"/>, it may not work if the <see cref="Task{TResult}"/>
+ /// was constructed from an <see cref="IValueTaskSource{TResult}"/>.
+ /// </item>
+ /// <item>
+ /// Some operations that return a <see cref="ValueTask{TResult}"/> may invalidate it based on some subsequent operation being performed.
+ /// Unless otherwise documented, assume that a <see cref="ValueTask{TResult}"/> should be awaited prior to performing any additional operations
+ /// on the instance from which it was retrieved.
+ /// </item>
+ /// </list>
/// </remarks>
[AsyncMethodBuilder(typeof(AsyncValueTaskMethodBuilder<>))]
[StructLayout(LayoutKind.Auto)]
public readonly struct ValueTask<TResult> : IEquatable<ValueTask<TResult>>
{
+ /// <summary>A task canceled using `new CancellationToken(true)`. Lazily created only when first needed.</summary>
+ private static Task<TResult> s_canceledTask;
/// <summary>null if <see cref="_result"/> has the result, otherwise a <see cref="Task{TResult}"/> or a <see cref="IValueTaskSource{TResult}"/>.</summary>
internal readonly object _obj;
/// <summary>The result to be used if the operation completed successfully synchronously.</summary>
internal readonly TResult _result;
- /// <summary>Flags providing additional details about the ValueTask's contents and behavior.</summary>
- internal readonly ValueTaskFlags _flags;
/// <summary>Opaque value passed through to the <see cref="IValueTaskSource{TResult}"/>.</summary>
internal readonly short _token;
+ /// <summary>true to continue on the captured context; otherwise, false.</summary>
+ /// <remarks>Stored in the <see cref="ValueTask{TResult}"/> rather than in the configured awaiter to utilize otherwise padding space.</remarks>
+ internal readonly bool _continueOnCapturedContext;
// An instance created with the default ctor (a zero init'd struct) represents a synchronously, successfully completed operation
// with a result of default(TResult).
@@ -391,7 +476,7 @@ namespace System.Threading.Tasks
_result = result;
_obj = null;
- _flags = 0;
+ _continueOnCapturedContext = true;
_token = 0;
}
@@ -408,7 +493,7 @@ namespace System.Threading.Tasks
_obj = task;
_result = default;
- _flags = ValueTaskFlags.ObjectIsTask;
+ _continueOnCapturedContext = true;
_token = 0;
}
@@ -427,54 +512,23 @@ namespace System.Threading.Tasks
_token = token;
_result = default;
- _flags = 0;
+ _continueOnCapturedContext = true;
}
/// <summary>Non-verified initialization of the struct to the specified values.</summary>
/// <param name="obj">The object.</param>
/// <param name="result">The result.</param>
/// <param name="token">The token.</param>
- /// <param name="flags">The flags.</param>
+ /// <param name="continueOnCapturedContext">true to continue on captured context; otherwise, false.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private ValueTask(object obj, TResult result, short token, ValueTaskFlags flags)
+ private ValueTask(object obj, TResult result, short token, bool continueOnCapturedContext)
{
_obj = obj;
_result = result;
_token = token;
- _flags = flags;
- }
-
- /// <summary>Gets whether the contination should be scheduled to the current context.</summary>
- internal bool ContinueOnCapturedContext
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => (_flags & ValueTaskFlags.AvoidCapturedContext) == 0;
- }
-
- /// <summary>Gets whether the object in the <see cref="_obj"/> field is a <see cref="Task{TResult}"/>.</summary>
- internal bool ObjectIsTask
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => (_flags & ValueTaskFlags.ObjectIsTask) != 0;
+ _continueOnCapturedContext = continueOnCapturedContext;
}
- /// <summary>Returns the <see cref="Task{TResult}"/> stored in <see cref="_obj"/>. This uses <see cref="Unsafe"/>.</summary>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal Task<TResult> UnsafeGetTask()
- {
- Debug.Assert(ObjectIsTask);
- Debug.Assert(_obj is Task<TResult>);
- return Unsafe.As<Task<TResult>>(_obj);
- }
-
- /// <summary>Returns the <see cref="IValueTaskSource{TResult}"/> stored in <see cref="_obj"/>. This uses <see cref="Unsafe"/>.</summary>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal IValueTaskSource<TResult> UnsafeGetValueTaskSource()
- {
- Debug.Assert(!ObjectIsTask);
- Debug.Assert(_obj is IValueTaskSource<TResult>);
- return Unsafe.As<IValueTaskSource<TResult>>(_obj);
- }
/// <summary>Returns the hash code for this instance.</summary>
public override int GetHashCode() =>
@@ -508,23 +562,39 @@ namespace System.Threading.Tasks
/// It will either return the wrapped task object if one exists, or it'll
/// manufacture a new task object to represent the result.
/// </remarks>
- public Task<TResult> AsTask() =>
- _obj == null ?
+ public Task<TResult> AsTask()
+ {
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj == null)
+ {
+ return
#if netstandard
- Task.FromResult(_result) :
+ Task.FromResult(_result);
#else
- AsyncTaskMethodBuilder<TResult>.GetTaskForResult(_result) :
+ AsyncTaskMethodBuilder<TResult>.GetTaskForResult(_result);
#endif
- ObjectIsTask ? UnsafeGetTask() :
- GetTaskForValueTaskSource();
+ }
+
+ if (obj is Task<TResult> t)
+ {
+ return t;
+ }
+
+ return GetTaskForValueTaskSource(Unsafe.As<IValueTaskSource<TResult>>(obj));
+ }
/// <summary>Gets a <see cref="ValueTask{TResult}"/> that may be used at any point in the future.</summary>
public ValueTask<TResult> Preserve() => _obj == null ? this : new ValueTask<TResult>(AsTask());
/// <summary>Creates a <see cref="Task{TResult}"/> to represent the <see cref="IValueTaskSource{TResult}"/>.</summary>
- private Task<TResult> GetTaskForValueTaskSource()
+ /// <remarks>
+ /// The <see cref="IValueTaskSource{TResult}"/> is passed in rather than reading and casting <see cref="_obj"/>
+ /// so that the caller can pass in an object it's already validated.
+ /// </remarks>
+ private Task<TResult> GetTaskForValueTaskSource(IValueTaskSource<TResult> t)
{
- IValueTaskSource<TResult> t = UnsafeGetValueTaskSource();
ValueTaskSourceStatus status = t.GetStatus(_token);
if (status != ValueTaskSourceStatus.Pending)
{
@@ -548,22 +618,29 @@ namespace System.Threading.Tasks
{
if (status == ValueTaskSourceStatus.Canceled)
{
-#if netstandard
- var tcs = new TaskCompletionSource<TResult>();
- tcs.TrySetCanceled();
- return tcs.Task;
-#else
+#if !netstandard
if (exc is OperationCanceledException oce)
{
var task = new Task<TResult>();
task.TrySetCanceled(oce.CancellationToken, oce);
return task;
}
- else
+#endif
+
+ Task<TResult> canceledTask = s_canceledTask;
+ if (canceledTask == null)
{
- return Task.FromCanceled<TResult>(new CancellationToken(true));
- }
+#if netstandard
+ var tcs = new TaskCompletionSource<TResult>();
+ tcs.TrySetCanceled();
+ canceledTask = tcs.Task;
+#else
+ canceledTask = Task.FromCanceled<TResult>(new CancellationToken(true));
#endif
+ // Benign race condition to initialize cached task, as identity doesn't matter.
+ s_canceledTask = canceledTask;
+ }
+ return canceledTask;
}
else
{
@@ -578,7 +655,7 @@ namespace System.Threading.Tasks
}
}
- var m = new ValueTaskSourceTask(t, _token);
+ var m = new ValueTaskSourceAsTask(t, _token);
return
#if netstandard
m.Task;
@@ -588,7 +665,7 @@ namespace System.Threading.Tasks
}
/// <summary>Type used to create a <see cref="Task{TResult}"/> to represent a <see cref="IValueTaskSource{TResult}"/>.</summary>
- private sealed class ValueTaskSourceTask :
+ private sealed class ValueTaskSourceAsTask :
#if netstandard
TaskCompletionSource<TResult>
#else
@@ -597,7 +674,7 @@ namespace System.Threading.Tasks
{
private static readonly Action<object> s_completionAction = state =>
{
- if (!(state is ValueTaskSourceTask vtst) ||
+ if (!(state is ValueTaskSourceAsTask vtst) ||
!(vtst._source is IValueTaskSource<TResult> source))
{
// This could only happen if the IValueTaskSource<TResult> passed the wrong state
@@ -642,7 +719,7 @@ namespace System.Threading.Tasks
/// <summary>The token to pass through to operations on <see cref="_source"/></summary>
private readonly short _token;
- public ValueTaskSourceTask(IValueTaskSource<TResult> source, short token)
+ public ValueTaskSourceAsTask(IValueTaskSource<TResult> source, short token)
{
_source = source;
_token = token;
@@ -654,30 +731,73 @@ namespace System.Threading.Tasks
public bool IsCompleted
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get => _obj == null || (ObjectIsTask ? UnsafeGetTask().IsCompleted : UnsafeGetValueTaskSource().GetStatus(_token) != ValueTaskSourceStatus.Pending);
+ get
+ {
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj == null)
+ {
+ return true;
+ }
+
+ if (obj is Task<TResult> t)
+ {
+ return t.IsCompleted;
+ }
+
+ return Unsafe.As<IValueTaskSource<TResult>>(obj).GetStatus(_token) != ValueTaskSourceStatus.Pending;
+ }
}
/// <summary>Gets whether the <see cref="ValueTask{TResult}"/> represents a successfully completed operation.</summary>
public bool IsCompletedSuccessfully
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- get =>
- _obj == null ||
- (ObjectIsTask ?
+ get
+ {
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj == null)
+ {
+ return true;
+ }
+
+ if (obj is Task<TResult> t)
+ {
+ return
#if netstandard
- UnsafeTask.Status == TaskStatus.RanToCompletion :
+ t.Status == TaskStatus.RanToCompletion;
#else
- UnsafeGetTask().IsCompletedSuccessfully :
+ t.IsCompletedSuccessfully;
#endif
- UnsafeGetValueTaskSource().GetStatus(_token) == ValueTaskSourceStatus.Succeeded);
+ }
+
+ return Unsafe.As<IValueTaskSource<TResult>>(obj).GetStatus(_token) == ValueTaskSourceStatus.Succeeded;
+ }
}
/// <summary>Gets whether the <see cref="ValueTask{TResult}"/> represents a failed operation.</summary>
public bool IsFaulted
{
- get =>
- _obj != null &&
- (ObjectIsTask ? UnsafeGetTask().IsFaulted : UnsafeGetValueTaskSource().GetStatus(_token) == ValueTaskSourceStatus.Faulted);
+ get
+ {
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj == null)
+ {
+ return false;
+ }
+
+ if (obj is Task<TResult> t)
+ {
+ return t.IsFaulted;
+ }
+
+ return Unsafe.As<IValueTaskSource<TResult>>(obj).GetStatus(_token) == ValueTaskSourceStatus.Faulted;
+ }
}
/// <summary>Gets whether the <see cref="ValueTask{TResult}"/> represents a canceled operation.</summary>
@@ -688,9 +808,23 @@ namespace System.Threading.Tasks
/// </remarks>
public bool IsCanceled
{
- get =>
- _obj != null &&
- (ObjectIsTask ? UnsafeGetTask().IsCanceled : UnsafeGetValueTaskSource().GetStatus(_token) == ValueTaskSourceStatus.Canceled);
+ get
+ {
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj == null)
+ {
+ return false;
+ }
+
+ if (obj is Task<TResult> t)
+ {
+ return t.IsCanceled;
+ }
+
+ return Unsafe.As<IValueTaskSource<TResult>>(obj).GetStatus(_token) == ValueTaskSourceStatus.Canceled;
+ }
}
/// <summary>Gets the result.</summary>
@@ -699,23 +833,25 @@ namespace System.Threading.Tasks
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
- if (_obj == null)
+ object obj = _obj;
+ Debug.Assert(obj == null || obj is Task<TResult> || obj is IValueTaskSource<TResult>);
+
+ if (obj == null)
{
return _result;
}
- if (ObjectIsTask)
+ if (obj is Task<TResult> t)
{
#if netstandard
- return UnsafeTask.GetAwaiter().GetResult();
+ return t.GetAwaiter().GetResult();
#else
- Task<TResult> t = UnsafeGetTask();
TaskAwaiter.ValidateEnd(t);
return t.ResultOnSuccess;
#endif
}
- return UnsafeGetValueTaskSource().GetResult(_token);
+ return Unsafe.As<IValueTaskSource<TResult>>(obj).GetResult(_token);
}
}
@@ -728,12 +864,8 @@ namespace System.Threading.Tasks
/// true to attempt to marshal the continuation back to the captured context; otherwise, false.
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public ConfiguredValueTaskAwaitable<TResult> ConfigureAwait(bool continueOnCapturedContext)
- {
- // TODO: Simplify once https://github.com/dotnet/coreclr/pull/16138 is fixed.
- bool avoidCapture = !continueOnCapturedContext;
- return new ConfiguredValueTaskAwaitable<TResult>(new ValueTask<TResult>(_obj, _result, _token, _flags | Unsafe.As<bool, ValueTaskFlags>(ref avoidCapture)));
- }
+ public ConfiguredValueTaskAwaitable<TResult> ConfigureAwait(bool continueOnCapturedContext) =>
+ new ConfiguredValueTaskAwaitable<TResult>(new ValueTask<TResult>(_obj, _result, _token, continueOnCapturedContext));
/// <summary>Gets a string-representation of this <see cref="ValueTask{TResult}"/>.</summary>
public override string ToString()
@@ -750,26 +882,4 @@ namespace System.Threading.Tasks
return string.Empty;
}
}
-
- /// <summary>Internal flags used in the implementation of <see cref="ValueTask"/> and <see cref="ValueTask{TResult}"/>.</summary>
- [Flags]
- internal enum ValueTaskFlags : byte
- {
- /// <summary>
- /// Indicates that context (e.g. SynchronizationContext) should not be captured when adding
- /// a continuation.
- /// </summary>
- /// <remarks>
- /// The value here must be 0x1, to match the value of a true Boolean reinterpreted as a byte.
- /// This only has meaning when awaiting a ValueTask, with ConfigureAwait creating a new
- /// ValueTask setting or not setting this flag appropriately.
- /// </remarks>
- AvoidCapturedContext = 0x1,
-
- /// <summary>
- /// Indicates that the ValueTask's object field stores a Task. This is used to avoid
- /// a type check on whatever is stored in the object field.
- /// </summary>
- ObjectIsTask = 0x2
- }
-} \ No newline at end of file
+}
diff --git a/src/System.Private.CoreLib/src/System/Threading/ThreadInterruptedException.cs b/src/System.Private.CoreLib/shared/System/Threading/ThreadInterruptedException.cs
index 28a827840..13fa1e91b 100644
--- a/src/System.Private.CoreLib/src/System/Threading/ThreadInterruptedException.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/ThreadInterruptedException.cs
@@ -2,47 +2,44 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-/*=============================================================================
-**
-**
-**
-** Purpose: An exception class to indicate that the thread was interrupted
-** from a waiting state.
-**
-**
-=============================================================================*/
-
using System.Runtime.Serialization;
namespace System.Threading
{
+ /// <summary>
+ /// An exception class to indicate that the thread was interrupted from a waiting state.
+ /// </summary>
[Serializable]
#if !MONO
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
#endif
public class ThreadInterruptedException : SystemException
{
- public ThreadInterruptedException()
- : base(SR.Threading_ThreadInterrupted)
+ public ThreadInterruptedException() : base(
+#if CORECLR
+ GetMessageFromNativeResources(ExceptionMessageKind.ThreadInterrupted)
+#else
+ SR.Threading_ThreadInterrupted
+#endif
+ )
{
HResult = HResults.COR_E_THREADINTERRUPTED;
}
- public ThreadInterruptedException(String message)
+ public ThreadInterruptedException(string message)
: base(message)
{
HResult = HResults.COR_E_THREADINTERRUPTED;
}
- public ThreadInterruptedException(String message, Exception innerException)
+ public ThreadInterruptedException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_THREADINTERRUPTED;
}
- protected ThreadInterruptedException(SerializationInfo info, StreamingContext context)
- : base(info, context)
+ protected ThreadInterruptedException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
}
-}
+} \ No newline at end of file
diff --git a/src/System.Private.CoreLib/src/System/Threading/ThreadLocal.cs b/src/System.Private.CoreLib/shared/System/Threading/ThreadLocal.cs
index ad6da89a9..9f4beae9c 100644
--- a/src/System.Private.CoreLib/src/System/Threading/ThreadLocal.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/ThreadLocal.cs
@@ -1,23 +1,13 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#pragma warning disable 0420
-// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
-//
-//
+using System.Collections.Generic;
+using System.Diagnostics;
-//
// A class that provides a simple, lightweight implementation of thread-local lazy-initialization, where a value is initialized once per accessing
// thread; this provides an alternative to using a ThreadStatic static variable and having
// to check the variable prior to every access to see if it's been initialized.
-//
-//
-//
-// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
-using System.Diagnostics;
-using System.Collections.Generic;
namespace System.Threading
{
@@ -37,15 +27,13 @@ namespace System.Threading
public class ThreadLocal<T> : IDisposable
{
// a delegate that returns the created value, if null the created value will be default(T)
- private Func<T> m_valueFactory;
+ private Func<T> _valueFactory;
- //
// ts_slotArray is a table of thread-local values for all ThreadLocal<T> instances
//
// So, when a thread reads ts_slotArray, it gets back an array of *all* ThreadLocal<T> values for this thread and this T.
- // The slot relevant to this particular ThreadLocal<T> instance is determined by the m_idComplement instance field stored in
+ // The slot relevant to this particular ThreadLocal<T> instance is determined by the _idComplement instance field stored in
// the ThreadLocal<T> instance.
- //
[ThreadStatic]
private static LinkedSlotVolatile[] ts_slotArray;
@@ -55,22 +43,22 @@ namespace System.Threading
// Slot ID of this ThreadLocal<> instance. We store a bitwise complement of the ID (that is ~ID), which allows us to distinguish
// between the case when ID is 0 and an incompletely initialized object, either due to a thread abort in the constructor, or
// possibly due to a memory model issue in user code.
- private int m_idComplement;
+ private int _idComplement;
// This field is set to true when the constructor completes. That is helpful for recognizing whether a constructor
// threw an exception - either due to invalid argument or due to a thread abort. Finally, the field is set to false
// when the instance is disposed.
- private volatile bool m_initialized;
+ private volatile bool _initialized;
// IdManager assigns and reuses slot IDs. Additionally, the object is also used as a global lock.
private static IdManager s_idManager = new IdManager();
// A linked list of all values associated with this ThreadLocal<T> instance.
// We create a dummy head node. That allows us to remove any (non-dummy) node without having to locate the m_linkedSlot field.
- private LinkedSlot m_linkedSlot = new LinkedSlot(null);
+ private LinkedSlot _linkedSlot = new LinkedSlot(null);
// Whether the Values property is supported
- private bool m_trackAllValues;
+ private bool _trackAllValues;
/// <summary>
/// Initializes the <see cref="System.Threading.ThreadLocal{T}"/> instance.
@@ -131,19 +119,19 @@ namespace System.Threading
private void Initialize(Func<T> valueFactory, bool trackAllValues)
{
- m_valueFactory = valueFactory;
- m_trackAllValues = trackAllValues;
+ _valueFactory = valueFactory;
+ _trackAllValues = trackAllValues;
- // Assign the ID and mark the instance as initialized. To avoid leaking IDs, we assign the ID and set m_initialized
+ // Assign the ID and mark the instance as initialized. To avoid leaking IDs, we assign the ID and set _initialized
// in a finally block, to avoid a thread abort in between the two statements.
try { }
finally
{
- m_idComplement = ~s_idManager.GetId();
+ _idComplement = ~s_idManager.GetId();
- // As the last step, mark the instance as fully initialized. (Otherwise, if m_initialized=false, we know that an exception
+ // As the last step, mark the instance as fully initialized. (Otherwise, if _initialized=false, we know that an exception
// occurred in the constructor.)
- m_initialized = true;
+ _initialized = true;
}
}
@@ -183,23 +171,23 @@ namespace System.Threading
{
int id;
- using (LockHolder.Hold(s_idManager.m_lock))
+ lock (s_idManager)
{
- id = ~m_idComplement;
- m_idComplement = 0;
+ id = ~_idComplement;
+ _idComplement = 0;
- if (id < 0 || !m_initialized)
+ if (id < 0 || !_initialized)
{
- Debug.Assert(id >= 0 || !m_initialized, "expected id >= 0 if initialized");
+ Debug.Assert(id >= 0 || !_initialized, "expected id >= 0 if initialized");
// Handle double Dispose calls or disposal of an instance whose constructor threw an exception.
return;
}
- m_initialized = false;
+ _initialized = false;
- for (LinkedSlot linkedSlot = m_linkedSlot.Next; linkedSlot != null; linkedSlot = linkedSlot.Next)
+ for (LinkedSlot linkedSlot = _linkedSlot._next; linkedSlot != null; linkedSlot = linkedSlot._next)
{
- LinkedSlotVolatile[] slotArray = linkedSlot.SlotArray;
+ LinkedSlotVolatile[] slotArray = linkedSlot._slotArray;
if (slotArray == null)
{
@@ -208,15 +196,15 @@ namespace System.Threading
}
// Remove the reference from the LinkedSlot to the slot table.
- linkedSlot.SlotArray = null;
+ linkedSlot._slotArray = null;
// And clear the references from the slot table to the linked slot and the value so that
// both can get garbage collected.
- slotArray[id].Value.Value = default(T);
+ slotArray[id].Value._value = default;
slotArray[id].Value = null;
}
}
- m_linkedSlot = null;
+ _linkedSlot = null;
s_idManager.ReturnId(id);
}
@@ -265,7 +253,7 @@ namespace System.Threading
{
LinkedSlotVolatile[] slotArray = ts_slotArray;
LinkedSlot slot;
- int id = ~m_idComplement;
+ int id = ~_idComplement;
//
// Attempt to get the value using the fast path
@@ -274,7 +262,7 @@ namespace System.Threading
&& id >= 0 // Is the ID non-negative (i.e., instance is not disposed)?
&& id < slotArray.Length // Is the table large enough?
&& (slot = slotArray[id].Value) != null // Has a LinkedSlot object has been allocated for this ID?
- && m_initialized // Has the instance *still* not been disposed (important for races with Dispose)?
+ && _initialized // Has the instance *still* not been disposed (important for a race condition with Dispose)?
)
{
// We verified that the instance has not been disposed *after* we got a reference to the slot.
@@ -282,7 +270,7 @@ namespace System.Threading
//
// Volatile read of the LinkedSlotVolatile.Value property ensures that the m_initialized read
// will not be reordered before the read of slotArray[id].
- return slot.Value;
+ return slot._value;
}
return GetValueSlow();
@@ -291,16 +279,14 @@ namespace System.Threading
{
LinkedSlotVolatile[] slotArray = ts_slotArray;
LinkedSlot slot;
- int id = ~m_idComplement;
+ int id = ~_idComplement;
- //
// Attempt to set the value using the fast path
- //
if (slotArray != null // Has the slot array been initialized?
&& id >= 0 // Is the ID non-negative (i.e., instance is not disposed)?
&& id < slotArray.Length // Is the table large enough?
&& (slot = slotArray[id].Value) != null // Has a LinkedSlot object has been allocated for this ID?
- && m_initialized // Has the instance *still* not been disposed (important for races with Dispose)?
+ && _initialized // Has the instance *still* not been disposed (important for a race condition with Dispose)?
)
{
// We verified that the instance has not been disposed *after* we got a reference to the slot.
@@ -308,7 +294,7 @@ namespace System.Threading
//
// Volatile read of the LinkedSlotVolatile.Value property ensures that the m_initialized read
// will not be reordered before the read of slotArray[id].
- slot.Value = value;
+ slot._value = value;
}
else
{
@@ -320,23 +306,23 @@ namespace System.Threading
private T GetValueSlow()
{
// If the object has been disposed, the id will be -1.
- int id = ~m_idComplement;
+ int id = ~_idComplement;
if (id < 0)
{
throw new ObjectDisposedException(SR.ThreadLocal_Disposed);
}
- //Debugger.NotifyOfCrossThreadDependency();
+ Debugger.NotifyOfCrossThreadDependency();
// Determine the initial value
T value;
- if (m_valueFactory == null)
+ if (_valueFactory == null)
{
- value = default(T);
+ value = default;
}
else
{
- value = m_valueFactory();
+ value = _valueFactory();
if (IsValueCreated)
{
@@ -351,7 +337,7 @@ namespace System.Threading
private void SetValueSlow(T value, LinkedSlotVolatile[] slotArray)
{
- int id = ~m_idComplement;
+ int id = ~_idComplement;
// If the object has been disposed, id will be -1.
if (id < 0)
@@ -363,7 +349,7 @@ namespace System.Threading
if (slotArray == null)
{
slotArray = new LinkedSlotVolatile[GetNewTableSize(id + 1)];
- ts_finalizationHelper = new FinalizationHelper(slotArray, m_trackAllValues);
+ ts_finalizationHelper = new FinalizationHelper(slotArray, _trackAllValues);
ts_slotArray = slotArray;
}
@@ -392,12 +378,12 @@ namespace System.Threading
// if this ThreadLocal instance was disposed on another thread and another ThreadLocal instance was
// created, we definitely won't assign the value into the wrong instance.
- if (!m_initialized)
+ if (!_initialized)
{
throw new ObjectDisposedException(SR.ThreadLocal_Disposed);
}
- slot.Value = value;
+ slot._value = value;
}
}
@@ -410,32 +396,30 @@ namespace System.Threading
var linkedSlot = new LinkedSlot(slotArray);
// Insert the LinkedSlot into the linked list maintained by this ThreadLocal<> instance and into the slot array
- using (LockHolder.Hold(s_idManager.m_lock))
+ lock (s_idManager)
{
// Check that the instance has not been disposed. It is important to check this under a lock, since
// Dispose also executes under a lock.
- if (!m_initialized)
+ if (!_initialized)
{
throw new ObjectDisposedException(SR.ThreadLocal_Disposed);
}
- LinkedSlot firstRealNode = m_linkedSlot.Next;
+ LinkedSlot firstRealNode = _linkedSlot._next;
- //
// Insert linkedSlot between nodes m_linkedSlot and firstRealNode.
- // (m_linkedSlot is the dummy head node that should always be in the front.)
- //
- linkedSlot.Next = firstRealNode;
- linkedSlot.Previous = m_linkedSlot;
- linkedSlot.Value = value;
+ // (_linkedSlot is the dummy head node that should always be in the front.)
+ linkedSlot._next = firstRealNode;
+ linkedSlot._previous = _linkedSlot;
+ linkedSlot._value = value;
if (firstRealNode != null)
{
- firstRealNode.Previous = linkedSlot;
+ firstRealNode._previous = linkedSlot;
}
- m_linkedSlot.Next = linkedSlot;
+ _linkedSlot._next = linkedSlot;
- // Assigning the slot under a lock prevents a race with Dispose (dispose also acquires the lock).
+ // Assigning the slot under a lock prevents a race condition with Dispose (dispose also acquires the lock).
// Otherwise, it would be possible that the ThreadLocal instance is disposed, another one gets created
// with the same ID, and the write would go to the wrong instance.
slotArray[id].Value = linkedSlot;
@@ -452,7 +436,7 @@ namespace System.Threading
{
get
{
- if (!m_trackAllValues)
+ if (!_trackAllValues)
{
throw new InvalidOperationException(SR.ThreadLocal_ValuesNotAvailable);
}
@@ -464,21 +448,21 @@ namespace System.Threading
}
/// <summary>Gets all of the threads' values in a list.</summary>
- private LowLevelListWithIList<T> GetValuesAsList()
+ private List<T> GetValuesAsList()
{
- LowLevelListWithIList<T> valueList = new LowLevelListWithIList<T>();
- int id = ~m_idComplement;
+ List<T> valueList = new List<T>();
+ int id = ~_idComplement;
if (id == -1)
{
return null;
}
// Walk over the linked list of slots and gather the values associated with this ThreadLocal instance.
- for (LinkedSlot linkedSlot = m_linkedSlot.Next; linkedSlot != null; linkedSlot = linkedSlot.Next)
+ for (LinkedSlot linkedSlot = _linkedSlot._next; linkedSlot != null; linkedSlot = linkedSlot._next)
{
// We can safely read linkedSlot.Value. Even if this ThreadLocal has been disposed in the meantime, the LinkedSlot
// objects will never be assigned to another ThreadLocal instance.
- valueList.Add(linkedSlot.Value);
+ valueList.Add(linkedSlot._value);
}
return valueList;
@@ -490,7 +474,7 @@ namespace System.Threading
get
{
int count = 0;
- for (LinkedSlot linkedSlot = m_linkedSlot.Next; linkedSlot != null; linkedSlot = linkedSlot.Next)
+ for (LinkedSlot linkedSlot = _linkedSlot._next; linkedSlot != null; linkedSlot = linkedSlot._next)
{
count++;
}
@@ -508,7 +492,7 @@ namespace System.Threading
{
get
{
- int id = ~m_idComplement;
+ int id = ~_idComplement;
if (id < 0)
{
throw new ObjectDisposedException(SR.ThreadLocal_Disposed);
@@ -527,17 +511,17 @@ namespace System.Threading
get
{
LinkedSlotVolatile[] slotArray = ts_slotArray;
- int id = ~m_idComplement;
+ int id = ~_idComplement;
LinkedSlot slot;
- if (slotArray == null || id >= slotArray.Length || (slot = slotArray[id].Value) == null || !m_initialized)
- return default(T);
- return slot.Value;
+ if (slotArray == null || id >= slotArray.Length || (slot = slotArray[id].Value) == null || !_initialized)
+ return default;
+ return slot._value;
}
}
/// <summary>Gets the values of all threads that accessed the ThreadLocal&lt;T&gt;.</summary>
- internal IList<T> ValuesForDebugDisplay // same as Values property, but doesn't throw if disposed
+ internal List<T> ValuesForDebugDisplay // same as Values property, but doesn't throw if disposed
{
get { return GetValuesAsList(); }
}
@@ -559,14 +543,14 @@ namespace System.Threading
// Dispose could use a stale SlotArray reference and clear out a slot in the old array only, while
// the value continues to be referenced from the new (larger) array.
//
- using (LockHolder.Hold(s_idManager.m_lock))
+ lock (s_idManager)
{
for (int i = 0; i < table.Length; i++)
{
LinkedSlot linkedSlot = table[i].Value;
- if (linkedSlot != null && linkedSlot.SlotArray != null)
+ if (linkedSlot != null && linkedSlot._slotArray != null)
{
- linkedSlot.SlotArray = newTable;
+ linkedSlot._slotArray = newTable;
newTable[i] = table[i];
}
}
@@ -575,14 +559,12 @@ namespace System.Threading
table = newTable;
}
- private const int MaxArrayLength = int.MaxValue;
-
/// <summary>
/// Chooses the next larger table size
/// </summary>
private static int GetNewTableSize(int minSize)
{
- if ((uint)minSize > MaxArrayLength)
+ if ((uint)minSize > Array.MaxArrayLength)
{
// Intentionally return a value that will result in an OutOfMemoryException
return int.MaxValue;
@@ -593,13 +575,13 @@ namespace System.Threading
// Round up the size to the next power of 2
//
// The algorithm takes three steps:
- // input -> subtract one -> propagate 1-bits to the right -> add one
+ // input -> subtract one -> propagate 1-bits to the right -> add one
//
// Let's take a look at the 3 steps in both interesting cases: where the input
// is (Example 1) and isn't (Example 2) a power of 2.
//
- // Example 1: 100000 -> 011111 -> 011111 -> 100000
- // Example 2: 011010 -> 011001 -> 011111 -> 100000
+ // Example 1: 100000 -> 011111 -> 011111 -> 100000
+ // Example 2: 011010 -> 011001 -> 011111 -> 100000
//
int newSize = minSize;
@@ -617,9 +599,9 @@ namespace System.Threading
newSize++;
// Don't set newSize to more than Array.MaxArrayLength
- if ((uint)newSize > MaxArrayLength)
+ if ((uint)newSize > Array.MaxArrayLength)
{
- newSize = MaxArrayLength;
+ newSize = Array.MaxArrayLength;
}
return newSize;
@@ -629,7 +611,7 @@ namespace System.Threading
/// A wrapper struct used as LinkedSlotVolatile[] - an array of LinkedSlot instances, but with volatile semantics
/// on array accesses.
/// </summary>
- internal struct LinkedSlotVolatile
+ private struct LinkedSlotVolatile
{
internal volatile LinkedSlot Value;
}
@@ -642,24 +624,24 @@ namespace System.Threading
/// 1. If SlotArray is not null, the value is in SlotArray.Table[id]
/// 2. If SlotArray is null, the value is in FinalValue.
/// </summary>
- internal sealed class LinkedSlot
+ private sealed class LinkedSlot
{
internal LinkedSlot(LinkedSlotVolatile[] slotArray)
{
- SlotArray = slotArray;
+ _slotArray = slotArray;
}
// The next LinkedSlot for this ThreadLocal<> instance
- internal volatile LinkedSlot Next;
+ internal volatile LinkedSlot _next;
// The previous LinkedSlot for this ThreadLocal<> instance
- internal volatile LinkedSlot Previous;
+ internal volatile LinkedSlot _previous;
// The SlotArray that stores this LinkedSlot at SlotArray.Table[id].
- internal volatile LinkedSlotVolatile[] SlotArray;
+ internal volatile LinkedSlotVolatile[] _slotArray;
// The value for this slot.
- internal T Value;
+ internal T _value;
}
/// <summary>
@@ -668,34 +650,32 @@ namespace System.Threading
private class IdManager
{
// The next ID to try
- private int m_nextIdToTry = 0;
+ private int _nextIdToTry = 0;
// Stores whether each ID is free or not. Additionally, the object is also used as a lock for the IdManager.
- private LowLevelList<bool> m_freeIds = new LowLevelList<bool>();
-
- internal Lock m_lock = new Lock();
+ private List<bool> _freeIds = new List<bool>();
internal int GetId()
{
- using (LockHolder.Hold(m_lock))
+ lock (_freeIds)
{
- int availableId = m_nextIdToTry;
- while (availableId < m_freeIds.Count)
+ int availableId = _nextIdToTry;
+ while (availableId < _freeIds.Count)
{
- if (m_freeIds[availableId]) { break; }
+ if (_freeIds[availableId]) { break; }
availableId++;
}
- if (availableId == m_freeIds.Count)
+ if (availableId == _freeIds.Count)
{
- m_freeIds.Add(false);
+ _freeIds.Add(false);
}
else
{
- m_freeIds[availableId] = false;
+ _freeIds[availableId] = false;
}
- m_nextIdToTry = availableId + 1;
+ _nextIdToTry = availableId + 1;
return availableId;
}
@@ -704,10 +684,10 @@ namespace System.Threading
// Return an ID to the pool
internal void ReturnId(int id)
{
- using (LockHolder.Hold(m_lock))
+ lock (_freeIds)
{
- m_freeIds[id] = true;
- if (id < m_nextIdToTry) m_nextIdToTry = id;
+ _freeIds[id] = true;
+ if (id < _nextIdToTry) _nextIdToTry = id;
}
}
}
@@ -716,7 +696,7 @@ namespace System.Threading
/// A class that facilitates ThreadLocal cleanup after a thread exits.
///
/// After a thread with an associated thread-local table has exited, the FinalizationHelper
- /// is reponsible for removing back-references to the table. Since an instance of FinalizationHelper
+ /// is responsible for removing back-references to the table. Since an instance of FinalizationHelper
/// is only referenced from a single thread-local slot, the FinalizationHelper will be GC'd once
/// the thread has exited.
///
@@ -724,15 +704,15 @@ namespace System.Threading
/// (all those LinkedSlot instances can be found by following references from the table slots) and
/// releases the table so that it can get GC'd.
/// </summary>
- internal class FinalizationHelper
+ private class FinalizationHelper
{
internal LinkedSlotVolatile[] SlotArray;
- private bool m_trackAllValues;
+ private bool _trackAllValues;
internal FinalizationHelper(LinkedSlotVolatile[] slotArray, bool trackAllValues)
{
SlotArray = slotArray;
- m_trackAllValues = trackAllValues;
+ _trackAllValues = trackAllValues;
}
~FinalizationHelper()
@@ -749,25 +729,25 @@ namespace System.Threading
continue;
}
- if (m_trackAllValues)
+ if (_trackAllValues)
{
// Set the SlotArray field to null to release the slot array.
- linkedSlot.SlotArray = null;
+ linkedSlot._slotArray = null;
}
else
{
// Remove the LinkedSlot from the linked list. Once the FinalizationHelper is done, all back-references to
// the table will be have been removed, and so the table can get GC'd.
- using (LockHolder.Hold(s_idManager.m_lock))
+ lock (s_idManager)
{
- if (linkedSlot.Next != null)
+ if (linkedSlot._next != null)
{
- linkedSlot.Next.Previous = linkedSlot.Previous;
+ linkedSlot._next._previous = linkedSlot._previous;
}
// Since the list uses a dummy head node, the Previous reference should never be null.
- Debug.Assert(linkedSlot.Previous != null);
- linkedSlot.Previous.Next = linkedSlot.Next;
+ Debug.Assert(linkedSlot._previous != null);
+ linkedSlot._previous._next = linkedSlot._next;
}
}
}
@@ -780,37 +760,22 @@ namespace System.Threading
internal sealed class SystemThreading_ThreadLocalDebugView<T>
{
//The ThreadLocal object being viewed.
- private readonly ThreadLocal<T> m_tlocal;
+ private readonly ThreadLocal<T> _tlocal;
/// <summary>Constructs a new debugger view object for the provided ThreadLocal object.</summary>
/// <param name="tlocal">A ThreadLocal object to browse in the debugger.</param>
public SystemThreading_ThreadLocalDebugView(ThreadLocal<T> tlocal)
{
- m_tlocal = tlocal;
+ _tlocal = tlocal;
}
/// <summary>Returns whether the ThreadLocal object is initialized or not.</summary>
- public bool IsValueCreated
- {
- get { return m_tlocal.IsValueCreated; }
- }
+ public bool IsValueCreated => _tlocal.IsValueCreated;
/// <summary>Returns the value of the ThreadLocal object.</summary>
- public T Value
- {
- get
- {
- return m_tlocal.ValueForDebugDisplay;
- }
- }
+ public T Value => _tlocal.ValueForDebugDisplay;
/// <summary>Return all values for all threads that have accessed this instance.</summary>
- public IList<T> Values
- {
- get
- {
- return m_tlocal.ValuesForDebugDisplay;
- }
- }
+ public List<T> Values => _tlocal.ValuesForDebugDisplay;
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Threading/ThreadStateException.cs b/src/System.Private.CoreLib/shared/System/Threading/ThreadStateException.cs
index 6fc06a851..d9ba48dfc 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/ThreadStateException.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/ThreadStateException.cs
@@ -26,13 +26,13 @@ namespace System.Threading
HResult = HResults.COR_E_THREADSTATE;
}
- public ThreadStateException(String message)
+ public ThreadStateException(string message)
: base(message)
{
HResult = HResults.COR_E_THREADSTATE;
}
- public ThreadStateException(String message, Exception innerException)
+ public ThreadStateException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_THREADSTATE;
diff --git a/src/System.Private.CoreLib/shared/System/Threading/TimeoutHelper.cs b/src/System.Private.CoreLib/shared/System/Threading/TimeoutHelper.cs
index c96a4d00d..dd3291281 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/TimeoutHelper.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/TimeoutHelper.cs
@@ -7,16 +7,16 @@ using System.Diagnostics;
namespace System.Threading
{
/// <summary>
- /// A helper class to capture a start time using Environment.TickCout as a time in milliseconds, also updates a given timeout bu subtracting the current time from
- /// the start time
+ /// A helper class to capture a start time using <see cref="Environment.TickCount"/> as a time in milliseconds.
+ /// Also updates a given timeout by subtracting the current time from the start time.
/// </summary>
internal static class TimeoutHelper
{
/// <summary>
- /// Returns the Environment.TickCount as a start time in milliseconds as a uint, TickCount tools over from positive to negative every ~ 25 days
- /// then ~25 days to back to positive again, uint is sued to ignore the sign and double the range to 50 days
+ /// Returns <see cref="Environment.TickCount"/> as a start time in milliseconds as a <see cref="UInt32"/>.
+ /// <see cref="Environment.TickCount"/> rolls over from positive to negative every ~25 days, then ~25 days to back to positive again.
+ /// <see cref="UInt32"/> is used to ignore the sign and double the range to 50 days.
/// </summary>
- /// <returns></returns>
public static uint GetTime()
{
return (uint)Environment.TickCount;
@@ -27,7 +27,7 @@ namespace System.Threading
/// </summary>
/// <param name="startTime"> The first time (in milliseconds) observed when the wait started</param>
/// <param name="originalWaitMillisecondsTimeout">The original wait timeout in milliseconds</param>
- /// <returns>The new wait time in milliseconds, -1 if the time expired</returns>
+ /// <returns>The new wait time in milliseconds, or -1 if the time expired</returns>
public static int UpdateTimeOut(uint startTime, int originalWaitMillisecondsTimeout)
{
// The function must be called in case the time out is not infinite
@@ -42,7 +42,7 @@ namespace System.Threading
}
// Subtract the elapsed time from the current wait time
- int currentWaitTimeout = originalWaitMillisecondsTimeout - (int)elapsedMilliseconds; ;
+ int currentWaitTimeout = originalWaitMillisecondsTimeout - (int)elapsedMilliseconds;
if (currentWaitTimeout <= 0)
{
return 0;
diff --git a/src/System.Private.CoreLib/shared/System/Threading/WaitHandleCannotBeOpenedException.cs b/src/System.Private.CoreLib/shared/System/Threading/WaitHandleCannotBeOpenedException.cs
index e60e46d2b..60821542b 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/WaitHandleCannotBeOpenedException.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/WaitHandleCannotBeOpenedException.cs
@@ -15,12 +15,12 @@ namespace System.Threading
HResult = HResults.COR_E_WAITHANDLECANNOTBEOPENED;
}
- public WaitHandleCannotBeOpenedException(String message) : base(message)
+ public WaitHandleCannotBeOpenedException(string message) : base(message)
{
HResult = HResults.COR_E_WAITHANDLECANNOTBEOPENED;
}
- public WaitHandleCannotBeOpenedException(String message, Exception innerException) : base(message, innerException)
+ public WaitHandleCannotBeOpenedException(string message, Exception innerException) : base(message, innerException)
{
HResult = HResults.COR_E_WAITHANDLECANNOTBEOPENED;
}
diff --git a/src/System.Private.CoreLib/shared/System/TimeSpan.cs b/src/System.Private.CoreLib/shared/System/TimeSpan.cs
index 4293ed505..10bdb331b 100644
--- a/src/System.Private.CoreLib/shared/System/TimeSpan.cs
+++ b/src/System.Private.CoreLib/shared/System/TimeSpan.cs
@@ -28,13 +28,13 @@ namespace System
// an appropriate custom ILMarshaler to keep WInRT interop scenarios enabled.
//
[Serializable]
- public struct TimeSpan : IComparable, IComparable<TimeSpan>, IEquatable<TimeSpan>, IFormattable, ISpanFormattable
+ public readonly struct TimeSpan : IComparable, IComparable<TimeSpan>, IEquatable<TimeSpan>, IFormattable, ISpanFormattable
{
public const long TicksPerMillisecond = 10000;
private const double MillisecondsPerTick = 1.0 / TicksPerMillisecond;
public const long TicksPerSecond = TicksPerMillisecond * 1000; // 10,000,000
- private const double SecondsPerTick = 1.0 / TicksPerSecond; // 0.0001
+ private const double SecondsPerTick = 1.0 / TicksPerSecond; // 0.0000001
public const long TicksPerMinute = TicksPerSecond * 60; // 600,000,000
private const double MinutesPerTick = 1.0 / TicksPerMinute; // 1.6666666666667e-9
@@ -50,22 +50,22 @@ namespace System
private const int MillisPerHour = MillisPerMinute * 60; // 3,600,000
private const int MillisPerDay = MillisPerHour * 24; // 86,400,000
- internal const long MaxSeconds = Int64.MaxValue / TicksPerSecond;
- internal const long MinSeconds = Int64.MinValue / TicksPerSecond;
+ internal const long MaxSeconds = long.MaxValue / TicksPerSecond;
+ internal const long MinSeconds = long.MinValue / TicksPerSecond;
- internal const long MaxMilliSeconds = Int64.MaxValue / TicksPerMillisecond;
- internal const long MinMilliSeconds = Int64.MinValue / TicksPerMillisecond;
+ internal const long MaxMilliSeconds = long.MaxValue / TicksPerMillisecond;
+ internal const long MinMilliSeconds = long.MinValue / TicksPerMillisecond;
internal const long TicksPerTenthSecond = TicksPerMillisecond * 100;
public static readonly TimeSpan Zero = new TimeSpan(0);
- public static readonly TimeSpan MaxValue = new TimeSpan(Int64.MaxValue);
- public static readonly TimeSpan MinValue = new TimeSpan(Int64.MinValue);
+ public static readonly TimeSpan MaxValue = new TimeSpan(long.MaxValue);
+ public static readonly TimeSpan MinValue = new TimeSpan(long.MinValue);
// internal so that DateTime doesn't have to call an extra get
// method for some arithmetic operations.
- internal long _ticks; // Do not rename (binary serialization)
+ internal readonly long _ticks; // Do not rename (binary serialization)
public TimeSpan(long ticks)
{
@@ -84,7 +84,7 @@ namespace System
public TimeSpan(int days, int hours, int minutes, int seconds, int milliseconds)
{
- Int64 totalMilliSeconds = ((Int64)days * 3600 * 24 + (Int64)hours * 3600 + (Int64)minutes * 60 + seconds) * 1000 + milliseconds;
+ long totalMilliSeconds = ((long)days * 3600 * 24 + (long)hours * 3600 + (long)minutes * 60 + seconds) * 1000 + milliseconds;
if (totalMilliSeconds > MaxMilliSeconds || totalMilliSeconds < MinMilliSeconds)
throw new ArgumentOutOfRangeException(null, SR.Overflow_TimeSpanTooLong);
_ticks = (long)totalMilliSeconds * TicksPerMillisecond;
@@ -178,7 +178,7 @@ namespace System
}
// Returns a value less than zero if this object
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null) return 1;
if (!(value is TimeSpan))
@@ -209,7 +209,7 @@ namespace System
return new TimeSpan(_ticks >= 0 ? _ticks : -_ticks);
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
if (value is TimeSpan)
{
@@ -240,11 +240,11 @@ namespace System
private static TimeSpan Interval(double value, int scale)
{
- if (Double.IsNaN(value))
+ if (double.IsNaN(value))
throw new ArgumentException(SR.Arg_CannotBeNaN);
double tmp = value * scale;
double millis = tmp + (value >= 0 ? 0.5 : -0.5);
- if ((millis > Int64.MaxValue / TicksPerMillisecond) || (millis < Int64.MinValue / TicksPerMillisecond))
+ if ((millis > long.MaxValue / TicksPerMillisecond) || (millis < long.MinValue / TicksPerMillisecond))
throw new OverflowException(SR.Overflow_TimeSpanTooLong);
return new TimeSpan((long)millis * TicksPerMillisecond);
}
@@ -305,18 +305,18 @@ namespace System
// See System.Globalization.TimeSpanParse and System.Globalization.TimeSpanFormat
#region ParseAndFormat
- private static void ValidateStyles(TimeSpanStyles style, String parameterName)
+ private static void ValidateStyles(TimeSpanStyles style, string parameterName)
{
if (style != TimeSpanStyles.None && style != TimeSpanStyles.AssumeNegative)
throw new ArgumentException(SR.Argument_InvalidTimeSpanStyles, parameterName);
}
- public static TimeSpan Parse(String s)
+ public static TimeSpan Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
/* Constructs a TimeSpan from a string. Leading and trailing white space characters are allowed. */
return TimeSpanParse.Parse(s, null);
}
- public static TimeSpan Parse(String input, IFormatProvider formatProvider)
+ public static TimeSpan Parse(string input, IFormatProvider formatProvider)
{
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
return TimeSpanParse.Parse(input, formatProvider);
@@ -325,18 +325,18 @@ namespace System
{
return TimeSpanParse.Parse(input, formatProvider);
}
- public static TimeSpan ParseExact(String input, String format, IFormatProvider formatProvider)
+ public static TimeSpan ParseExact(string input, string format, IFormatProvider formatProvider)
{
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
if (format == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.format);
return TimeSpanParse.ParseExact(input, format, formatProvider, TimeSpanStyles.None);
}
- public static TimeSpan ParseExact(String input, String[] formats, IFormatProvider formatProvider)
+ public static TimeSpan ParseExact(string input, string[] formats, IFormatProvider formatProvider)
{
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
return TimeSpanParse.ParseExactMultiple(input, formats, formatProvider, TimeSpanStyles.None);
}
- public static TimeSpan ParseExact(String input, String format, IFormatProvider formatProvider, TimeSpanStyles styles)
+ public static TimeSpan ParseExact(string input, string format, IFormatProvider formatProvider, TimeSpanStyles styles)
{
ValidateStyles(styles, nameof(styles));
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
@@ -349,7 +349,7 @@ namespace System
ValidateStyles(styles, nameof(styles));
return TimeSpanParse.ParseExact(input, format, formatProvider, styles);
}
- public static TimeSpan ParseExact(String input, String[] formats, IFormatProvider formatProvider, TimeSpanStyles styles)
+ public static TimeSpan ParseExact(string input, string[] formats, IFormatProvider formatProvider, TimeSpanStyles styles)
{
ValidateStyles(styles, nameof(styles));
if (input == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.input);
@@ -360,11 +360,11 @@ namespace System
ValidateStyles(styles, nameof(styles));
return TimeSpanParse.ParseExactMultiple(input, formats, formatProvider, styles);
}
- public static Boolean TryParse(String s, out TimeSpan result)
+ public static bool TryParse(string s, out TimeSpan result)
{
if (s == null)
{
- result = default(TimeSpan);
+ result = default;
return false;
}
return TimeSpanParse.TryParse(s, null, out result);
@@ -374,11 +374,11 @@ namespace System
return TimeSpanParse.TryParse(s, null, out result);
}
- public static Boolean TryParse(String input, IFormatProvider formatProvider, out TimeSpan result)
+ public static bool TryParse(string input, IFormatProvider formatProvider, out TimeSpan result)
{
if (input == null)
{
- result = default(TimeSpan);
+ result = default;
return false;
}
return TimeSpanParse.TryParse(input, formatProvider, out result);
@@ -387,7 +387,7 @@ namespace System
{
return TimeSpanParse.TryParse(input, formatProvider, out result);
}
- public static Boolean TryParseExact(String input, String format, IFormatProvider formatProvider, out TimeSpan result)
+ public static bool TryParseExact(string input, string format, IFormatProvider formatProvider, out TimeSpan result)
{
if (input == null || format == null)
{
@@ -401,11 +401,11 @@ namespace System
{
return TimeSpanParse.TryParseExact(input, format, formatProvider, TimeSpanStyles.None, out result);
}
- public static Boolean TryParseExact(String input, String[] formats, IFormatProvider formatProvider, out TimeSpan result)
+ public static bool TryParseExact(string input, string[] formats, IFormatProvider formatProvider, out TimeSpan result)
{
if (input == null)
{
- result = default(TimeSpan);
+ result = default;
return false;
}
return TimeSpanParse.TryParseExactMultiple(input, formats, formatProvider, TimeSpanStyles.None, out result);
@@ -415,7 +415,7 @@ namespace System
return TimeSpanParse.TryParseExactMultiple(input, formats, formatProvider, TimeSpanStyles.None, out result);
}
- public static Boolean TryParseExact(String input, String format, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result)
+ public static bool TryParseExact(string input, string format, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result)
{
ValidateStyles(styles, nameof(styles));
if (input == null || format == null)
@@ -432,12 +432,12 @@ namespace System
ValidateStyles(styles, nameof(styles));
return TimeSpanParse.TryParseExact(input, format, formatProvider, styles, out result);
}
- public static Boolean TryParseExact(String input, String[] formats, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result)
+ public static bool TryParseExact(string input, string[] formats, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result)
{
ValidateStyles(styles, nameof(styles));
if (input == null)
{
- result = default(TimeSpan);
+ result = default;
return false;
}
return TimeSpanParse.TryParseExactMultiple(input, formats, formatProvider, styles, out result);
@@ -448,15 +448,15 @@ namespace System
ValidateStyles(styles, nameof(styles));
return TimeSpanParse.TryParseExactMultiple(input, formats, formatProvider, styles, out result);
}
- public override String ToString()
+ public override string ToString()
{
- return TimeSpanFormat.Format(this, null, null);
+ return TimeSpanFormat.FormatC(this);
}
- public String ToString(String format)
+ public string ToString(string format)
{
return TimeSpanFormat.Format(this, format, null);
}
- public String ToString(String format, IFormatProvider formatProvider)
+ public string ToString(string format, IFormatProvider formatProvider)
{
return TimeSpanFormat.Format(this, format, formatProvider);
}
diff --git a/src/System.Private.CoreLib/shared/System/TimeZone.cs b/src/System.Private.CoreLib/shared/System/TimeZone.cs
index d4059babf..010db8090 100644
--- a/src/System.Private.CoreLib/shared/System/TimeZone.cs
+++ b/src/System.Private.CoreLib/shared/System/TimeZone.cs
@@ -32,15 +32,15 @@ namespace System
private static volatile TimeZone currentTimeZone = null;
// Private object for locking instead of locking on a public type for SQL reliability work.
- private static Object s_InternalSyncObject;
- private static Object InternalSyncObject
+ private static object s_InternalSyncObject;
+ private static object InternalSyncObject
{
get
{
if (s_InternalSyncObject == null)
{
- Object o = new Object();
- Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
+ object o = new object();
+ Interlocked.CompareExchange<object>(ref s_InternalSyncObject, o, null);
}
return s_InternalSyncObject;
}
@@ -87,12 +87,12 @@ namespace System
}
}
- public abstract String StandardName
+ public abstract string StandardName
{
get;
}
- public abstract String DaylightName
+ public abstract string DaylightName
{
get;
}
@@ -129,8 +129,8 @@ namespace System
{
return time;
}
- Boolean isAmbiguousLocalDst = false;
- Int64 offset = ((CurrentSystemTimeZone)(TimeZone.CurrentTimeZone)).GetUtcOffsetFromUniversalTime(time, ref isAmbiguousLocalDst);
+ bool isAmbiguousLocalDst = false;
+ long offset = ((CurrentSystemTimeZone)(TimeZone.CurrentTimeZone)).GetUtcOffsetFromUniversalTime(time, ref isAmbiguousLocalDst);
return new DateTime(time.Ticks + offset, DateTimeKind.Local, isAmbiguousLocalDst);
}
@@ -247,7 +247,7 @@ namespace System
ambiguousEnd = startTime - daylightTimes.Delta;
}
- Boolean isDst = false;
+ bool isDst = false;
if (startTime > endTime)
{
// In southern hemisphere, the daylight saving time starts later in the year, and ends in the beginning of next year.
diff --git a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.AdjustmentRule.cs b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.AdjustmentRule.cs
index 0e949a30e..aceb7b90f 100644
--- a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.AdjustmentRule.cs
+++ b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.AdjustmentRule.cs
@@ -11,6 +11,8 @@ namespace System
[Serializable]
public sealed class AdjustmentRule : IEquatable<AdjustmentRule>, ISerializable, IDeserializationCallback
{
+ private static readonly TimeSpan DaylightDeltaAdjustment = TimeSpan.FromHours(24.0);
+ private static readonly TimeSpan MaxDaylightDelta = TimeSpan.FromHours(12.0);
private readonly DateTime _dateStart;
private readonly DateTime _dateEnd;
private readonly TimeSpan _daylightDelta;
@@ -39,8 +41,8 @@ namespace System
internal bool HasDaylightSaving =>
DaylightDelta != TimeSpan.Zero ||
- (DaylightTransitionStart != default(TransitionTime) && DaylightTransitionStart.TimeOfDay != DateTime.MinValue) ||
- (DaylightTransitionEnd != default(TransitionTime) && DaylightTransitionEnd.TimeOfDay != DateTime.MinValue.AddMilliseconds(1));
+ (DaylightTransitionStart != default && DaylightTransitionStart.TimeOfDay != DateTime.MinValue) ||
+ (DaylightTransitionEnd != default && DaylightTransitionEnd.TimeOfDay != DateTime.MinValue.AddMilliseconds(1));
public bool Equals(AdjustmentRule other) =>
other != null &&
@@ -100,6 +102,7 @@ namespace System
TimeSpan baseUtcOffsetDelta,
bool noDaylightTransitions)
{
+ AdjustDaylightDeltaToExpectedRange(ref daylightDelta, ref baseUtcOffsetDelta);
return new AdjustmentRule(
dateStart,
dateEnd,
@@ -186,6 +189,26 @@ namespace System
}
}
+ /// <summary>
+ /// Ensures the daylight delta is within [-12, 12] hours
+ /// </summary>>
+ private static void AdjustDaylightDeltaToExpectedRange(ref TimeSpan daylightDelta, ref TimeSpan baseUtcOffsetDelta)
+ {
+ if (daylightDelta > MaxDaylightDelta)
+ {
+ daylightDelta -= DaylightDeltaAdjustment;
+ baseUtcOffsetDelta += DaylightDeltaAdjustment;
+ }
+ else if (daylightDelta < -MaxDaylightDelta)
+ {
+ daylightDelta += DaylightDeltaAdjustment;
+ baseUtcOffsetDelta -= DaylightDeltaAdjustment;
+ }
+
+ System.Diagnostics.Debug.Assert(daylightDelta <= MaxDaylightDelta && daylightDelta >= -MaxDaylightDelta,
+ "DaylightDelta should not ever be more than 24h");
+ }
+
void IDeserializationCallback.OnDeserialization(object sender)
{
// OnDeserialization is called after each instance of this class is deserialized.
diff --git a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Unix.cs b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Unix.cs
index 410eaf3ff..5645c2a38 100644
--- a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Unix.cs
+++ b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Unix.cs
@@ -384,8 +384,8 @@ namespace System
string symlinkPath = Interop.Sys.ReadLink(tzFilePath);
if (symlinkPath != null)
{
- // Use Path.Combine to resolve links that contain a relative path (e.g. /etc/localtime).
- symlinkPath = Path.Combine(tzFilePath, symlinkPath);
+ // symlinkPath can be relative path, use Path to get the full absolute path.
+ symlinkPath = Path.GetFullPath(symlinkPath, Path.GetDirectoryName(tzFilePath));
string timeZoneDirectory = GetTimeZoneDirectory();
if (symlinkPath.StartsWith(timeZoneDirectory, StringComparison.Ordinal))
@@ -398,7 +398,7 @@ namespace System
}
/// <summary>
- /// Enumerate files
+ /// Enumerate files
/// </summary>
private static IEnumerable<string> EnumerateFilesRecursively(string path)
{
@@ -595,6 +595,7 @@ namespace System
}
catch (ArgumentException) { }
catch (InvalidTimeZoneException) { }
+
try
{
return new TimeZoneInfo(rawData, id, dstDisabled: true); // create a TimeZoneInfo instance from the TZif data w/o DST support
@@ -602,7 +603,6 @@ namespace System
catch (ArgumentException) { }
catch (InvalidTimeZoneException) { }
}
-
return null;
}
@@ -866,7 +866,7 @@ namespace System
index++;
}
- if (index == 0)
+ if (rulesList.Count == 0 && index < dts.Length)
{
TZifType transitionType = TZif_GetEarlyDateTransitionType(transitionTypes);
DateTime endTransitionDate = dts[index];
@@ -883,6 +883,12 @@ namespace System
default(TransitionTime),
baseUtcDelta,
noDaylightTransitions: true);
+
+ if (!IsValidAdjustmentRuleOffest(timeZoneBaseUtcOffset, r))
+ {
+ NormalizeAdjustmentRuleOffset(timeZoneBaseUtcOffset, ref r);
+ }
+
rulesList.Add(r);
}
else if (index < dts.Length)
@@ -920,6 +926,12 @@ namespace System
default(TransitionTime),
baseUtcDelta,
noDaylightTransitions: true);
+
+ if (!IsValidAdjustmentRuleOffest(timeZoneBaseUtcOffset, r))
+ {
+ NormalizeAdjustmentRuleOffset(timeZoneBaseUtcOffset, ref r);
+ }
+
rulesList.Add(r);
}
else
@@ -932,8 +944,14 @@ namespace System
if (!string.IsNullOrEmpty(futureTransitionsPosixFormat))
{
AdjustmentRule r = TZif_CreateAdjustmentRuleForPosixFormat(futureTransitionsPosixFormat, startTransitionDate, timeZoneBaseUtcOffset);
+
if (r != null)
{
+ if (!IsValidAdjustmentRuleOffest(timeZoneBaseUtcOffset, r))
+ {
+ NormalizeAdjustmentRuleOffset(timeZoneBaseUtcOffset, ref r);
+ }
+
rulesList.Add(r);
}
}
@@ -954,6 +972,12 @@ namespace System
default(TransitionTime),
baseUtcDelta,
noDaylightTransitions: true);
+
+ if (!IsValidAdjustmentRuleOffest(timeZoneBaseUtcOffset, r))
+ {
+ NormalizeAdjustmentRuleOffset(timeZoneBaseUtcOffset, ref r);
+ }
+
rulesList.Add(r);
}
}
@@ -1012,17 +1036,15 @@ namespace System
/// </remarks>
private static AdjustmentRule TZif_CreateAdjustmentRuleForPosixFormat(string posixFormat, DateTime startTransitionDate, TimeSpan timeZoneBaseUtcOffset)
{
- string standardName;
- string standardOffset;
- string daylightSavingsName;
- string daylightSavingsOffset;
- string start;
- string startTime;
- string end;
- string endTime;
-
- if (TZif_ParsePosixFormat(posixFormat, out standardName, out standardOffset, out daylightSavingsName,
- out daylightSavingsOffset, out start, out startTime, out end, out endTime))
+ if (TZif_ParsePosixFormat(posixFormat,
+ out ReadOnlySpan<char> standardName,
+ out ReadOnlySpan<char> standardOffset,
+ out ReadOnlySpan<char> daylightSavingsName,
+ out ReadOnlySpan<char> daylightSavingsOffset,
+ out ReadOnlySpan<char> start,
+ out ReadOnlySpan<char> startTime,
+ out ReadOnlySpan<char> end,
+ out ReadOnlySpan<char> endTime))
{
// a valid posixFormat has at least standardName and standardOffset
@@ -1033,7 +1055,7 @@ namespace System
baseOffset = TZif_CalculateTransitionOffsetFromBase(baseOffset, timeZoneBaseUtcOffset);
// having a daylightSavingsName means there is a DST rule
- if (!string.IsNullOrEmpty(daylightSavingsName))
+ if (!daylightSavingsName.IsEmpty)
{
TimeSpan? parsedDaylightSavings = TZif_ParseOffsetString(daylightSavingsOffset);
TimeSpan daylightSavingsTimeSpan;
@@ -1079,16 +1101,16 @@ namespace System
return null;
}
- private static TimeSpan? TZif_ParseOffsetString(string offset)
+ private static TimeSpan? TZif_ParseOffsetString(ReadOnlySpan<char> offset)
{
TimeSpan? result = null;
- if (!string.IsNullOrEmpty(offset))
+ if (offset.Length > 0)
{
bool negative = offset[0] == '-';
if (negative || offset[0] == '+')
{
- offset = offset.Substring(1);
+ offset = offset.Slice(1);
}
// Try parsing just hours first.
@@ -1117,9 +1139,40 @@ namespace System
return result;
}
- private static TransitionTime TZif_CreateTransitionTimeFromPosixRule(string date, string time)
+ private static DateTime ParseTimeOfDay(ReadOnlySpan<char> time)
+ {
+ DateTime timeOfDay;
+ TimeSpan? timeOffset = TZif_ParseOffsetString(time);
+ if (timeOffset.HasValue)
+ {
+ // This logic isn't correct and can't be corrected until https://github.com/dotnet/corefx/issues/2618 is fixed.
+ // Some time zones use time values like, "26", "144", or "-2".
+ // This allows the week to sometimes be week 4 and sometimes week 5 in the month.
+ // For now, strip off any 'days' in the offset, and just get the time of day correct
+ timeOffset = new TimeSpan(timeOffset.Value.Hours, timeOffset.Value.Minutes, timeOffset.Value.Seconds);
+ if (timeOffset.Value < TimeSpan.Zero)
+ {
+ timeOfDay = new DateTime(1, 1, 2, 0, 0, 0);
+ }
+ else
+ {
+ timeOfDay = new DateTime(1, 1, 1, 0, 0, 0);
+ }
+
+ timeOfDay += timeOffset.Value;
+ }
+ else
+ {
+ // default to 2AM.
+ timeOfDay = new DateTime(1, 1, 1, 2, 0, 0);
+ }
+
+ return timeOfDay;
+ }
+
+ private static TransitionTime TZif_CreateTransitionTimeFromPosixRule(ReadOnlySpan<char> date, ReadOnlySpan<char> time)
{
- if (string.IsNullOrEmpty(date))
+ if (date.IsEmpty)
{
return default(TransitionTime);
}
@@ -1135,51 +1188,93 @@ namespace System
DayOfWeek day;
if (!TZif_ParseMDateRule(date, out month, out week, out day))
{
- throw new InvalidTimeZoneException(SR.Format(SR.InvalidTimeZone_UnparseablePosixMDateString, date));
+ throw new InvalidTimeZoneException(SR.Format(SR.InvalidTimeZone_UnparseablePosixMDateString, date.ToString()));
}
- DateTime timeOfDay;
- TimeSpan? timeOffset = TZif_ParseOffsetString(time);
- if (timeOffset.HasValue)
- {
- // This logic isn't correct and can't be corrected until https://github.com/dotnet/corefx/issues/2618 is fixed.
- // Some time zones use time values like, "26", "144", or "-2".
- // This allows the week to sometimes be week 4 and sometimes week 5 in the month.
- // For now, strip off any 'days' in the offset, and just get the time of day correct
- timeOffset = new TimeSpan(timeOffset.Value.Hours, timeOffset.Value.Minutes, timeOffset.Value.Seconds);
- if (timeOffset.Value < TimeSpan.Zero)
- {
- timeOfDay = new DateTime(1, 1, 2, 0, 0, 0);
- }
- else
- {
- timeOfDay = new DateTime(1, 1, 1, 0, 0, 0);
- }
-
- timeOfDay += timeOffset.Value;
- }
- else
+ return TransitionTime.CreateFloatingDateRule(ParseTimeOfDay(time), month, week, day);
+ }
+ else
+ {
+ if (date[0] != 'J')
{
- // default to 2AM.
- timeOfDay = new DateTime(1, 1, 1, 2, 0, 0);
+ // should be n Julian day format which we don't support.
+ //
+ // This specifies the Julian day, with n between 0 and 365. February 29 is counted in leap years.
+ //
+ // n would be a relative number from the begining of the year. which should handle if the
+ // the year is a leap year or not.
+ //
+ // In leap year, n would be counted as:
+ //
+ // 0 30 31 59 60 90 335 365
+ // |-------Jan--------|-------Feb--------|-------Mar--------|....|-------Dec--------|
+ //
+ // while in non leap year we'll have
+ //
+ // 0 30 31 58 59 89 334 364
+ // |-------Jan--------|-------Feb--------|-------Mar--------|....|-------Dec--------|
+ //
+ //
+ // For example if n is specified as 60, this means in leap year the rule will start at Mar 1,
+ // while in non leap year the rule will start at Mar 2.
+ //
+ // If we need to support n format, we'll have to have a floating adjustment rule support this case.
+
+ throw new InvalidTimeZoneException(SR.InvalidTimeZone_NJulianDayNotSupported);
}
- return TransitionTime.CreateFloatingDateRule(timeOfDay, month, week, day);
+ // Julian day
+ TZif_ParseJulianDay(date, out int month, out int day);
+ return TransitionTime.CreateFixedDateRule(ParseTimeOfDay(time), month, day);
}
- else
+ }
+
+ /// <summary>
+ /// Parses a string like Jn or n into month and day values.
+ /// </summary>
+ /// <returns>
+ /// true if the parsing succeeded; otherwise, false.
+ /// </returns>
+ private static void TZif_ParseJulianDay(ReadOnlySpan<char> date, out int month, out int day)
+ {
+ // Jn
+ // This specifies the Julian day, with n between 1 and 365.February 29 is never counted, even in leap years.
+ Debug.Assert(!date.IsEmpty);
+ Debug.Assert(date[0] == 'J');
+ month = day = 0;
+
+ int index = 1;
+
+ if (index >= date.Length || ((uint)(date[index] - '0') > '9'-'0'))
+ {
+ throw new InvalidTimeZoneException(SR.InvalidTimeZone_InvalidJulianDay);
+ }
+
+ int julianDay = 0;
+
+ do
{
- // Jn
- // This specifies the Julian day, with n between 1 and 365.February 29 is never counted, even in leap years.
+ julianDay = julianDay * 10 + (int) (date[index] - '0');
+ index++;
+ } while (index < date.Length && ((uint)(date[index] - '0') <= '9'-'0'));
- // n
- // This specifies the Julian day, with n between 0 and 365.February 29 is counted in leap years.
+ int[] days = GregorianCalendarHelper.DaysToMonth365;
- // These two rules cannot be expressed with the current AdjustmentRules
- // One of them *could* be supported if we relaxed the TransitionTime validation rules, and allowed
- // "IsFixedDateRule = true, Month = 0, Day = n" to mean the nth day of the year, picking one of the rules above
+ if (julianDay == 0 || julianDay > days[days.Length - 1])
+ {
+ throw new InvalidTimeZoneException(SR.InvalidTimeZone_InvalidJulianDay);
+ }
- throw new InvalidTimeZoneException(SR.InvalidTimeZone_JulianDayNotSupported);
+ int i = 1;
+ while (i < days.Length && julianDay > days[i])
+ {
+ i++;
}
+
+ Debug.Assert(i > 0 && i < days.Length);
+
+ month = i;
+ day = julianDay - days[i - 1];
}
/// <summary>
@@ -1188,19 +1283,20 @@ namespace System
/// <returns>
/// true if the parsing succeeded; otherwise, false.
/// </returns>
- private static bool TZif_ParseMDateRule(string dateRule, out int month, out int week, out DayOfWeek dayOfWeek)
+ private static bool TZif_ParseMDateRule(ReadOnlySpan<char> dateRule, out int month, out int week, out DayOfWeek dayOfWeek)
{
if (dateRule[0] == 'M')
{
- int firstDotIndex = dateRule.IndexOf('.');
- if (firstDotIndex > 0)
+ int monthWeekDotIndex = dateRule.IndexOf('.');
+ if (monthWeekDotIndex > 0)
{
- int secondDotIndex = dateRule.IndexOf('.', firstDotIndex + 1);
- if (secondDotIndex > 0)
+ ReadOnlySpan<char> weekDaySpan = dateRule.Slice(monthWeekDotIndex + 1);
+ int weekDayDotIndex = weekDaySpan.IndexOf('.');
+ if (weekDayDotIndex > 0)
{
- if (int.TryParse(dateRule.AsSpan().Slice(1, firstDotIndex - 1), out month) &&
- int.TryParse(dateRule.AsSpan().Slice(firstDotIndex + 1, secondDotIndex - firstDotIndex - 1), out week) &&
- int.TryParse(dateRule.AsSpan().Slice(secondDotIndex + 1), out int day))
+ if (int.TryParse(dateRule.Slice(1, monthWeekDotIndex - 1), out month) &&
+ int.TryParse(weekDaySpan.Slice(0, weekDayDotIndex), out week) &&
+ int.TryParse(weekDaySpan.Slice(weekDayDotIndex + 1), out int day))
{
dayOfWeek = (DayOfWeek)day;
return true;
@@ -1216,15 +1312,15 @@ namespace System
}
private static bool TZif_ParsePosixFormat(
- string posixFormat,
- out string standardName,
- out string standardOffset,
- out string daylightSavingsName,
- out string daylightSavingsOffset,
- out string start,
- out string startTime,
- out string end,
- out string endTime)
+ ReadOnlySpan<char> posixFormat,
+ out ReadOnlySpan<char> standardName,
+ out ReadOnlySpan<char> standardOffset,
+ out ReadOnlySpan<char> daylightSavingsName,
+ out ReadOnlySpan<char> daylightSavingsOffset,
+ out ReadOnlySpan<char> start,
+ out ReadOnlySpan<char> startTime,
+ out ReadOnlySpan<char> end,
+ out ReadOnlySpan<char> endTime)
{
standardName = null;
standardOffset = null;
@@ -1240,7 +1336,7 @@ namespace System
standardOffset = TZif_ParsePosixOffset(posixFormat, ref index);
daylightSavingsName = TZif_ParsePosixName(posixFormat, ref index);
- if (!string.IsNullOrEmpty(daylightSavingsName))
+ if (!daylightSavingsName.IsEmpty)
{
daylightSavingsOffset = TZif_ParsePosixOffset(posixFormat, ref index);
@@ -1257,10 +1353,10 @@ namespace System
}
}
- return !string.IsNullOrEmpty(standardName) && !string.IsNullOrEmpty(standardOffset);
+ return !standardName.IsEmpty && !standardOffset.IsEmpty;
}
- private static string TZif_ParsePosixName(string posixFormat, ref int index)
+ private static ReadOnlySpan<char> TZif_ParsePosixName(ReadOnlySpan<char> posixFormat, ref int index)
{
bool isBracketEnclosed = index < posixFormat.Length && posixFormat[index] == '<';
if (isBracketEnclosed)
@@ -1268,7 +1364,7 @@ namespace System
// move past the opening bracket
index++;
- string result = TZif_ParsePosixString(posixFormat, ref index, c => c == '>');
+ ReadOnlySpan<char> result = TZif_ParsePosixString(posixFormat, ref index, c => c == '>');
// move past the closing bracket
if (index < posixFormat.Length && posixFormat[index] == '>')
@@ -1287,10 +1383,10 @@ namespace System
}
}
- private static string TZif_ParsePosixOffset(string posixFormat, ref int index) =>
+ private static ReadOnlySpan<char> TZif_ParsePosixOffset(ReadOnlySpan<char> posixFormat, ref int index) =>
TZif_ParsePosixString(posixFormat, ref index, c => !char.IsDigit(c) && c != '+' && c != '-' && c != ':');
- private static void TZif_ParsePosixDateTime(string posixFormat, ref int index, out string date, out string time)
+ private static void TZif_ParsePosixDateTime(ReadOnlySpan<char> posixFormat, ref int index, out ReadOnlySpan<char> date, out ReadOnlySpan<char> time)
{
time = null;
@@ -1302,13 +1398,13 @@ namespace System
}
}
- private static string TZif_ParsePosixDate(string posixFormat, ref int index) =>
+ private static ReadOnlySpan<char> TZif_ParsePosixDate(ReadOnlySpan<char> posixFormat, ref int index) =>
TZif_ParsePosixString(posixFormat, ref index, c => c == '/' || c == ',');
- private static string TZif_ParsePosixTime(string posixFormat, ref int index) =>
+ private static ReadOnlySpan<char> TZif_ParsePosixTime(ReadOnlySpan<char> posixFormat, ref int index) =>
TZif_ParsePosixString(posixFormat, ref index, c => c == ',');
- private static string TZif_ParsePosixString(string posixFormat, ref int index, Func<char, bool> breakCondition)
+ private static ReadOnlySpan<char> TZif_ParsePosixString(ReadOnlySpan<char> posixFormat, ref int index, Func<char, bool> breakCondition)
{
int startIndex = index;
for (; index < posixFormat.Length; index++)
@@ -1320,7 +1416,7 @@ namespace System
}
}
- return posixFormat.Substring(startIndex, index - startIndex);
+ return posixFormat.Slice(startIndex, index - startIndex);
}
// Returns the Substring from zoneAbbreviations starting at index and ending at '\0'
diff --git a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Win32.cs b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Win32.cs
index 5950c9565..443b8d45d 100644
--- a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Win32.cs
+++ b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.Win32.cs
@@ -422,7 +422,7 @@ namespace System
if (!supportsDst)
{
- transitionTime = default(TransitionTime);
+ transitionTime = default;
return false;
}
@@ -676,7 +676,7 @@ namespace System
return true;
}
- private unsafe static bool TryGetTimeZoneEntryFromRegistry(RegistryKey key, string name, out REG_TZI_FORMAT dtzi)
+ private static unsafe bool TryGetTimeZoneEntryFromRegistry(RegistryKey key, string name, out REG_TZI_FORMAT dtzi)
{
byte[] regValue = key.GetValue(name, null, RegistryValueOptions.None) as byte[];
if (regValue == null || regValue.Length != sizeof(REG_TZI_FORMAT))
diff --git a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.cs b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.cs
index 6e27376b6..e95321df2 100644
--- a/src/System.Private.CoreLib/shared/System/TimeZoneInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/TimeZoneInfo.cs
@@ -1918,12 +1918,6 @@ namespace System
}
/// <summary>
- /// Helper function that validates the TimeSpan is within +/- 14.0 hours
- /// </summary>
- internal static bool UtcOffsetOutOfRange(TimeSpan offset) =>
- offset.TotalHours < -14.0 || offset.TotalHours > 14.0;
-
- /// <summary>
/// Helper function that performs all of the validation checks for the
/// factory methods and deserialization callback.
/// </summary>
@@ -1972,11 +1966,7 @@ namespace System
throw new InvalidTimeZoneException(SR.Argument_AdjustmentRulesNoNulls);
}
- // FUTURE: check to see if this rule supports Daylight Saving Time
- // adjustmentRulesSupportDst = adjustmentRulesSupportDst || current.SupportsDaylightSavingTime;
- // FUTURE: test baseUtcOffset + current.StandardDelta
-
- if (UtcOffsetOutOfRange(baseUtcOffset + current.DaylightDelta))
+ if (!IsValidAdjustmentRuleOffest(baseUtcOffset, current))
{
throw new InvalidTimeZoneException(SR.ArgumentOutOfRange_UtcOffsetAndDaylightDelta);
}
@@ -1989,5 +1979,82 @@ namespace System
}
}
}
+
+ private static readonly TimeSpan MaxOffset = TimeSpan.FromHours(14.0);
+ private static readonly TimeSpan MinOffset = -MaxOffset;
+
+ /// <summary>
+ /// Helper function that validates the TimeSpan is within +/- 14.0 hours
+ /// </summary>
+ internal static bool UtcOffsetOutOfRange(TimeSpan offset) =>
+ offset < MinOffset || offset > MaxOffset;
+
+ private static TimeSpan GetUtcOffset(TimeSpan baseUtcOffset, AdjustmentRule adjustmentRule)
+ {
+ return baseUtcOffset
+ + adjustmentRule.BaseUtcOffsetDelta
+ + (adjustmentRule.HasDaylightSaving ? adjustmentRule.DaylightDelta : TimeSpan.Zero);
+ }
+
+ /// <summary>
+ /// Helper function that performs adjustment rule validation
+ /// </summary>
+ private static bool IsValidAdjustmentRuleOffest(TimeSpan baseUtcOffset, AdjustmentRule adjustmentRule)
+ {
+ TimeSpan utcOffset = GetUtcOffset(baseUtcOffset, adjustmentRule);
+ return !UtcOffsetOutOfRange(utcOffset);
+ }
+
+ /// <summary>
+ /// Normalize adjustment rule offset so that it is within valid range
+ /// This method should not be called at all but is here in case something changes in the future
+ /// or if really old time zones are present on the OS (no combination is known at the moment)
+ /// </summary>
+ private static void NormalizeAdjustmentRuleOffset(TimeSpan baseUtcOffset, ref AdjustmentRule adjustmentRule)
+ {
+ // Certain time zones such as:
+ // Time Zone start date end date offset
+ // -----------------------------------------------------
+ // America/Yakutat 0001-01-01 1867-10-18 14:41:00
+ // America/Yakutat 1867-10-18 1900-08-20 14:41:00
+ // America/Sitka 0001-01-01 1867-10-18 14:58:00
+ // America/Sitka 1867-10-18 1900-08-20 14:58:00
+ // Asia/Manila 0001-01-01 1844-12-31 -15:56:00
+ // Pacific/Guam 0001-01-01 1845-01-01 -14:21:00
+ // Pacific/Saipan 0001-01-01 1845-01-01 -14:21:00
+ //
+ // have larger offset than currently supported by framework.
+ // If for whatever reason we find that time zone exceeding max
+ // offset of 14h this function will truncate it to the max valid offset.
+ // Updating max offset may cause problems with interacting with SQL server
+ // which uses SQL DATETIMEOFFSET field type which was originally designed to be
+ // bit-for-bit compatible with DateTimeOffset.
+
+ TimeSpan utcOffset = GetUtcOffset(baseUtcOffset, adjustmentRule);
+
+ // utc base offset delta increment
+ TimeSpan adjustment = TimeSpan.Zero;
+
+ if (utcOffset > MaxOffset)
+ {
+ adjustment = MaxOffset - utcOffset;
+ }
+ else if (utcOffset < MinOffset)
+ {
+ adjustment = MinOffset - utcOffset;
+ }
+
+ if (adjustment != TimeSpan.Zero)
+ {
+ adjustmentRule = AdjustmentRule.CreateAdjustmentRule(
+ adjustmentRule.DateStart,
+ adjustmentRule.DateEnd,
+ adjustmentRule.DaylightDelta,
+ adjustmentRule.DaylightTransitionStart,
+ adjustmentRule.DaylightTransitionEnd,
+ adjustmentRule.BaseUtcOffsetDelta + adjustment,
+ adjustmentRule.NoDaylightTransitions);
+ }
+ }
}
}
diff --git a/src/System.Private.CoreLib/shared/System/TimeZoneNotFoundException.cs b/src/System.Private.CoreLib/shared/System/TimeZoneNotFoundException.cs
index f83c6443c..3dc1bb1d4 100644
--- a/src/System.Private.CoreLib/shared/System/TimeZoneNotFoundException.cs
+++ b/src/System.Private.CoreLib/shared/System/TimeZoneNotFoundException.cs
@@ -14,12 +14,12 @@ namespace System
{
}
- public TimeZoneNotFoundException(String message)
+ public TimeZoneNotFoundException(string message)
: base(message)
{
}
- public TimeZoneNotFoundException(String message, Exception innerException)
+ public TimeZoneNotFoundException(string message, Exception innerException)
: base(message, innerException)
{
}
diff --git a/src/System.Private.CoreLib/shared/System/TimeoutException.cs b/src/System.Private.CoreLib/shared/System/TimeoutException.cs
index ddaa47747..2480f4bc2 100644
--- a/src/System.Private.CoreLib/shared/System/TimeoutException.cs
+++ b/src/System.Private.CoreLib/shared/System/TimeoutException.cs
@@ -25,13 +25,13 @@ namespace System
HResult = HResults.COR_E_TIMEOUT;
}
- public TimeoutException(String message)
+ public TimeoutException(string message)
: base(message)
{
HResult = HResults.COR_E_TIMEOUT;
}
- public TimeoutException(String message, Exception innerException)
+ public TimeoutException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_TIMEOUT;
diff --git a/src/System.Private.CoreLib/shared/System/Tuple.cs b/src/System.Private.CoreLib/shared/System/Tuple.cs
index 141ae08dc..8529e01f9 100644
--- a/src/System.Private.CoreLib/shared/System/Tuple.cs
+++ b/src/System.Private.CoreLib/shared/System/Tuple.cs
@@ -117,12 +117,12 @@ namespace System
m_Item1 = item1;
}
- public override Boolean Equals(Object obj)
+ public override bool Equals(object obj)
{
- return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<Object>.Default);
+ return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<object>.Default);
}
- Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer)
+ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null) return false;
@@ -136,12 +136,12 @@ namespace System
return comparer.Equals(m_Item1, objTuple.m_Item1);
}
- Int32 IComparable.CompareTo(Object obj)
+ int IComparable.CompareTo(object obj)
{
- return ((IStructuralComparable)this).CompareTo(obj, Comparer<Object>.Default);
+ return ((IStructuralComparable)this).CompareTo(obj, Comparer<object>.Default);
}
- Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer)
+ int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
@@ -157,15 +157,15 @@ namespace System
public override int GetHashCode()
{
- return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<Object>.Default);
+ return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<object>.Default);
}
- Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
+ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return comparer.GetHashCode(m_Item1);
}
- Int32 ITupleInternal.GetHashCode(IEqualityComparer comparer)
+ int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return ((IStructuralEquatable)this).GetHashCode(comparer);
}
@@ -222,12 +222,12 @@ namespace System
m_Item2 = item2;
}
- public override Boolean Equals(Object obj)
+ public override bool Equals(object obj)
{
- return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<Object>.Default); ;
+ return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<object>.Default); ;
}
- Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer)
+ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null) return false;
@@ -241,12 +241,12 @@ namespace System
return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2);
}
- Int32 IComparable.CompareTo(Object obj)
+ int IComparable.CompareTo(object obj)
{
- return ((IStructuralComparable)this).CompareTo(obj, Comparer<Object>.Default);
+ return ((IStructuralComparable)this).CompareTo(obj, Comparer<object>.Default);
}
- Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer)
+ int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
@@ -268,15 +268,15 @@ namespace System
public override int GetHashCode()
{
- return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<Object>.Default);
+ return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<object>.Default);
}
- Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
+ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2));
}
- Int32 ITupleInternal.GetHashCode(IEqualityComparer comparer)
+ int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return ((IStructuralEquatable)this).GetHashCode(comparer);
}
@@ -342,12 +342,12 @@ namespace System
m_Item3 = item3;
}
- public override Boolean Equals(Object obj)
+ public override bool Equals(object obj)
{
- return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<Object>.Default); ;
+ return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<object>.Default); ;
}
- Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer)
+ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null) return false;
@@ -361,12 +361,12 @@ namespace System
return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3);
}
- Int32 IComparable.CompareTo(Object obj)
+ int IComparable.CompareTo(object obj)
{
- return ((IStructuralComparable)this).CompareTo(obj, Comparer<Object>.Default);
+ return ((IStructuralComparable)this).CompareTo(obj, Comparer<object>.Default);
}
- Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer)
+ int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
@@ -392,15 +392,15 @@ namespace System
public override int GetHashCode()
{
- return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<Object>.Default);
+ return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<object>.Default);
}
- Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
+ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3));
}
- Int32 ITupleInternal.GetHashCode(IEqualityComparer comparer)
+ int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return ((IStructuralEquatable)this).GetHashCode(comparer);
}
@@ -473,12 +473,12 @@ namespace System
m_Item4 = item4;
}
- public override Boolean Equals(Object obj)
+ public override bool Equals(object obj)
{
- return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<Object>.Default); ;
+ return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<object>.Default); ;
}
- Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer)
+ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null) return false;
@@ -492,12 +492,12 @@ namespace System
return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3) && comparer.Equals(m_Item4, objTuple.m_Item4);
}
- Int32 IComparable.CompareTo(Object obj)
+ int IComparable.CompareTo(object obj)
{
- return ((IStructuralComparable)this).CompareTo(obj, Comparer<Object>.Default);
+ return ((IStructuralComparable)this).CompareTo(obj, Comparer<object>.Default);
}
- Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer)
+ int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
@@ -527,15 +527,15 @@ namespace System
public override int GetHashCode()
{
- return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<Object>.Default);
+ return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<object>.Default);
}
- Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
+ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4));
}
- Int32 ITupleInternal.GetHashCode(IEqualityComparer comparer)
+ int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return ((IStructuralEquatable)this).GetHashCode(comparer);
}
@@ -615,12 +615,12 @@ namespace System
m_Item5 = item5;
}
- public override Boolean Equals(Object obj)
+ public override bool Equals(object obj)
{
- return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<Object>.Default); ;
+ return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<object>.Default); ;
}
- Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer)
+ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null) return false;
@@ -634,12 +634,12 @@ namespace System
return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3) && comparer.Equals(m_Item4, objTuple.m_Item4) && comparer.Equals(m_Item5, objTuple.m_Item5);
}
- Int32 IComparable.CompareTo(Object obj)
+ int IComparable.CompareTo(object obj)
{
- return ((IStructuralComparable)this).CompareTo(obj, Comparer<Object>.Default);
+ return ((IStructuralComparable)this).CompareTo(obj, Comparer<object>.Default);
}
- Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer)
+ int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
@@ -673,15 +673,15 @@ namespace System
public override int GetHashCode()
{
- return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<Object>.Default);
+ return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<object>.Default);
}
- Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
+ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5));
}
- Int32 ITupleInternal.GetHashCode(IEqualityComparer comparer)
+ int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return ((IStructuralEquatable)this).GetHashCode(comparer);
}
@@ -768,12 +768,12 @@ namespace System
m_Item6 = item6;
}
- public override Boolean Equals(Object obj)
+ public override bool Equals(object obj)
{
- return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<Object>.Default); ;
+ return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<object>.Default); ;
}
- Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer)
+ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null) return false;
@@ -787,12 +787,12 @@ namespace System
return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3) && comparer.Equals(m_Item4, objTuple.m_Item4) && comparer.Equals(m_Item5, objTuple.m_Item5) && comparer.Equals(m_Item6, objTuple.m_Item6);
}
- Int32 IComparable.CompareTo(Object obj)
+ int IComparable.CompareTo(object obj)
{
- return ((IStructuralComparable)this).CompareTo(obj, Comparer<Object>.Default);
+ return ((IStructuralComparable)this).CompareTo(obj, Comparer<object>.Default);
}
- Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer)
+ int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
@@ -830,15 +830,15 @@ namespace System
public override int GetHashCode()
{
- return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<Object>.Default);
+ return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<object>.Default);
}
- Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
+ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5), comparer.GetHashCode(m_Item6));
}
- Int32 ITupleInternal.GetHashCode(IEqualityComparer comparer)
+ int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return ((IStructuralEquatable)this).GetHashCode(comparer);
}
@@ -932,12 +932,12 @@ namespace System
m_Item7 = item7;
}
- public override Boolean Equals(Object obj)
+ public override bool Equals(object obj)
{
- return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<Object>.Default); ;
+ return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<object>.Default); ;
}
- Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer)
+ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null) return false;
@@ -951,12 +951,12 @@ namespace System
return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3) && comparer.Equals(m_Item4, objTuple.m_Item4) && comparer.Equals(m_Item5, objTuple.m_Item5) && comparer.Equals(m_Item6, objTuple.m_Item6) && comparer.Equals(m_Item7, objTuple.m_Item7);
}
- Int32 IComparable.CompareTo(Object obj)
+ int IComparable.CompareTo(object obj)
{
- return ((IStructuralComparable)this).CompareTo(obj, Comparer<Object>.Default);
+ return ((IStructuralComparable)this).CompareTo(obj, Comparer<object>.Default);
}
- Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer)
+ int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
@@ -998,15 +998,15 @@ namespace System
public override int GetHashCode()
{
- return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<Object>.Default);
+ return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<object>.Default);
}
- Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
+ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5), comparer.GetHashCode(m_Item6), comparer.GetHashCode(m_Item7));
}
- Int32 ITupleInternal.GetHashCode(IEqualityComparer comparer)
+ int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return ((IStructuralEquatable)this).GetHashCode(comparer);
}
@@ -1112,12 +1112,12 @@ namespace System
m_Rest = rest;
}
- public override Boolean Equals(Object obj)
+ public override bool Equals(object obj)
{
- return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<Object>.Default); ;
+ return ((IStructuralEquatable)this).Equals(obj, EqualityComparer<object>.Default); ;
}
- Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer)
+ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null) return false;
@@ -1131,12 +1131,12 @@ namespace System
return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3) && comparer.Equals(m_Item4, objTuple.m_Item4) && comparer.Equals(m_Item5, objTuple.m_Item5) && comparer.Equals(m_Item6, objTuple.m_Item6) && comparer.Equals(m_Item7, objTuple.m_Item7) && comparer.Equals(m_Rest, objTuple.m_Rest);
}
- Int32 IComparable.CompareTo(Object obj)
+ int IComparable.CompareTo(object obj)
{
- return ((IStructuralComparable)this).CompareTo(obj, Comparer<Object>.Default);
+ return ((IStructuralComparable)this).CompareTo(obj, Comparer<object>.Default);
}
- Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer)
+ int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null) return 1;
@@ -1182,10 +1182,10 @@ namespace System
public override int GetHashCode()
{
- return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<Object>.Default);
+ return ((IStructuralEquatable)this).GetHashCode(EqualityComparer<object>.Default);
}
- Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
+ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
// We want to have a limited hash in this case. We'll use the last 8 elements of the tuple
ITupleInternal t = (ITupleInternal)m_Rest;
@@ -1214,7 +1214,7 @@ namespace System
return -1;
}
- Int32 ITupleInternal.GetHashCode(IEqualityComparer comparer)
+ int ITupleInternal.GetHashCode(IEqualityComparer comparer)
{
return ((IStructuralEquatable)this).GetHashCode(comparer);
}
diff --git a/src/System.Private.CoreLib/shared/System/Type.Helpers.cs b/src/System.Private.CoreLib/shared/System/Type.Helpers.cs
index db8df231e..3de7d827e 100644
--- a/src/System.Private.CoreLib/shared/System/Type.Helpers.cs
+++ b/src/System.Private.CoreLib/shared/System/Type.Helpers.cs
@@ -473,54 +473,31 @@ namespace System
// This method will filter based upon the name. A partial wildcard
// at the end of the string is supported.
// filterCriteria -- This is the string name
- private static bool FilterNameImpl(MemberInfo m, object filterCriteria)
+ private static bool FilterNameImpl(MemberInfo m, object filterCriteria, StringComparison comparison)
{
// Check that the criteria object is a String object
- if (filterCriteria == null || !(filterCriteria is string))
+ if (!(filterCriteria is string filterCriteriaString))
+ {
throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritString);
+ }
- // At the moment this fails if its done on a single line....
- string str = ((string)filterCriteria);
- str = str.Trim();
+ ReadOnlySpan<char> str = filterCriteriaString.AsSpan().Trim();
+ ReadOnlySpan<char> name = m.Name;
- string name = m.Name;
// Get the nested class name only, as opposed to the mangled one
if (m.MemberType == MemberTypes.NestedType)
- name = name.Substring(name.LastIndexOf('+') + 1);
- // Check to see if this is a prefix or exact match requirement
- if (str.Length > 0 && str[str.Length - 1] == '*')
{
- str = str.Substring(0, str.Length - 1);
- return (name.StartsWith(str, StringComparison.Ordinal));
+ name = name.Slice(name.LastIndexOf('+') + 1);
}
- return (name.Equals(str));
- }
-
- // FilterIgnoreCase
- // This delegate will do a name search but does it with the
- // ignore case specified.
- private static bool FilterNameIgnoreCaseImpl(MemberInfo m, object filterCriteria)
- {
- // Check that the criteria object is a String object
- if (filterCriteria == null || !(filterCriteria is string))
- throw new InvalidFilterCriteriaException(SR.InvalidFilterCriteriaException_CritString);
-
- string str = (string)filterCriteria;
- str = str.Trim();
-
- string name = m.Name;
- // Get the nested class name only, as opposed to the mangled one
- if (m.MemberType == MemberTypes.NestedType)
- name = name.Substring(name.LastIndexOf('+') + 1);
// Check to see if this is a prefix or exact match requirement
if (str.Length > 0 && str[str.Length - 1] == '*')
{
- str = str.Substring(0, str.Length - 1);
- return (string.Compare(name, 0, str, 0, str.Length, StringComparison.OrdinalIgnoreCase) == 0);
+ str = str.Slice(0, str.Length - 1);
+ return name.StartsWith(str, comparison);
}
- return (string.Compare(str, name, StringComparison.OrdinalIgnoreCase) == 0);
+ return name.Equals(str, comparison);
}
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Type.cs b/src/System.Private.CoreLib/shared/System/Type.cs
index a0d219ddd..c78d98833 100644
--- a/src/System.Private.CoreLib/shared/System/Type.cs
+++ b/src/System.Private.CoreLib/shared/System/Type.cs
@@ -346,10 +346,12 @@ namespace System
public virtual Type MakeGenericType(params Type[] typeArguments) { throw new NotSupportedException(SR.NotSupported_SubclassOverride); }
public virtual Type MakePointerType() { throw new NotSupportedException(); }
+ public static Type MakeGenericSignatureType(Type genericTypeDefinition, params Type[] typeArguments) => new SignatureConstructedGenericType(genericTypeDefinition, typeArguments);
+
public static Type MakeGenericMethodParameter(int position)
{
if (position < 0)
- throw new ArgumentException(SR.ArgumentOutOfRange_MustBeNonNegNum, nameof(position));
+ throw new ArgumentException(SR.ArgumentOutOfRange_NeedNonNegNum, nameof(position));
return new SignatureGenericMethodParameterType(position);
}
@@ -387,8 +389,8 @@ namespace System
public static readonly object Missing = System.Reflection.Missing.Value;
public static readonly MemberFilter FilterAttribute = FilterAttributeImpl;
- public static readonly MemberFilter FilterName = FilterNameImpl;
- public static readonly MemberFilter FilterNameIgnoreCase = FilterNameIgnoreCaseImpl;
+ public static readonly MemberFilter FilterName = (m, c) => FilterNameImpl(m, c, StringComparison.Ordinal);
+ public static readonly MemberFilter FilterNameIgnoreCase = (m, c) => FilterNameImpl(m, c, StringComparison.OrdinalIgnoreCase);
private const BindingFlags DefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
}
diff --git a/src/System.Private.CoreLib/shared/System/TypeInitializationException.cs b/src/System.Private.CoreLib/shared/System/TypeInitializationException.cs
index 4bf290621..2ef822ab2 100644
--- a/src/System.Private.CoreLib/shared/System/TypeInitializationException.cs
+++ b/src/System.Private.CoreLib/shared/System/TypeInitializationException.cs
@@ -23,7 +23,7 @@ namespace System
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public sealed class TypeInitializationException : SystemException
{
- private String _typeName;
+ private string _typeName;
// This exception is not creatable without specifying the
// inner exception.
@@ -34,19 +34,19 @@ namespace System
}
- public TypeInitializationException(String fullTypeName, Exception innerException)
+ public TypeInitializationException(string fullTypeName, Exception innerException)
: this(fullTypeName, SR.Format(SR.TypeInitialization_Type, fullTypeName), innerException)
{
}
// This is called from within the runtime. I believe this is necessary
// for Interop only, though it's not particularly useful.
- internal TypeInitializationException(String message) : base(message)
+ internal TypeInitializationException(string message) : base(message)
{
HResult = HResults.COR_E_TYPEINITIALIZATION;
}
- internal TypeInitializationException(String fullTypeName, String message, Exception innerException)
+ internal TypeInitializationException(string fullTypeName, string message, Exception innerException)
: base(message, innerException)
{
_typeName = fullTypeName;
@@ -65,13 +65,13 @@ namespace System
info.AddValue("TypeName", TypeName, typeof(string));
}
- public String TypeName
+ public string TypeName
{
get
{
if (_typeName == null)
{
- return String.Empty;
+ return string.Empty;
}
return _typeName;
}
diff --git a/src/System.Private.CoreLib/shared/System/UInt16.cs b/src/System.Private.CoreLib/shared/System/UInt16.cs
index 3047d1819..f9ef1f6a6 100644
--- a/src/System.Private.CoreLib/shared/System/UInt16.cs
+++ b/src/System.Private.CoreLib/shared/System/UInt16.cs
@@ -13,9 +13,9 @@ namespace System
[CLSCompliant(false)]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct UInt16 : IComparable, IConvertible, IFormattable, IComparable<UInt16>, IEquatable<UInt16>, ISpanFormattable
+ public readonly struct UInt16 : IComparable, IConvertible, IFormattable, IComparable<ushort>, IEquatable<ushort>, ISpanFormattable
{
- private ushort m_value; // Do not rename (binary serialization)
+ private readonly ushort m_value; // Do not rename (binary serialization)
public const ushort MaxValue = (ushort)0xFFFF;
public const ushort MinValue = 0;
@@ -27,35 +27,35 @@ namespace System
// null is considered to be less than any instance.
// If object is not of type UInt16, this method throws an ArgumentException.
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
- if (value is UInt16)
+ if (value is ushort)
{
- return ((int)m_value - (int)(((UInt16)value).m_value));
+ return ((int)m_value - (int)(((ushort)value).m_value));
}
throw new ArgumentException(SR.Arg_MustBeUInt16);
}
- public int CompareTo(UInt16 value)
+ public int CompareTo(ushort value)
{
return ((int)m_value - (int)value);
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is UInt16))
+ if (!(obj is ushort))
{
return false;
}
- return m_value == ((UInt16)obj).m_value;
+ return m_value == ((ushort)obj).m_value;
}
[NonVersionable]
- public bool Equals(UInt16 obj)
+ public bool Equals(ushort obj)
{
return m_value == obj;
}
@@ -67,23 +67,23 @@ namespace System
}
// Converts the current value to a String in base-10 with no extra padding.
- public override String ToString()
+ public override string ToString()
{
return Number.FormatUInt32(m_value, null, null);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return Number.FormatUInt32(m_value, null, provider);
}
- public String ToString(String format)
+ public string ToString(string format)
{
return Number.FormatUInt32(m_value, format, null);
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
return Number.FormatUInt32(m_value, format, provider);
}
@@ -94,14 +94,14 @@ namespace System
}
[CLSCompliant(false)]
- public static ushort Parse(String s)
+ public static ushort Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}
[CLSCompliant(false)]
- public static ushort Parse(String s, NumberStyles style)
+ public static ushort Parse(string s, NumberStyles style)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -110,14 +110,14 @@ namespace System
[CLSCompliant(false)]
- public static ushort Parse(String s, IFormatProvider provider)
+ public static ushort Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Parse((ReadOnlySpan<char>)s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
}
[CLSCompliant(false)]
- public static ushort Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static ushort Parse(string s, NumberStyles style, IFormatProvider provider)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -148,7 +148,7 @@ namespace System
}
[CLSCompliant(false)]
- public static bool TryParse(String s, out UInt16 result)
+ public static bool TryParse(string s, out ushort result)
{
if (s == null)
{
@@ -166,7 +166,7 @@ namespace System
}
[CLSCompliant(false)]
- public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out UInt16 result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out ushort result)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
@@ -186,10 +186,10 @@ namespace System
return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
}
- private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out UInt16 result)
+ private static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, NumberFormatInfo info, out ushort result)
{
result = 0;
- UInt32 i;
+ uint i;
if (!Number.TryParseUInt32(s, style, info, out i))
{
return false;
@@ -198,7 +198,7 @@ namespace System
{
return false;
}
- result = (UInt16)i;
+ result = (ushort)i;
return true;
}
@@ -271,7 +271,7 @@ namespace System
return Convert.ToDouble(m_value);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -281,7 +281,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "UInt16", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/UInt32.cs b/src/System.Private.CoreLib/shared/System/UInt32.cs
index 1e33dcf17..5ed193e95 100644
--- a/src/System.Private.CoreLib/shared/System/UInt32.cs
+++ b/src/System.Private.CoreLib/shared/System/UInt32.cs
@@ -13,9 +13,9 @@ namespace System
[CLSCompliant(false)]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct UInt32 : IComparable, IConvertible, IFormattable, IComparable<UInt32>, IEquatable<UInt32>, ISpanFormattable
+ public readonly struct UInt32 : IComparable, IConvertible, IFormattable, IComparable<uint>, IEquatable<uint>, ISpanFormattable
{
- private uint m_value; // Do not rename (binary serialization)
+ private readonly uint m_value; // Do not rename (binary serialization)
public const uint MaxValue = (uint)0xffffffff;
public const uint MinValue = 0U;
@@ -27,13 +27,13 @@ namespace System
// null is considered to be less than any instance.
// If object is not of type UInt32, this method throws an ArgumentException.
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
- if (value is UInt32)
+ if (value is uint)
{
// Need to use compare because subtraction will wrap
// to positive for very large neg numbers, etc.
@@ -45,7 +45,7 @@ namespace System
throw new ArgumentException(SR.Arg_MustBeUInt32);
}
- public int CompareTo(UInt32 value)
+ public int CompareTo(uint value)
{
// Need to use compare because subtraction will wrap
// to positive for very large neg numbers, etc.
@@ -54,17 +54,17 @@ namespace System
return 0;
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is UInt32))
+ if (!(obj is uint))
{
return false;
}
- return m_value == ((UInt32)obj).m_value;
+ return m_value == ((uint)obj).m_value;
}
[NonVersionable]
- public bool Equals(UInt32 obj)
+ public bool Equals(uint obj)
{
return m_value == obj;
}
@@ -76,22 +76,22 @@ namespace System
}
// The base 10 representation of the number with no extra padding.
- public override String ToString()
+ public override string ToString()
{
return Number.FormatUInt32(m_value, null, null);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return Number.FormatUInt32(m_value, null, provider);
}
- public String ToString(String format)
+ public string ToString(string format)
{
return Number.FormatUInt32(m_value, format, null);
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
return Number.FormatUInt32(m_value, format, provider);
}
@@ -102,14 +102,14 @@ namespace System
}
[CLSCompliant(false)]
- public static uint Parse(String s)
+ public static uint Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseUInt32(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}
[CLSCompliant(false)]
- public static uint Parse(String s, NumberStyles style)
+ public static uint Parse(string s, NumberStyles style)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -118,14 +118,14 @@ namespace System
[CLSCompliant(false)]
- public static uint Parse(String s, IFormatProvider provider)
+ public static uint Parse(string s, IFormatProvider provider)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseUInt32(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
}
[CLSCompliant(false)]
- public static uint Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static uint Parse(string s, NumberStyles style, IFormatProvider provider)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -140,7 +140,7 @@ namespace System
}
[CLSCompliant(false)]
- public static bool TryParse(String s, out UInt32 result)
+ public static bool TryParse(string s, out uint result)
{
if (s == null)
{
@@ -158,7 +158,7 @@ namespace System
}
[CLSCompliant(false)]
- public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out UInt32 result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out uint result)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
@@ -247,7 +247,7 @@ namespace System
return Convert.ToDouble(m_value);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -257,7 +257,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "UInt32", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/UInt64.cs b/src/System.Private.CoreLib/shared/System/UInt64.cs
index d30fbe1e4..6abd76da2 100644
--- a/src/System.Private.CoreLib/shared/System/UInt64.cs
+++ b/src/System.Private.CoreLib/shared/System/UInt64.cs
@@ -13,9 +13,9 @@ namespace System
[CLSCompliant(false)]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct UInt64 : IComparable, IConvertible, IFormattable, IComparable<UInt64>, IEquatable<UInt64>, ISpanFormattable
+ public readonly struct UInt64 : IComparable, IConvertible, IFormattable, IComparable<ulong>, IEquatable<ulong>, ISpanFormattable
{
- private ulong m_value; // Do not rename (binary serialization)
+ private readonly ulong m_value; // Do not rename (binary serialization)
public const ulong MaxValue = (ulong)0xffffffffffffffffL;
public const ulong MinValue = 0x0;
@@ -26,13 +26,13 @@ namespace System
// null is considered to be less than any instance.
// If object is not of type UInt64, this method throws an ArgumentException.
//
- public int CompareTo(Object value)
+ public int CompareTo(object value)
{
if (value == null)
{
return 1;
}
- if (value is UInt64)
+ if (value is ulong)
{
// Need to use compare because subtraction will wrap
// to positive for very large neg numbers, etc.
@@ -44,7 +44,7 @@ namespace System
throw new ArgumentException(SR.Arg_MustBeUInt64);
}
- public int CompareTo(UInt64 value)
+ public int CompareTo(ulong value)
{
// Need to use compare because subtraction will wrap
// to positive for very large neg numbers, etc.
@@ -53,17 +53,17 @@ namespace System
return 0;
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
- if (!(obj is UInt64))
+ if (!(obj is ulong))
{
return false;
}
- return m_value == ((UInt64)obj).m_value;
+ return m_value == ((ulong)obj).m_value;
}
[NonVersionable]
- public bool Equals(UInt64 obj)
+ public bool Equals(ulong obj)
{
return m_value == obj;
}
@@ -74,22 +74,22 @@ namespace System
return ((int)m_value) ^ (int)(m_value >> 32);
}
- public override String ToString()
+ public override string ToString()
{
return Number.FormatUInt64(m_value, null, null);
}
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return Number.FormatUInt64(m_value, null, provider);
}
- public String ToString(String format)
+ public string ToString(string format)
{
return Number.FormatUInt64(m_value, format, null);
}
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
return Number.FormatUInt64(m_value, format, provider);
}
@@ -100,14 +100,14 @@ namespace System
}
[CLSCompliant(false)]
- public static ulong Parse(String s)
+ public static ulong Parse(string s)
{
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
return Number.ParseUInt64(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}
[CLSCompliant(false)]
- public static ulong Parse(String s, NumberStyles style)
+ public static ulong Parse(string s, NumberStyles style)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -122,7 +122,7 @@ namespace System
}
[CLSCompliant(false)]
- public static ulong Parse(String s, NumberStyles style, IFormatProvider provider)
+ public static ulong Parse(string s, NumberStyles style, IFormatProvider provider)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s);
@@ -137,7 +137,7 @@ namespace System
}
[CLSCompliant(false)]
- public static Boolean TryParse(String s, out UInt64 result)
+ public static bool TryParse(string s, out ulong result)
{
if (s == null)
{
@@ -155,7 +155,7 @@ namespace System
}
[CLSCompliant(false)]
- public static Boolean TryParse(String s, NumberStyles style, IFormatProvider provider, out UInt64 result)
+ public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out ulong result)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
@@ -244,7 +244,7 @@ namespace System
return Convert.ToDouble(m_value);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value);
}
@@ -254,7 +254,7 @@ namespace System
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "UInt64", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/shared/System/UIntPtr.cs b/src/System.Private.CoreLib/shared/System/UIntPtr.cs
index 23750e95f..c57dd86a7 100644
--- a/src/System.Private.CoreLib/shared/System/UIntPtr.cs
+++ b/src/System.Private.CoreLib/shared/System/UIntPtr.cs
@@ -18,9 +18,9 @@ namespace System
[Serializable]
[CLSCompliant(false)]
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
- public struct UIntPtr : IEquatable<UIntPtr>, ISerializable
+ public readonly struct UIntPtr : IEquatable<UIntPtr>, ISerializable
{
- unsafe private void* _value; // Do not rename (binary serialization)
+ private readonly unsafe void* _value; // Do not rename (binary serialization)
[Intrinsic]
public static readonly UIntPtr Zero;
@@ -68,7 +68,7 @@ namespace System
info.AddValue("value", ToUInt64());
}
- public unsafe override bool Equals(Object obj)
+ public unsafe override bool Equals(object obj)
{
if (obj is UIntPtr)
{
@@ -77,9 +77,9 @@ namespace System
return false;
}
- unsafe bool IEquatable<UIntPtr>.Equals(UIntPtr value)
+ unsafe bool IEquatable<UIntPtr>.Equals(UIntPtr other)
{
- return _value == value._value;
+ return _value == other._value;
}
public unsafe override int GetHashCode()
@@ -208,6 +208,9 @@ namespace System
[Intrinsic]
[NonVersionable]
+#if PROJECTN
+ [System.Runtime.CompilerServices.DependencyReductionRootAttribute]
+#endif
public unsafe void* ToPointer()
{
return _value;
diff --git a/src/System.Private.CoreLib/shared/System/UnauthorizedAccessException.cs b/src/System.Private.CoreLib/shared/System/UnauthorizedAccessException.cs
index a28f6dd73..e384dfeb3 100644
--- a/src/System.Private.CoreLib/shared/System/UnauthorizedAccessException.cs
+++ b/src/System.Private.CoreLib/shared/System/UnauthorizedAccessException.cs
@@ -29,13 +29,13 @@ namespace System
HResult = HResults.COR_E_UNAUTHORIZEDACCESS;
}
- public UnauthorizedAccessException(String message)
+ public UnauthorizedAccessException(string message)
: base(message)
{
HResult = HResults.COR_E_UNAUTHORIZEDACCESS;
}
- public UnauthorizedAccessException(String message, Exception inner)
+ public UnauthorizedAccessException(string message, Exception inner)
: base(message, inner)
{
HResult = HResults.COR_E_UNAUTHORIZEDACCESS;
diff --git a/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventArgs.cs b/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventArgs.cs
index 5cde57216..c214afdc7 100644
--- a/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventArgs.cs
+++ b/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventArgs.cs
@@ -6,16 +6,16 @@ namespace System
{
public class UnhandledExceptionEventArgs : EventArgs
{
- private Object _exception;
+ private object _exception;
private bool _isTerminating;
- public UnhandledExceptionEventArgs(Object exception, bool isTerminating)
+ public UnhandledExceptionEventArgs(object exception, bool isTerminating)
{
_exception = exception;
_isTerminating = isTerminating;
}
- public Object ExceptionObject
+ public object ExceptionObject
{
get { return _exception; }
}
diff --git a/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventHandler.cs b/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventHandler.cs
index 14e31c7bb..58f1eb514 100644
--- a/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventHandler.cs
+++ b/src/System.Private.CoreLib/shared/System/UnhandledExceptionEventHandler.cs
@@ -4,5 +4,5 @@
namespace System
{
- public delegate void UnhandledExceptionEventHandler(Object sender, UnhandledExceptionEventArgs e);
+ public delegate void UnhandledExceptionEventHandler(object sender, UnhandledExceptionEventArgs e);
}
diff --git a/src/System.Private.CoreLib/shared/System/UnitySerializationHolder.cs b/src/System.Private.CoreLib/shared/System/UnitySerializationHolder.cs
index 2f3035670..53323c32b 100644
--- a/src/System.Private.CoreLib/shared/System/UnitySerializationHolder.cs
+++ b/src/System.Private.CoreLib/shared/System/UnitySerializationHolder.cs
@@ -11,12 +11,8 @@ namespace System
/// This only exists for compatibility with .NET Framework.
/// </summary>
[Serializable]
-#if CORERT
- public
-#else
- internal
-#endif
- sealed class UnitySerializationHolder : ISerializable, IObjectReference
+ // Needs to be public to support binary serialization compatibility
+ public sealed class UnitySerializationHolder : ISerializable, IObjectReference
{
internal const int NullUnity = 0x0002;
private readonly int _unityType;
diff --git a/src/System.Private.CoreLib/shared/System/ValueTuple.cs b/src/System.Private.CoreLib/shared/System/ValueTuple.cs
index e89d83097..b486573ff 100644
--- a/src/System.Private.CoreLib/shared/System/ValueTuple.cs
+++ b/src/System.Private.CoreLib/shared/System/ValueTuple.cs
@@ -638,7 +638,7 @@ namespace System
/// The string returned by this method takes the form <c>(Item1, Item2)</c>,
/// where <c>Item1</c> and <c>Item2</c> represent the values of the <see cref="Item1"/>
/// and <see cref="Item2"/> fields. If either field value is <see langword="null"/>,
- /// it is represented as <see cref="String.Empty"/>.
+ /// it is represented as <see cref="string.Empty"/>.
/// </remarks>
public override string ToString()
{
@@ -846,7 +846,7 @@ namespace System
/// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3}"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>(Item1, Item2, Item3)</c>.
- /// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
+ /// If any field value is <see langword="null"/>, it is represented as <see cref="string.Empty"/>.
/// </remarks>
public override string ToString()
{
@@ -1073,7 +1073,7 @@ namespace System
/// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3, T4}"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>(Item1, Item2, Item3, Item4)</c>.
- /// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
+ /// If any field value is <see langword="null"/>, it is represented as <see cref="string.Empty"/>.
/// </remarks>
public override string ToString()
{
@@ -1319,7 +1319,7 @@ namespace System
/// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3, T4, T5}"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>(Item1, Item2, Item3, Item4, Item5)</c>.
- /// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
+ /// If any field value is <see langword="null"/>, it is represented as <see cref="string.Empty"/>.
/// </remarks>
public override string ToString()
{
@@ -1584,7 +1584,7 @@ namespace System
/// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3, T4, T5, T6}"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>(Item1, Item2, Item3, Item4, Item5, Item6)</c>.
- /// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
+ /// If any field value is <see langword="null"/>, it is represented as <see cref="string.Empty"/>.
/// </remarks>
public override string ToString()
{
@@ -1868,7 +1868,7 @@ namespace System
/// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7}"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>(Item1, Item2, Item3, Item4, Item5, Item6, Item7)</c>.
- /// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
+ /// If any field value is <see langword="null"/>, it is represented as <see cref="string.Empty"/>.
/// </remarks>
public override string ToString()
{
@@ -2270,7 +2270,7 @@ namespace System
/// <returns>The string representation of this <see cref="ValueTuple{T1, T2, T3, T4, T5, T6, T7, TRest}"/> instance.</returns>
/// <remarks>
/// The string returned by this method takes the form <c>(Item1, Item2, Item3, Item4, Item5, Item6, Item7, Rest)</c>.
- /// If any field value is <see langword="null"/>, it is represented as <see cref="String.Empty"/>.
+ /// If any field value is <see langword="null"/>, it is represented as <see cref="string.Empty"/>.
/// </remarks>
public override string ToString()
{
diff --git a/src/System.Private.CoreLib/shared/System/Version.cs b/src/System.Private.CoreLib/shared/System/Version.cs
index 9e4cefcd6..444ee4885 100644
--- a/src/System.Private.CoreLib/shared/System/Version.cs
+++ b/src/System.Private.CoreLib/shared/System/Version.cs
@@ -73,7 +73,7 @@ namespace System
_Minor = minor;
}
- public Version(String version)
+ public Version(string version)
{
Version v = Version.Parse(version);
_Major = v.Major;
@@ -134,7 +134,7 @@ namespace System
get { return (short)(_Revision & 0xFFFF); }
}
- public int CompareTo(Object version)
+ public int CompareTo(object version)
{
if (version == null)
{
@@ -154,7 +154,7 @@ namespace System
{
return
object.ReferenceEquals(value, this) ? 0 :
- object.ReferenceEquals(value, null) ? 1 :
+ value is null ? 1 :
_Major != value._Major ? (_Major > value._Major ? 1 : -1) :
_Minor != value._Minor ? (_Minor > value._Minor ? 1 : -1) :
_Build != value._Build ? (_Build > value._Build ? 1 : -1) :
@@ -162,7 +162,7 @@ namespace System
0;
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
return Equals(obj as Version);
}
@@ -170,7 +170,7 @@ namespace System
public bool Equals(Version obj)
{
return object.ReferenceEquals(obj, this) ||
- (!object.ReferenceEquals(obj, null) &&
+ (!(obj is null) &&
_Major == obj._Major &&
_Minor == obj._Minor &&
_Build == obj._Build &&
@@ -333,13 +333,15 @@ namespace System
// Find the ends of the optional minor and build portions.
// We musn't have any separators after build.
int buildEnd = -1;
- int minorEnd = input.IndexOf('.', majorEnd + 1);
+ int minorEnd = input.Slice(majorEnd + 1).IndexOf('.');
if (minorEnd != -1)
{
- buildEnd = input.IndexOf('.', minorEnd + 1);
+ minorEnd += (majorEnd + 1);
+ buildEnd = input.Slice(minorEnd + 1).IndexOf('.');
if (buildEnd != -1)
{
- if (input.IndexOf('.', buildEnd + 1) != -1)
+ buildEnd += (minorEnd + 1);
+ if (input.Slice(buildEnd + 1).Contains('.'))
{
if (throwOnFailure) throw new ArgumentException(SR.Arg_VersionString, nameof(input));
return null;
@@ -347,10 +349,10 @@ namespace System
}
}
- int major, minor, build, revision;
+ int minor, build, revision;
// Parse the major version
- if (!TryParseComponent(input.Slice(0, majorEnd), nameof(input), throwOnFailure, out major))
+ if (!TryParseComponent(input.Slice(0, majorEnd), nameof(input), throwOnFailure, out int major))
{
return null;
}
@@ -405,9 +407,9 @@ namespace System
public static bool operator ==(Version v1, Version v2)
{
- if (Object.ReferenceEquals(v1, null))
+ if (v1 is null)
{
- return Object.ReferenceEquals(v2, null);
+ return v2 is null;
}
return v1.Equals(v2);
@@ -420,14 +422,14 @@ namespace System
public static bool operator <(Version v1, Version v2)
{
- if ((Object)v1 == null)
+ if ((object)v1 == null)
throw new ArgumentNullException(nameof(v1));
return (v1.CompareTo(v2) < 0);
}
public static bool operator <=(Version v1, Version v2)
{
- if ((Object)v1 == null)
+ if ((object)v1 == null)
throw new ArgumentNullException(nameof(v1));
return (v1.CompareTo(v2) <= 0);
}
diff --git a/src/System.Private.CoreLib/src/Internal/DeveloperExperience/DeveloperExperience.cs b/src/System.Private.CoreLib/src/Internal/DeveloperExperience/DeveloperExperience.cs
index 791f0ed35..c507307c6 100644
--- a/src/System.Private.CoreLib/src/Internal/DeveloperExperience/DeveloperExperience.cs
+++ b/src/System.Private.CoreLib/src/Internal/DeveloperExperience/DeveloperExperience.cs
@@ -16,28 +16,49 @@ namespace Internal.DeveloperExperience
[System.Runtime.CompilerServices.ReflectionBlocked]
public class DeveloperExperience
{
- public virtual void WriteLine(String s)
+ /// <summary>
+ /// Check the AppCompat switch 'Diagnostics.DisableMetadataStackTraceResolution'.
+ /// Some customers use DIA-based tooling to translate stack traces in the raw format
+ /// (module)+RVA - for them, stack trace and reflection metadata-based resolution
+ /// constitutes technically a regression because these two resolution methods today cannot
+ /// provide file name and line number information; PDB-based tooling can easily do that
+ /// based on the RVA information.
+ ///
+ /// Note: a related switch 'Diagnostics.DisableDiaStackTraceResolution' controls whether
+ /// runtime may try to use DIA for PDB-based stack frame resolution.
+ /// </summary>
+ private static bool IsMetadataStackTraceResolutionDisabled()
+ {
+ bool disableMetadata = false;
+ AppContext.TryGetSwitch("Diagnostics.DisableMetadataStackTraceResolution", out disableMetadata);
+ return disableMetadata;
+ }
+
+ public virtual void WriteLine(string s)
{
Debug.WriteLine(s);
return;
}
- public virtual String CreateStackTraceString(IntPtr ip, bool includeFileInfo)
+ public virtual string CreateStackTraceString(IntPtr ip, bool includeFileInfo)
{
- StackTraceMetadataCallbacks stackTraceCallbacks = RuntimeAugments.StackTraceCallbacksIfAvailable;
- if (stackTraceCallbacks != null)
+ if (!IsMetadataStackTraceResolutionDisabled())
{
- IntPtr methodStart = RuntimeImports.RhFindMethodStartAddress(ip);
- if (methodStart != IntPtr.Zero)
+ StackTraceMetadataCallbacks stackTraceCallbacks = RuntimeAugments.StackTraceCallbacksIfAvailable;
+ if (stackTraceCallbacks != null)
{
- string methodName = stackTraceCallbacks.TryGetMethodNameFromStartAddress(methodStart);
- if (methodName != null)
+ IntPtr methodStart = RuntimeImports.RhFindMethodStartAddress(ip);
+ if (methodStart != IntPtr.Zero)
{
- if (ip != methodStart)
+ string methodName = stackTraceCallbacks.TryGetMethodNameFromStartAddress(methodStart);
+ if (methodName != null)
{
- methodName += " + 0x" + (ip.ToInt64() - methodStart.ToInt64()).ToString("x");
+ if (ip != methodStart)
+ {
+ methodName += " + 0x" + (ip.ToInt64() - methodStart.ToInt64()).ToString("x");
+ }
+ return methodName;
}
- return methodName;
}
}
}
@@ -53,7 +74,7 @@ namespace Internal.DeveloperExperience
}
StringBuilder sb = new StringBuilder();
- String fileNameWithoutExtension = GetFileNameWithoutExtension(moduleFullFileName);
+ string fileNameWithoutExtension = GetFileNameWithoutExtension(moduleFullFileName);
int rva = RuntimeAugments.ConvertIpToRva(ip);
sb.Append(fileNameWithoutExtension);
sb.Append("!<BaseAddress>+0x");
@@ -86,7 +107,7 @@ namespace Internal.DeveloperExperience
}
}
- public virtual bool OnContractFailure(String stackTrace, ContractFailureKind contractFailureKind, String displayMessage, String userMessage, String conditionText, Exception innerException)
+ public virtual bool OnContractFailure(string stackTrace, ContractFailureKind contractFailureKind, string displayMessage, string userMessage, string conditionText, Exception innerException)
{
Debug.WriteLine("Assertion failed: " + (displayMessage == null ? "" : displayMessage));
if (Debugger.IsAttached)
@@ -110,7 +131,7 @@ namespace Internal.DeveloperExperience
}
}
- private static String GetFileNameWithoutExtension(String path)
+ private static string GetFileNameWithoutExtension(string path)
{
path = GetFileName(path);
int i;
@@ -120,7 +141,7 @@ namespace Internal.DeveloperExperience
return path.Substring(0, i);
}
- private static String GetFileName(String path)
+ private static string GetFileName(string path)
{
int length = path.Length;
for (int i = length; --i >= 0;)
diff --git a/src/System.Private.CoreLib/src/Internal/IntrinsicSupport/ComparerHelpers.cs b/src/System.Private.CoreLib/src/Internal/IntrinsicSupport/ComparerHelpers.cs
index bcbd541dd..f88223917 100644
--- a/src/System.Private.CoreLib/src/Internal/IntrinsicSupport/ComparerHelpers.cs
+++ b/src/System.Private.CoreLib/src/Internal/IntrinsicSupport/ComparerHelpers.cs
@@ -175,7 +175,7 @@ namespace System.Collections.Generic
}
// Equals method for the comparer itself.
- public sealed override bool Equals(Object obj) => obj != null && GetType() == obj.GetType();
+ public sealed override bool Equals(object obj) => obj != null && GetType() == obj.GetType();
public sealed override int GetHashCode() => GetType().GetHashCode();
}
@@ -201,7 +201,7 @@ namespace System.Collections.Generic
}
// Equals method for the comparer itself.
- public sealed override bool Equals(Object obj) => obj != null && GetType() == obj.GetType();
+ public sealed override bool Equals(object obj) => obj != null && GetType() == obj.GetType();
public sealed override int GetHashCode() => GetType().GetHashCode();
}
@@ -216,7 +216,7 @@ namespace System.Collections.Generic
}
// Equals method for the comparer itself.
- public sealed override bool Equals(Object obj) => obj != null && GetType() == obj.GetType();
+ public sealed override bool Equals(object obj) => obj != null && GetType() == obj.GetType();
public sealed override int GetHashCode() => GetType().GetHashCode();
}
diff --git a/src/System.Private.CoreLib/src/Internal/IntrinsicSupport/EqualityComparerHelpers.cs b/src/System.Private.CoreLib/src/Internal/IntrinsicSupport/EqualityComparerHelpers.cs
index 73ed2b25d..b9c735ca1 100644
--- a/src/System.Private.CoreLib/src/Internal/IntrinsicSupport/EqualityComparerHelpers.cs
+++ b/src/System.Private.CoreLib/src/Internal/IntrinsicSupport/EqualityComparerHelpers.cs
@@ -195,10 +195,15 @@ namespace Internal.IntrinsicSupport
#endif
}
+ private static bool StructOnlyNormalEquals<T>(T left, T right)
+ {
+ return left.Equals(right);
+ }
+
[Intrinsic]
internal static bool StructOnlyEquals<T>(T left, T right)
{
- return left.Equals(right);
+ return EqualityComparer<T>.Default.Equals(left, right);
}
}
}
@@ -239,7 +244,7 @@ namespace System.Collections.Generic
}
// Equals method for the comparer itself.
- public sealed override bool Equals(Object obj) => obj is GenericEqualityComparer<T>;
+ public sealed override bool Equals(object obj) => obj is GenericEqualityComparer<T>;
public sealed override int GetHashCode() => typeof(GenericEqualityComparer<T>).GetHashCode();
}
@@ -270,7 +275,7 @@ namespace System.Collections.Generic
// Equals method for the comparer itself.
- public sealed override bool Equals(Object obj) => obj is NullableEqualityComparer<T>;
+ public sealed override bool Equals(object obj) => obj is NullableEqualityComparer<T>;
public sealed override int GetHashCode() => typeof(NullableEqualityComparer<T>).GetHashCode();
}
@@ -303,7 +308,7 @@ namespace System.Collections.Generic
}
// Equals method for the comparer itself.
- public override bool Equals(Object obj) => obj is EnumEqualityComparer<T>;
+ public override bool Equals(object obj) => obj is EnumEqualityComparer<T>;
public override int GetHashCode() => typeof(EnumEqualityComparer<T>).GetHashCode();
}
@@ -335,7 +340,7 @@ namespace System.Collections.Generic
}
// Equals method for the comparer itself.
- public sealed override bool Equals(Object obj)
+ public sealed override bool Equals(object obj)
{
if(obj == null)
{
diff --git a/src/System.Private.CoreLib/src/Internal/Reflection/ExplicitScopeAttribute.cs b/src/System.Private.CoreLib/src/Internal/Reflection/ExplicitScopeAttribute.cs
index fc309169b..ef0aa6597 100644
--- a/src/System.Private.CoreLib/src/Internal/Reflection/ExplicitScopeAttribute.cs
+++ b/src/System.Private.CoreLib/src/Internal/Reflection/ExplicitScopeAttribute.cs
@@ -21,7 +21,7 @@ namespace Internal.Reflection
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Struct | AttributeTargets.Delegate, Inherited = false)]
public sealed class ExplicitScopeAttribute : Attribute
{
- public ExplicitScopeAttribute(String assemblyIdentity)
+ public ExplicitScopeAttribute(string assemblyIdentity)
{
}
}
diff --git a/src/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeInstantiator.cs b/src/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeInstantiator.cs
index 260166e55..c19686db2 100644
--- a/src/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeInstantiator.cs
+++ b/src/System.Private.CoreLib/src/Internal/Reflection/Extensions/NonPortable/CustomAttributeInstantiator.cs
@@ -48,7 +48,7 @@ namespace Internal.Reflection.Extensions.NonPortable
{
Type parameterType = parameters[i].ParameterType;
if (!(parameterType.Equals(constructorArguments[i].ArgumentType) ||
- parameterType.Equals(typeof(Object))))
+ parameterType.Equals(typeof(object))))
break;
}
if (i == parameters.Length)
@@ -65,7 +65,7 @@ namespace Internal.Reflection.Extensions.NonPortable
// Found the right constructor. Instantiate the Attribute.
//
int arity = matchingParameters.Length;
- Object[] invokeArguments = new Object[arity];
+ object[] invokeArguments = new object[arity];
for (int i = 0; i < arity; i++)
{
invokeArguments[i] = constructorArguments[i].Convert();
@@ -77,9 +77,9 @@ namespace Internal.Reflection.Extensions.NonPortable
//
foreach (CustomAttributeNamedArgument namedArgument in cad.NamedArguments)
{
- Object argumentValue = namedArgument.TypedValue.Convert();
+ object argumentValue = namedArgument.TypedValue.Convert();
Type walk = attributeType;
- String name = namedArgument.MemberName;
+ string name = namedArgument.MemberName;
if (namedArgument.IsField)
{
// Field
@@ -122,13 +122,13 @@ namespace Internal.Reflection.Extensions.NonPortable
//
// Convert the argument value reported by Reflection into an actual object.
//
- private static Object Convert(this CustomAttributeTypedArgument typedArgument)
+ private static object Convert(this CustomAttributeTypedArgument typedArgument)
{
Type argumentType = typedArgument.ArgumentType;
if (!argumentType.IsArray)
{
bool isEnum = argumentType.IsEnum;
- Object argumentValue = typedArgument.Value;
+ object argumentValue = typedArgument.Value;
if (isEnum)
argumentValue = Enum.ToObject(argumentType, argumentValue);
return argumentValue;
@@ -142,7 +142,7 @@ namespace Internal.Reflection.Extensions.NonPortable
Array array = Array.CreateInstance(elementType, typedElements.Count);
for (int i = 0; i < typedElements.Count; i++)
{
- Object elementValue = typedElements[i].Convert();
+ object elementValue = typedElements[i].Convert();
array.SetValue(elementValue, i);
}
return array;
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.Unix.cs b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.Unix.cs
index 6d28d393b..76ead8cb7 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.Unix.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.Unix.cs
@@ -27,10 +27,55 @@ namespace Internal.Runtime.Augments
public static IEnumerable<KeyValuePair<string,string>> EnumerateEnvironmentVariables()
{
- if ("".Length != 0)
- throw new NotImplementedException(); // Need to return something better than an empty environment block.
+ IntPtr block = Interop.Sys.GetEnviron();
+ if (block == IntPtr.Zero)
+ yield break;
- return Array.Empty<KeyValuePair<string,string>>();
+ // Per man page, environment variables come back as an array of pointers to strings
+ // Parse each pointer of strings individually
+ while (ParseEntry(block, out string key, out string value))
+ {
+ if (key != null && value != null)
+ yield return new KeyValuePair<string, string>(key, value);
+
+ // Increment to next environment variable entry
+ block += IntPtr.Size;
+ }
+
+ // Use a local, unsafe function since we cannot use `yield return` inside of an `unsafe` block
+ unsafe bool ParseEntry(IntPtr current, out string key, out string value)
+ {
+ // Setup
+ key = null;
+ value = null;
+
+ // Point to current entry
+ byte* entry = *(byte**)current;
+
+ // Per man page, "The last pointer in this array has the value NULL"
+ // Therefore, if entry is null then we're at the end and can bail
+ if (entry == null)
+ return false;
+
+ // Parse each byte of the entry until we hit either the separator '=' or '\0'.
+ // This finds the split point for creating key/value strings below.
+ // On some old OS, the environment block can be corrupted.
+ // Some will not have '=', so we need to check for '\0'.
+ byte* splitpoint = entry;
+ while (*splitpoint != '=' && *splitpoint != '\0')
+ splitpoint++;
+
+ // Skip over entries starting with '=' and entries with no value (just a null-terminating char '\0')
+ if (splitpoint == entry || *splitpoint == '\0')
+ return true;
+
+ // The key is the bytes from start (0) until our splitpoint
+ key = new string((sbyte*)entry, 0, checked((int)(splitpoint - entry)));
+ // The value is the rest of the bytes starting after the splitpoint
+ value = new string((sbyte*)(splitpoint + 1));
+
+ return true;
+ }
}
private static void ExitRaw()
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/ReflectionExecutionDomainCallbacks.cs b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/ReflectionExecutionDomainCallbacks.cs
index c37c0d064..bf19ab608 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/ReflectionExecutionDomainCallbacks.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/ReflectionExecutionDomainCallbacks.cs
@@ -47,7 +47,7 @@ namespace Internal.Runtime.Augments
// Flotsam and jetsam.
public abstract Exception CreateMissingMetadataException(Type typeWithMissingMetadata);
- public abstract String GetBetterDiagnosticInfoIfAvailable(RuntimeTypeHandle runtimeTypeHandle);
+ public abstract string GetBetterDiagnosticInfoIfAvailable(RuntimeTypeHandle runtimeTypeHandle);
public abstract MethodBase GetMethodBaseFromStartAddressIfAvailable(IntPtr methodStartAddress);
public abstract int ValueTypeGetHashCodeUsingReflection(object valueType);
public abstract bool ValueTypeEqualsUsingReflection(object left, object right);
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs
index 0213e8821..23c22a965 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs
@@ -87,11 +87,11 @@ namespace Internal.Runtime.Augments
//
// In these cases, this helper returns "null" and ConstructorInfo.Invoke() must deal with these specially.
//
- public static Object NewObject(RuntimeTypeHandle typeHandle)
+ public static object NewObject(RuntimeTypeHandle typeHandle)
{
EETypePtr eeType = typeHandle.ToEETypePtr();
if (eeType.IsNullable
- || eeType == EETypePtr.EETypePtrOf<String>()
+ || eeType == EETypePtr.EETypePtrOf<string>()
)
return null;
return RuntimeImports.RhNewObject(eeType);
@@ -102,7 +102,7 @@ namespace Internal.Runtime.Augments
// Unlike the NewObject API, this is the raw version that does not special case any EEType, and should be used with
// caution for very specific scenarios.
//
- public static Object RawNewObject(RuntimeTypeHandle typeHandle)
+ public static object RawNewObject(RuntimeTypeHandle typeHandle)
{
return RuntimeImports.RhNewObject(typeHandle.ToEETypePtr());
}
@@ -192,7 +192,7 @@ namespace Internal.Runtime.Augments
//
// Helper to create a delegate on a runtime-supplied type.
//
- public static Delegate CreateDelegate(RuntimeTypeHandle typeHandleForDelegate, IntPtr ldftnResult, Object thisObject, bool isStatic, bool isOpen)
+ public static Delegate CreateDelegate(RuntimeTypeHandle typeHandleForDelegate, IntPtr ldftnResult, object thisObject, bool isStatic, bool isOpen)
{
return Delegate.CreateDelegate(typeHandleForDelegate.ToEETypePtr(), ldftnResult, thisObject, isStatic: isStatic, isOpen: isOpen);
}
@@ -248,7 +248,7 @@ namespace Internal.Runtime.Augments
return new IntPtr(RuntimeImports.RhGetThreadStaticFieldAddress(typeHandle.ToEETypePtr(), threadStaticsBlockOffset, fieldOffset));
}
- public static unsafe void StoreValueTypeField(IntPtr address, Object fieldValue, RuntimeTypeHandle fieldType)
+ public static unsafe void StoreValueTypeField(IntPtr address, object fieldValue, RuntimeTypeHandle fieldType)
{
RuntimeImports.RhUnbox(fieldValue, *(void**)&address, fieldType.ToEETypePtr());
}
@@ -258,7 +258,7 @@ namespace Internal.Runtime.Augments
return ref obj.GetRawData();
}
- public static unsafe Object LoadValueTypeField(IntPtr address, RuntimeTypeHandle fieldType)
+ public static unsafe object LoadValueTypeField(IntPtr address, RuntimeTypeHandle fieldType)
{
return RuntimeImports.RhBox(fieldType.ToEETypePtr(), *(void**)&address);
}
@@ -268,12 +268,12 @@ namespace Internal.Runtime.Augments
return Pointer.Box(*(void**)address, Type.GetTypeFromHandle(fieldType));
}
- public static unsafe void StoreValueTypeField(ref byte address, Object fieldValue, RuntimeTypeHandle fieldType)
+ public static unsafe void StoreValueTypeField(ref byte address, object fieldValue, RuntimeTypeHandle fieldType)
{
RuntimeImports.RhUnbox(fieldValue, ref address, fieldType.ToEETypePtr());
}
- public static unsafe void StoreValueTypeField(Object obj, int fieldOffset, Object fieldValue, RuntimeTypeHandle fieldType)
+ public static unsafe void StoreValueTypeField(object obj, int fieldOffset, object fieldValue, RuntimeTypeHandle fieldType)
{
fixed (IntPtr* pObj = &obj.m_pEEType)
{
@@ -283,7 +283,7 @@ namespace Internal.Runtime.Augments
}
}
- public static unsafe Object LoadValueTypeField(Object obj, int fieldOffset, RuntimeTypeHandle fieldType)
+ public static unsafe object LoadValueTypeField(object obj, int fieldOffset, RuntimeTypeHandle fieldType)
{
fixed (IntPtr* pObj = &obj.m_pEEType)
{
@@ -293,7 +293,7 @@ namespace Internal.Runtime.Augments
}
}
- public static unsafe Object LoadPointerTypeField(Object obj, int fieldOffset, RuntimeTypeHandle fieldType)
+ public static unsafe object LoadPointerTypeField(object obj, int fieldOffset, RuntimeTypeHandle fieldType)
{
fixed (IntPtr* pObj = &obj.m_pEEType)
{
@@ -303,17 +303,17 @@ namespace Internal.Runtime.Augments
}
}
- public static unsafe void StoreReferenceTypeField(IntPtr address, Object fieldValue)
+ public static unsafe void StoreReferenceTypeField(IntPtr address, object fieldValue)
{
- Volatile.Write<Object>(ref Unsafe.As<IntPtr, Object>(ref *(IntPtr*)address), fieldValue);
+ Volatile.Write<Object>(ref Unsafe.As<IntPtr, object>(ref *(IntPtr*)address), fieldValue);
}
- public static unsafe Object LoadReferenceTypeField(IntPtr address)
+ public static unsafe object LoadReferenceTypeField(IntPtr address)
{
- return Volatile.Read<Object>(ref Unsafe.As<IntPtr, Object>(ref *(IntPtr*)address));
+ return Volatile.Read<Object>(ref Unsafe.As<IntPtr, object>(ref *(IntPtr*)address));
}
- public static unsafe void StoreReferenceTypeField(Object obj, int fieldOffset, Object fieldValue)
+ public static unsafe void StoreReferenceTypeField(object obj, int fieldOffset, object fieldValue)
{
fixed (IntPtr* pObj = &obj.m_pEEType)
{
@@ -323,7 +323,7 @@ namespace Internal.Runtime.Augments
}
}
- public static unsafe Object LoadReferenceTypeField(Object obj, int fieldOffset)
+ public static unsafe object LoadReferenceTypeField(object obj, int fieldOffset)
{
fixed (IntPtr* pObj = &obj.m_pEEType)
{
@@ -473,7 +473,7 @@ namespace Internal.Runtime.Augments
// Note that this is not versionable as it is exposed as a const (and needs to be a const so we can used as a custom attribute argument - which
// is the other reason this string is not versionable.)
//
- public const String HiddenScopeAssemblyName = "HiddenScope, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
+ public const string HiddenScopeAssemblyName = "HiddenScope, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
//
// This implements the "IsAssignableFrom()" api for runtime-created types. By policy, we let the underlying runtime decide assignability.
@@ -716,7 +716,7 @@ namespace Internal.Runtime.Augments
return true;
}
- public static Object CheckArgument(Object srcObject, RuntimeTypeHandle dstType, BinderBundle binderBundle)
+ public static object CheckArgument(object srcObject, RuntimeTypeHandle dstType, BinderBundle binderBundle)
{
return InvokeUtils.CheckArgument(srcObject, dstType, binderBundle);
}
@@ -728,7 +728,7 @@ namespace Internal.Runtime.Augments
return InvokeUtils.CheckArgument(srcObject, dstType.ToEETypePtr(), InvokeUtils.CheckArgumentSemantics.SetFieldDirect, binderBundle: null);
}
- public static bool IsAssignable(Object srcObject, RuntimeTypeHandle dstType)
+ public static bool IsAssignable(object srcObject, RuntimeTypeHandle dstType)
{
EETypePtr srcEEType = srcObject.EETypePtr;
return RuntimeImports.AreTypesAssignable(srcEEType, dstType.ToEETypePtr());
@@ -751,9 +751,9 @@ namespace Internal.Runtime.Augments
//
// Useful helper for finding .pdb's. (This design is admittedly tied to the single-module design of Project N.)
//
- public static String TryGetFullPathToMainApplication()
+ public static string TryGetFullPathToMainApplication()
{
- Func<String> delegateToAnythingInsideMergedApp = TryGetFullPathToMainApplication;
+ Func<string> delegateToAnythingInsideMergedApp = TryGetFullPathToMainApplication;
IntPtr ipToAnywhereInsideMergedApp = delegateToAnythingInsideMergedApp.GetFunctionPointer(out RuntimeTypeHandle _, out bool _, out bool _);
IntPtr moduleBase = RuntimeImports.RhGetOSModuleFromPointer(ipToAnywhereInsideMergedApp);
return TryGetFullPathToApplicationModule(moduleBase);
@@ -763,7 +763,7 @@ namespace Internal.Runtime.Augments
/// Locate the file path for a given native application module.
/// </summary>
/// <param name="moduleBase">Module base address</param>
- public static unsafe String TryGetFullPathToApplicationModule(IntPtr moduleBase)
+ public static unsafe string TryGetFullPathToApplicationModule(IntPtr moduleBase)
{
#if PLATFORM_UNIX
byte* pModuleNameUtf8;
@@ -772,7 +772,7 @@ namespace Internal.Runtime.Augments
#else // PLATFORM_UNIX
char* pModuleName;
int numChars = RuntimeImports.RhGetModuleFileName(moduleBase, out pModuleName);
- String modulePath = new String(pModuleName, 0, numChars);
+ string modulePath = new string(pModuleName, 0, numChars);
#endif // PLATFORM_UNIX
return modulePath;
}
@@ -1111,7 +1111,7 @@ namespace Internal.Runtime.Augments
return RuntimeImports.RhBoxAny((void*)pData, new EETypePtr(pEEType));
}
- public static IntPtr RhHandleAlloc(Object value, GCHandleType type)
+ public static IntPtr RhHandleAlloc(object value, GCHandleType type)
{
return RuntimeImports.RhHandleAlloc(value, type);
}
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.Unix.cs b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.Unix.cs
index 7b9d380e7..bc3a042eb 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.Unix.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.Unix.cs
@@ -144,6 +144,14 @@ namespace Internal.Runtime.Augments
return IntPtr.Zero;
}
+ private void InitializeComOnNewThread()
+ {
+ }
+
+ internal static void InitializeCom()
+ {
+ }
+
public void Interrupt() => WaitSubsystem.Interrupt(this);
internal static void UninterruptibleSleep0() => WaitSubsystem.UninterruptibleSleep0();
private static void SleepInternal(int millisecondsTimeout) => WaitSubsystem.Sleep(millisecondsTimeout);
@@ -159,5 +167,17 @@ namespace Internal.Runtime.Augments
{
throw new PlatformNotSupportedException();
}
+
+ private static int ComputeCurrentProcessorId()
+ {
+ int processorId = Interop.Sys.SchedGetCpu();
+
+ // sched_getcpu doesn't exist on all platforms. On those it doesn't exist on, the shim
+ // returns -1. As a fallback in that case and to spread the threads across the buckets
+ // by default, we use the current managed thread ID as a proxy.
+ if (processorId < 0) processorId = Environment.CurrentManagedThreadId;
+
+ return processorId;
+ }
}
}
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.Windows.cs b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.Windows.cs
index 6d0e937dc..e9fe5485b 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.Windows.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.Windows.cs
@@ -21,8 +21,13 @@ namespace Internal.Runtime.Augments
[ThreadStatic]
private static ApartmentType t_apartmentType;
+ [ThreadStatic]
+ private static bool t_comInitializedByUs;
+
private SafeWaitHandle _osHandle;
+ private ApartmentState _initialAppartmentState = ApartmentState.Unknown;
+
/// <summary>
/// Used by <see cref="WaitHandle"/>'s multi-wait functions
/// </summary>
@@ -99,7 +104,7 @@ namespace Internal.Runtime.Augments
// Throw an ApplicationException for compatibility with CoreCLR. First save the error code.
int errorCode = Marshal.GetLastWin32Error();
var ex = new ApplicationException();
- ex.SetErrorCode(errorCode);
+ ex.HResult = errorCode;
throw ex;
}
@@ -283,10 +288,103 @@ namespace Internal.Runtime.Augments
return 0;
}
- public ApartmentState GetApartmentState() { throw null; }
- public bool TrySetApartmentState(ApartmentState state) { throw null; }
- public void DisableComObjectEagerCleanup() { throw null; }
- public void Interrupt() { throw null; }
+ public ApartmentState GetApartmentState()
+ {
+ if (this != CurrentThread)
+ {
+ if (HasStarted())
+ throw new ThreadStateException();
+ return _initialAppartmentState;
+ }
+
+ switch (GetCurrentApartmentType())
+ {
+ case ApartmentType.STA:
+ return ApartmentState.STA;
+ case ApartmentType.MTA:
+ return ApartmentState.MTA;
+ default:
+ return ApartmentState.Unknown;
+ }
+ }
+
+ public bool TrySetApartmentState(ApartmentState state)
+ {
+ if (this != CurrentThread)
+ {
+ using (LockHolder.Hold(_lock))
+ {
+ if (HasStarted())
+ throw new ThreadStateException();
+ _initialAppartmentState = state;
+ return true;
+ }
+ }
+
+ if (state != ApartmentState.Unknown)
+ {
+ InitializeCom(state);
+ }
+ else
+ {
+ UninitializeCom();
+ }
+
+ // Clear the cache and check whether new state matches the desired state
+ t_apartmentType = ApartmentType.Unknown;
+ return state == GetApartmentState();
+ }
+
+ private void InitializeComOnNewThread()
+ {
+ InitializeCom(_initialAppartmentState);
+ }
+
+ internal static void InitializeCom(ApartmentState state = ApartmentState.MTA)
+ {
+ if (t_comInitializedByUs)
+ return;
+
+#if ENABLE_WINRT
+ int hr = Interop.WinRT.RoInitialize(
+ (state == ApartmentState.STA) ? Interop.WinRT.RO_INIT_SINGLETHREADED
+ : Interop.WinRT.RO_INIT_MULTITHREADED);
+#else
+ int hr = Interop.Ole32.CoInitializeEx(IntPtr.Zero,
+ (state == ApartmentState.STA) ? Interop.Ole32.COINIT_APARTMENTTHREADED
+ : Interop.Ole32.COINIT_MULTITHREADED);
+#endif
+ // RPC_E_CHANGED_MODE indicates this thread has been already initialized with a different
+ // concurrency model. We stay away and let whoever else initialized the COM to be in control.
+ if (hr == HResults.RPC_E_CHANGED_MODE)
+ return;
+ if (hr < 0)
+ throw new OutOfMemoryException();
+
+ t_comInitializedByUs = true;
+
+ // If the thread has already been CoInitialized to the proper mode, then
+ // we don't want to leave an outstanding CoInit so we CoUninit.
+ if (hr > 0)
+ UninitializeCom();
+ }
+
+ private static void UninitializeCom()
+ {
+ if (!t_comInitializedByUs)
+ return;
+
+#if ENABLE_WINRT
+ Interop.WinRT.RoUninitialize();
+#else
+ Interop.Ole32.CoUninitialize();
+#endif
+ t_comInitializedByUs = false;
+ }
+
+ // TODO: https://github.com/dotnet/corefx/issues/20766
+ public void DisableComObjectEagerCleanup() { }
+ public void Interrupt() { throw new PlatformNotSupportedException(); }
internal static void UninterruptibleSleep0()
{
@@ -324,40 +422,40 @@ namespace Internal.Runtime.Augments
if (currentThreadType != ApartmentType.Unknown)
return currentThreadType;
- Interop._APTTYPE aptType;
- Interop._APTTYPEQUALIFIER aptTypeQualifier;
- int result = Interop.mincore.CoGetApartmentType(out aptType, out aptTypeQualifier);
+ Interop.APTTYPE aptType;
+ Interop.APTTYPEQUALIFIER aptTypeQualifier;
+ int result = Interop.Ole32.CoGetApartmentType(out aptType, out aptTypeQualifier);
ApartmentType type = ApartmentType.Unknown;
- switch ((Interop.Constants)result)
+ switch (result)
{
- case Interop.Constants.CoENotInitialized:
+ case HResults.CO_E_NOTINITIALIZED:
type = ApartmentType.None;
break;
- case Interop.Constants.SOk:
+ case HResults.S_OK:
switch (aptType)
{
- case Interop._APTTYPE.APTTYPE_STA:
- case Interop._APTTYPE.APTTYPE_MAINSTA:
+ case Interop.APTTYPE.APTTYPE_STA:
+ case Interop.APTTYPE.APTTYPE_MAINSTA:
type = ApartmentType.STA;
break;
- case Interop._APTTYPE.APTTYPE_MTA:
+ case Interop.APTTYPE.APTTYPE_MTA:
type = ApartmentType.MTA;
break;
- case Interop._APTTYPE.APTTYPE_NA:
+ case Interop.APTTYPE.APTTYPE_NA:
switch (aptTypeQualifier)
{
- case Interop._APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_MTA:
- case Interop._APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_IMPLICIT_MTA:
+ case Interop.APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_MTA:
+ case Interop.APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_IMPLICIT_MTA:
type = ApartmentType.MTA;
break;
- case Interop._APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_STA:
- case Interop._APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_MAINSTA:
+ case Interop.APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_STA:
+ case Interop.APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_MAINSTA:
type = ApartmentType.STA;
break;
@@ -386,5 +484,7 @@ namespace Internal.Runtime.Augments
STA,
MTA
}
+
+ private static int ComputeCurrentProcessorId() => (int)Interop.mincore.GetCurrentProcessorNumber();
}
}
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.cs b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.cs
index b21d9ced8..b3e9a14fe 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.cs
@@ -7,6 +7,7 @@ using System;
using System.Diagnostics;
using System.Globalization;
using System.Runtime;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
@@ -79,6 +80,14 @@ namespace Internal.Runtime.Augments
}
}
+ internal static ulong CurrentOSThreadId
+ {
+ get
+ {
+ return RuntimeImports.RhCurrentOSThreadId();
+ }
+ }
+
// Slow path executed once per thread
private static RuntimeThread InitializeExistingThread(bool threadPoolThread)
{
@@ -103,7 +112,7 @@ namespace Internal.Runtime.Augments
if (threadPoolThread)
{
- RoInitialize();
+ InitializeCom();
}
return currentThread;
@@ -142,16 +151,6 @@ namespace Internal.Runtime.Augments
}
/// <summary>
- /// Ensures the Windows Runtime is initialized on the current thread.
- /// </summary>
- internal static void RoInitialize()
- {
-#if ENABLE_WINRT
- Interop.WinRT.RoInitialize();
-#endif
- }
-
- /// <summary>
/// Returns true if the underlying OS thread has been created and started execution of managed code.
/// </summary>
private bool HasStarted()
@@ -370,6 +369,7 @@ namespace Internal.Runtime.Augments
return JoinInternal(millisecondsTimeout);
}
+ [MethodImpl(MethodImplOptions.NoInlining)] // Slow path method. Make sure that the caller frame does not pay for PInvoke overhead.
public static void Sleep(int millisecondsTimeout) => SleepInternal(VerifyTimeoutMilliseconds(millisecondsTimeout));
/// <summary>
@@ -381,6 +381,8 @@ namespace Internal.Runtime.Augments
internal static readonly int OptimalMaxSpinWaitsPerSpinIteration = 64;
public static void SpinWait(int iterations) => RuntimeImports.RhSpinWait(iterations);
+
+ [MethodImpl(MethodImplOptions.NoInlining)] // Slow path method. Make sure that the caller frame does not pay for PInvoke overhead.
public static bool Yield() => RuntimeImports.RhYield();
public void Start() => StartInternal(null);
@@ -455,7 +457,7 @@ namespace Internal.Runtime.Augments
{
t_currentThread = thread;
System.Threading.ManagedThreadId.SetForCurrentThread(thread._managedThreadId);
- RoInitialize();
+ thread.InitializeComOnNewThread();
}
catch (OutOfMemoryException)
{
@@ -491,5 +493,42 @@ namespace Internal.Runtime.Augments
thread.SetThreadStateBit(ThreadState.Stopped);
}
}
+
+ // The upper bits of t_currentProcessorIdCache are the currentProcessorId. The lower bits of
+ // the t_currentProcessorIdCache are counting down to get it periodically refreshed.
+ // TODO: Consider flushing the currentProcessorIdCache on Wait operations or similar
+ // actions that are likely to result in changing the executing core
+ [ThreadStatic]
+ private static int t_currentProcessorIdCache;
+
+ private const int ProcessorIdCacheShift = 16;
+ private const int ProcessorIdCacheCountDownMask = (1 << ProcessorIdCacheShift) - 1;
+ private const int ProcessorIdRefreshRate = 5000;
+
+ private static int RefreshCurrentProcessorId()
+ {
+ int currentProcessorId = ComputeCurrentProcessorId();
+
+ // Add offset to make it clear that it is not guaranteed to be 0-based processor number
+ currentProcessorId += 100;
+
+ Debug.Assert(ProcessorIdRefreshRate <= ProcessorIdCacheCountDownMask);
+
+ // Mask with int.MaxValue to ensure the execution Id is not negative
+ t_currentProcessorIdCache = ((currentProcessorId << ProcessorIdCacheShift) & int.MaxValue) + ProcessorIdRefreshRate;
+
+ return currentProcessorId;
+ }
+
+ // Cached processor id used as a hint for which per-core stack to access. It is periodically
+ // refreshed to trail the actual thread core affinity.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int GetCurrentProcessorId()
+ {
+ int currentProcessorIdCache = t_currentProcessorIdCache--;
+ if ((currentProcessorIdCache & ProcessorIdCacheCountDownMask) == 0)
+ return RefreshCurrentProcessorId();
+ return (currentProcessorIdCache >> ProcessorIdCacheShift);
+ }
}
}
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs b/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs
index ad79c2510..dc598bbb7 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs
@@ -3,10 +3,11 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Text;
-using System.Runtime.InteropServices;
using System.Diagnostics;
-using Interlocked = System.Threading.Interlocked;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
namespace Internal.Runtime.CompilerHelpers
{
@@ -15,7 +16,7 @@ namespace Internal.Runtime.CompilerHelpers
/// </summary>
internal static class InteropHelpers
{
- internal static unsafe byte* StringToAnsiString(String str, bool bestFit, bool throwOnUnmappableChar)
+ internal static unsafe byte* StringToAnsiString(string str, bool bestFit, bool throwOnUnmappableChar)
{
return PInvokeMarshal.StringToAnsiString(str, bestFit, throwOnUnmappableChar);
}
@@ -37,7 +38,7 @@ namespace Internal.Runtime.CompilerHelpers
return PInvokeMarshal.ByValAnsiStringToString(buffer, length);
}
- internal static unsafe void StringToUnicodeFixedArray(String str, UInt16* buffer, int length)
+ internal static unsafe void StringToUnicodeFixedArray(string str, ushort* buffer, int length)
{
if (buffer == null)
return;
@@ -58,16 +59,16 @@ namespace Internal.Runtime.CompilerHelpers
}
}
- internal static unsafe string UnicodeToStringFixedArray(UInt16* buffer, int length)
+ internal static unsafe string UnicodeToStringFixedArray(ushort* buffer, int length)
{
if (buffer == null)
- return String.Empty;
+ return string.Empty;
- string result = String.Empty;
+ string result = string.Empty;
if (length > 0)
{
- result = new String(' ', length);
+ result = new string(' ', length);
fixed (char* pTemp = result)
{
@@ -78,7 +79,7 @@ namespace Internal.Runtime.CompilerHelpers
return result;
}
- internal static unsafe char* StringToUnicodeBuffer(String str)
+ internal static unsafe char* StringToUnicodeBuffer(string str)
{
if (str == null)
return null;
@@ -98,7 +99,7 @@ namespace Internal.Runtime.CompilerHelpers
public static unsafe string UnicodeBufferToString(char* buffer)
{
- return new String(buffer);
+ return new string(buffer);
}
public static unsafe byte* AllocMemoryForAnsiStringBuilder(StringBuilder sb)
@@ -208,6 +209,7 @@ namespace Internal.Runtime.CompilerHelpers
return ResolvePInvokeSlow(pCell);
}
+ [MethodImpl(MethodImplOptions.NoInlining)]
internal static unsafe IntPtr ResolvePInvokeSlow(MethodFixupCell* pCell)
{
ModuleFixupCell* pModuleCell = pCell->Module;
@@ -304,8 +306,8 @@ namespace Internal.Runtime.CompilerHelpers
{
byte* methodName = (byte*)pCell->MethodName;
-#if !PLATFORM_UNIX
- pCell->Target = Interop.mincore.GetProcAddress(hModule, methodName);
+#if PLATFORM_WINDOWS
+ pCell->Target = GetProcAddress(hModule, methodName, pCell->CharSetMangling);
#else
pCell->Target = Interop.Sys.GetProcAddress(hModule, methodName);
#endif
@@ -316,6 +318,44 @@ namespace Internal.Runtime.CompilerHelpers
}
}
+#if PLATFORM_WINDOWS
+ private static unsafe IntPtr GetProcAddress(IntPtr hModule, byte* methodName, CharSet charSetMangling)
+ {
+ // First look for the unmangled name. If it is unicode function, we are going
+ // to need to check for the 'W' API because it takes precedence over the
+ // unmangled one (on NT some APIs have unmangled ANSI exports).
+
+ var exactMatch = Interop.mincore.GetProcAddress(hModule, methodName);
+
+ if ((charSetMangling == CharSet.Ansi && exactMatch != IntPtr.Zero) || charSetMangling == 0)
+ {
+ return exactMatch;
+ }
+
+ int nameLength = strlen(methodName);
+
+ // We need to add an extra byte for the suffix, and an extra byte for the null terminator
+ byte* probedMethodName = stackalloc byte[nameLength + 2];
+
+ for (int i = 0; i < nameLength; i++)
+ {
+ probedMethodName[i] = methodName[i];
+ }
+
+ probedMethodName[nameLength + 1] = 0;
+
+ probedMethodName[nameLength] = (charSetMangling == CharSet.Ansi) ? (byte)'A' : (byte)'W';
+
+ IntPtr probedMethod = Interop.mincore.GetProcAddress(hModule, probedMethodName);
+ if (probedMethod != IntPtr.Zero)
+ {
+ return probedMethod;
+ }
+
+ return exactMatch;
+ }
+#endif
+
internal static unsafe int strlen(byte* pString)
{
byte* p = pString;
@@ -379,6 +419,7 @@ namespace Internal.Runtime.CompilerHelpers
public IntPtr Target;
public IntPtr MethodName;
public ModuleFixupCell* Module;
+ public CharSet CharSetMangling;
}
}
}
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs b/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs
index c31521d80..6947cc9f3 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs
@@ -24,64 +24,64 @@ namespace Internal.Runtime.CompilerHelpers
// Helper to multiply two 32-bit uints
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static UInt64 Mul32x32To64(UInt32 a, UInt32 b)
+ private static ulong Mul32x32To64(uint a, uint b)
{
- return a * (UInt64)b;
+ return a * (ulong)b;
}
// Helper to get high 32-bit of 64-bit int
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static UInt32 Hi32Bits(Int64 a)
+ private static uint Hi32Bits(long a)
{
- return (UInt32)(a >> 32);
+ return (uint)(a >> 32);
}
// Helper to get high 32-bit of 64-bit int
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static UInt32 Hi32Bits(UInt64 a)
+ private static uint Hi32Bits(ulong a)
{
- return (UInt32)(a >> 32);
+ return (uint)(a >> 32);
}
[RuntimeExport("LMulOvf")]
- public static Int64 LMulOvf(Int64 i, Int64 j)
+ public static long LMulOvf(long i, long j)
{
- Int64 ret;
+ long ret;
// Remember the sign of the result
- Int32 sign = (Int32)(Hi32Bits(i) ^ Hi32Bits(j));
+ int sign = (int)(Hi32Bits(i) ^ Hi32Bits(j));
// Convert to unsigned multiplication
if (i < 0) i = -i;
if (j < 0) j = -j;
// Get the upper 32 bits of the numbers
- UInt32 val1High = Hi32Bits(i);
- UInt32 val2High = Hi32Bits(j);
+ uint val1High = Hi32Bits(i);
+ uint val2High = Hi32Bits(j);
- UInt64 valMid;
+ ulong valMid;
if (val1High == 0)
{
// Compute the 'middle' bits of the long multiplication
- valMid = Mul32x32To64(val2High, (UInt32)i);
+ valMid = Mul32x32To64(val2High, (uint)i);
}
else
{
if (val2High != 0)
goto ThrowExcep;
// Compute the 'middle' bits of the long multiplication
- valMid = Mul32x32To64(val1High, (UInt32)j);
+ valMid = Mul32x32To64(val1High, (uint)j);
}
// See if any bits after bit 32 are set
if (Hi32Bits(valMid) != 0)
goto ThrowExcep;
- ret = (Int64)(Mul32x32To64((UInt32)i, (UInt32)j) + (valMid << 32));
+ ret = (long)(Mul32x32To64((uint)i, (uint)j) + (valMid << 32));
// check for overflow
- if (Hi32Bits(ret) < (UInt32)valMid)
+ if (Hi32Bits(ret) < (uint)valMid)
goto ThrowExcep;
if (sign >= 0)
@@ -104,39 +104,39 @@ namespace Internal.Runtime.CompilerHelpers
}
[RuntimeExport("ULMulOvf")]
- public static UInt64 ULMulOvf(UInt64 i, UInt64 j)
+ public static ulong ULMulOvf(ulong i, ulong j)
{
- UInt64 ret;
+ ulong ret;
// Get the upper 32 bits of the numbers
- UInt32 val1High = Hi32Bits(i);
- UInt32 val2High = Hi32Bits(j);
+ uint val1High = Hi32Bits(i);
+ uint val2High = Hi32Bits(j);
- UInt64 valMid;
+ ulong valMid;
if (val1High == 0)
{
if (val2High == 0)
- return Mul32x32To64((UInt32)i, (UInt32)j);
+ return Mul32x32To64((uint)i, (uint)j);
// Compute the 'middle' bits of the long multiplication
- valMid = Mul32x32To64(val2High, (UInt32)i);
+ valMid = Mul32x32To64(val2High, (uint)i);
}
else
{
if (val2High != 0)
goto ThrowExcep;
// Compute the 'middle' bits of the long multiplication
- valMid = Mul32x32To64(val1High, (UInt32)j);
+ valMid = Mul32x32To64(val1High, (uint)j);
}
// See if any bits after bit 32 are set
if (Hi32Bits(valMid) != 0)
goto ThrowExcep;
- ret = Mul32x32To64((UInt32)i, (UInt32)j) + (valMid << 32);
+ ret = Mul32x32To64((uint)i, (uint)j) + (valMid << 32);
// check for overflow
- if (Hi32Bits(ret) < (UInt32)valMid)
+ if (Hi32Bits(ret) < (uint)valMid)
goto ThrowExcep;
return ret;
@@ -212,7 +212,7 @@ namespace Internal.Runtime.CompilerHelpers
// Note that this expression also works properly for val = NaN case
// We need to compare with the very next double to two63. 0x402 is epsilon to get us there.
if (val > -two63 - 0x402 && val < two63)
- return ((Int64)val);
+ return ((long)val);
return ThrowIntOvf();
}
@@ -222,13 +222,13 @@ namespace Internal.Runtime.CompilerHelpers
[RuntimeImport(RuntimeLibrary, "RhpIDiv")]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern Int32 RhpIDiv(Int32 i, Int32 j);
+ private static extern int RhpIDiv(int i, int j);
- public static int IDiv(Int32 i, Int32 j)
+ public static int IDiv(int i, int j)
{
if (j == 0)
return ThrowIntDivByZero();
- else if (j == -1 && i == Int32.MinValue)
+ else if (j == -1 && i == int.MinValue)
return ThrowIntArithExc();
else
return RhpIDiv(i, j);
@@ -236,9 +236,9 @@ namespace Internal.Runtime.CompilerHelpers
[RuntimeImport(RuntimeLibrary, "RhpUDiv")]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern UInt32 RhpUDiv(UInt32 i, UInt32 j);
+ private static extern uint RhpUDiv(uint i, uint j);
- public static long UDiv(UInt32 i, UInt32 j)
+ public static long UDiv(uint i, uint j)
{
if (j == 0)
return ThrowUIntDivByZero();
@@ -248,9 +248,9 @@ namespace Internal.Runtime.CompilerHelpers
[RuntimeImport(RuntimeLibrary, "RhpULDiv")]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern UInt64 RhpULDiv(UInt64 i, UInt64 j);
+ private static extern ulong RhpULDiv(ulong i, ulong j);
- public static ulong ULDiv(UInt64 i, UInt64 j)
+ public static ulong ULDiv(ulong i, ulong j)
{
if (j == 0)
return ThrowULngDivByZero();
@@ -260,13 +260,13 @@ namespace Internal.Runtime.CompilerHelpers
[RuntimeImport(RuntimeLibrary, "RhpLDiv")]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern Int64 RhpLDiv(Int64 i, Int64 j);
+ private static extern long RhpLDiv(long i, long j);
- public static long LDiv(Int64 i, Int64 j)
+ public static long LDiv(long i, long j)
{
if (j == 0)
return ThrowLngDivByZero();
- else if (j == -1 && i == Int64.MinValue)
+ else if (j == -1 && i == long.MinValue)
return ThrowLngArithExc();
else
return RhpLDiv(i, j);
@@ -274,9 +274,9 @@ namespace Internal.Runtime.CompilerHelpers
[RuntimeImport(RuntimeLibrary, "RhpIMod")]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern Int32 RhpIMod(Int32 i, Int32 j);
+ private static extern int RhpIMod(int i, int j);
- public static int IMod(Int32 i, Int32 j)
+ public static int IMod(int i, int j)
{
if (j == 0)
return ThrowIntDivByZero();
@@ -286,9 +286,9 @@ namespace Internal.Runtime.CompilerHelpers
[RuntimeImport(RuntimeLibrary, "RhpUMod")]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern UInt32 RhpUMod(UInt32 i, UInt32 j);
+ private static extern uint RhpUMod(uint i, uint j);
- public static long UMod(UInt32 i, UInt32 j)
+ public static long UMod(uint i, uint j)
{
if (j == 0)
return ThrowUIntDivByZero();
@@ -298,9 +298,9 @@ namespace Internal.Runtime.CompilerHelpers
[RuntimeImport(RuntimeLibrary, "RhpULMod")]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern UInt64 RhpULMod(UInt64 i, UInt64 j);
+ private static extern ulong RhpULMod(ulong i, ulong j);
- public static ulong ULMod(UInt64 i, UInt64 j)
+ public static ulong ULMod(ulong i, ulong j)
{
if (j == 0)
return ThrowULngDivByZero();
@@ -310,9 +310,9 @@ namespace Internal.Runtime.CompilerHelpers
[RuntimeImport(RuntimeLibrary, "RhpLMod")]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern Int64 RhpLMod(Int64 i, Int64 j);
+ private static extern long RhpLMod(long i, long j);
- public static long LMod(Int64 i, Int64 j)
+ public static long LMod(long i, long j)
{
if (j == 0)
return ThrowLngDivByZero();
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/SynchronizedMethodHelpers.cs b/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/SynchronizedMethodHelpers.cs
index 30694aead..018c8005c 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/SynchronizedMethodHelpers.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/SynchronizedMethodHelpers.cs
@@ -54,7 +54,7 @@ namespace Internal.Runtime.CompilerHelpers
lockTaken = false;
}
- private static Object GetStaticLockObject(IntPtr pEEType)
+ private static object GetStaticLockObject(IntPtr pEEType)
{
return Internal.Reflection.Core.NonPortable.RuntimeTypeUnifier.GetRuntimeTypeForEEType(new System.EETypePtr(pEEType));
}
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RelocatedTypeAttribute.cs b/src/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RelocatedTypeAttribute.cs
index a848f5a94..74363b72b 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RelocatedTypeAttribute.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RelocatedTypeAttribute.cs
@@ -19,7 +19,7 @@ namespace Internal.Runtime.CompilerServices
/// </summary>
/// <param name="originalAssemblySimpleName">Simple name of the CoreFX assembly the type was relocated from.
/// For example, System.Collections (with no version or public key token)</param>
- public RelocatedTypeAttribute(String originalAssemblySimpleName)
+ public RelocatedTypeAttribute(string originalAssemblySimpleName)
{
}
}
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/ThreadStatics.cs b/src/System.Private.CoreLib/src/Internal/Runtime/ThreadStatics.cs
index db6977ee5..be6537858 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/ThreadStatics.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/ThreadStatics.cs
@@ -4,6 +4,7 @@
using System;
using System.Runtime;
+using System.Runtime.CompilerServices;
using Internal.Runtime.CompilerHelpers;
namespace Internal.Runtime
@@ -18,21 +19,29 @@ namespace Internal.Runtime
/// This method is called from a ReadyToRun helper to get base address of thread
/// static storage for the given type.
/// </summary>
- internal static unsafe object GetThreadStaticBaseForType(TypeManagerSlot* pModuleData, Int32 typeTlsIndex)
+ internal static unsafe object GetThreadStaticBaseForType(TypeManagerSlot* pModuleData, int typeTlsIndex)
{
// Get the array that holds thread static memory blocks for each type in the given module
- Int32 moduleIndex = pModuleData->ModuleIndex;
- object[] storage = (object[])RuntimeImports.RhGetThreadStaticStorageForModule(moduleIndex);
+ object[] storage = RuntimeImports.RhGetThreadStaticStorageForModule(pModuleData->ModuleIndex);
// Check whether thread static storage has already been allocated for this module and type.
- if ((storage != null) && (typeTlsIndex < storage.Length) && (storage[typeTlsIndex] != null))
+ if ((storage != null) && ((uint)typeTlsIndex < (uint)storage.Length) && (storage[typeTlsIndex] != null))
{
return storage[typeTlsIndex];
}
+ return GetThreadStaticBaseForTypeSlow(pModuleData, typeTlsIndex);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ internal static unsafe object GetThreadStaticBaseForTypeSlow(TypeManagerSlot* pModuleData, int typeTlsIndex)
+ {
+ // Get the array that holds thread static memory blocks for each type in the given module
+ object[] storage = RuntimeImports.RhGetThreadStaticStorageForModule(pModuleData->ModuleIndex);
+
// This the first access to the thread statics of the type corresponding to typeTlsIndex.
// Make sure there is enough storage allocated to hold it.
- storage = EnsureThreadStaticStorage(moduleIndex, storage, requiredSize: typeTlsIndex + 1);
+ storage = EnsureThreadStaticStorage(pModuleData->ModuleIndex, storage, requiredSize: typeTlsIndex + 1);
// Allocate an object that will represent a memory block for all thread static fields of the type
object threadStaticBase = AllocateThreadStaticStorageForType(pModuleData->TypeManager, typeTlsIndex);
@@ -45,7 +54,7 @@ namespace Internal.Runtime
/// if it is required, this method extends thread static storage of the given module
/// to the specified size and then registers the memory with the runtime.
/// </summary>
- private static object[] EnsureThreadStaticStorage(Int32 moduleIndex, object[] existingStorage, Int32 requiredSize)
+ private static object[] EnsureThreadStaticStorage(int moduleIndex, object[] existingStorage, int requiredSize)
{
if ((existingStorage != null) && (requiredSize < existingStorage.Length))
{
@@ -73,9 +82,9 @@ namespace Internal.Runtime
/// This method allocates an object that represents a memory block for all thread static fields of the type
/// that corresponds to the specified TLS index.
/// </summary>
- private static unsafe object AllocateThreadStaticStorageForType(TypeManagerHandle typeManager, Int32 typeTlsIndex)
+ private static unsafe object AllocateThreadStaticStorageForType(TypeManagerHandle typeManager, int typeTlsIndex)
{
- Int32 length;
+ int length;
IntPtr* threadStaticRegion;
// Get a pointer to the beginning of the module's Thread Static section. Then get a pointer
diff --git a/src/System.Private.CoreLib/src/Internal/Threading/Tasks/AsyncCausalitySupport.cs b/src/System.Private.CoreLib/src/Internal/Threading/Tasks/AsyncCausalitySupport.cs
index f9cd9d037..ef427a3ca 100644
--- a/src/System.Private.CoreLib/src/Internal/Threading/Tasks/AsyncCausalitySupport.cs
+++ b/src/System.Private.CoreLib/src/Internal/Threading/Tasks/AsyncCausalitySupport.cs
@@ -42,7 +42,7 @@ namespace Internal.Threading.Tasks
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void TraceOperationCreation(Task task, String operationName)
+ public static void TraceOperationCreation(Task task, string operationName)
{
DebuggerSupport.TraceOperationCreation(CausalityTraceLevel.Required, task, operationName, 0);
}
diff --git a/src/System.Private.CoreLib/src/Interop/Interop.WinRT.cs b/src/System.Private.CoreLib/src/Interop/Interop.WinRT.cs
index 741ce4f21..0823dcffc 100644
--- a/src/System.Private.CoreLib/src/Interop/Interop.WinRT.cs
+++ b/src/System.Private.CoreLib/src/Interop/Interop.WinRT.cs
@@ -11,26 +11,13 @@ internal partial class Interop
{
private const string CORE_WINRT = "api-ms-win-core-winrt-l1-1-0.dll";
- private const int RPC_E_CHANGED_MODE = unchecked((int)0x80010106);
+ internal const uint RO_INIT_SINGLETHREADED = 0;
+ internal const uint RO_INIT_MULTITHREADED = 1;
- private enum RO_INIT_TYPE : uint
- {
- RO_INIT_MULTITHREADED = 1
- }
-
- internal static void RoInitialize()
- {
- int hr = RoInitialize((uint)RO_INIT_TYPE.RO_INIT_MULTITHREADED);
-
- // RPC_E_CHANGED_MODE indicates this thread has been already initialized with a different
- // concurrency model. That is fine; we just need to skip the RoUninitialize call on shutdown.
- if ((hr < 0) && (hr != RPC_E_CHANGED_MODE))
- {
- throw new OutOfMemoryException();
- }
- }
+ [DllImport(CORE_WINRT, ExactSpelling = true)]
+ internal static extern int RoInitialize(uint initType);
[DllImport(CORE_WINRT, ExactSpelling = true)]
- private static extern int RoInitialize(uint initType);
+ internal static extern int RoUninitialize();
}
}
diff --git a/src/System.Private.CoreLib/src/Interop/Interop.manual.cs b/src/System.Private.CoreLib/src/Interop/Interop.manual.cs
index c1785e5d3..b54b15522 100644
--- a/src/System.Private.CoreLib/src/Interop/Interop.manual.cs
+++ b/src/System.Private.CoreLib/src/Interop/Interop.manual.cs
@@ -10,51 +10,18 @@ internal partial class Interop
internal enum Constants : uint
{
WaitObject0 = 0x0u,
- SOk = 0x0u,
FailFastGenerateExceptionAddress = 0x1u,
ExceptionNonContinuable = 0x1u,
- CreateMutexInitialOwner = 0x1u,
- CreateEventManualReset = 0x1u,
- MutexModifyState = 0x1u,
- CreateEventInitialSet = 0x2u,
- SemaphoreModifyState = 0x2u,
- EventModifyState = 0x2u,
DuplicateSameAccess = 0x2u,
- FileTypeChar = 0x2u,
CreateSuspended = 0x4u,
WaitAbandoned0 = 0x80u,
WaitTimeout = 0x102u,
StackSizeParamIsAReservation = 0x10000u,
- Synchronize = 0x100000u,
- MaximumAllowed = 0x02000000u,
- EFail = 0x80004005u,
- CoENotInitialized = 0x800401F0u,
WaitFailed = 0xFFFFFFFFu,
}
- // MCG doesn't currently support constants that are not uint.
internal static IntPtr InvalidHandleValue => new IntPtr(-1);
- internal enum _APTTYPE : uint
- {
- APTTYPE_STA = 0x0u,
- APTTYPE_MTA = 0x1u,
- APTTYPE_NA = 0x2u,
- APTTYPE_MAINSTA = 0x3u,
- APTTYPE_CURRENT = 0xFFFFFFFFu,
- }
-
- internal enum _APTTYPEQUALIFIER : uint
- {
- APTTYPEQUALIFIER_NONE = 0x0u,
- APTTYPEQUALIFIER_IMPLICIT_MTA = 0x1u,
- APTTYPEQUALIFIER_NA_ON_MTA = 0x2u,
- APTTYPEQUALIFIER_NA_ON_STA = 0x3u,
- APTTYPEQUALIFIER_NA_ON_IMPLICIT_MTA = 0x4u,
- APTTYPEQUALIFIER_NA_ON_MAINSTA = 0x5u,
- APTTYPEQUALIFIER_APPLICATION_STA = 0x6u,
- }
-
#pragma warning disable 649
internal unsafe struct _EXCEPTION_RECORD
{
@@ -73,9 +40,6 @@ internal partial class Interop
internal partial class mincore
{
- [DllImport("api-ms-win-core-com-l1-1-0.dll")]
- internal extern static int CoGetApartmentType(out _APTTYPE pAptType, out _APTTYPEQUALIFIER pAptQualifier);
-
[DllImport("api-ms-win-core-debug-l1-1-0.dll", EntryPoint = "IsDebuggerPresent", CharSet = CharSet.Unicode)]
internal extern static bool IsDebuggerPresent();
diff --git a/src/System.Private.CoreLib/src/MembersMustExist.AnalyzerData b/src/System.Private.CoreLib/src/MembersMustExist.AnalyzerData
index 840e4bba1..c2c9ba98f 100644
--- a/src/System.Private.CoreLib/src/MembersMustExist.AnalyzerData
+++ b/src/System.Private.CoreLib/src/MembersMustExist.AnalyzerData
@@ -215,8 +215,7 @@ public string System.IntPtr.ToString(string format)
private static System.Text.StringBuilder System.Text.StringBuilderCache.t_cachedInstance
private int string._stringLength
private char string._firstChar
-private void* System.IntPtr._value
-private static volatile System.Collections.Generic.ArraySortHelper<TKey, TValue> System.Collections.Generic.ArraySortHelper<TKey, TValue>.s_defaultArraySortHelper
+private readonly void* System.IntPtr._value
private static volatile System.Globalization.CultureInfo System.Globalization.CultureInfo.s_DefaultThreadCurrentCulture
private static volatile System.Globalization.CultureInfo System.Globalization.CultureInfo.s_DefaultThreadCurrentUICulture
private static readonly System.Globalization.CultureInfo System.Globalization.CultureInfo.s_InvariantCultureInfo
diff --git a/src/System.Private.CoreLib/src/Microsoft/Win32/Registry.cs b/src/System.Private.CoreLib/src/Microsoft/Win32/Registry.cs
deleted file mode 100644
index 4afd135ac..000000000
--- a/src/System.Private.CoreLib/src/Microsoft/Win32/Registry.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-
-using System;
-
-namespace Microsoft.Win32
-{
- /**
- * Registry encapsulation. Contains members representing all top level system
- * keys.
- *
- * @security(checkClassLinking=on)
- */
- //This class contains only static members and does not need to be serializable.
- internal static class Registry
- {
- /**
- * Current User Key.
- *
- * This key should be used as the root for all user specific settings.
- */
- public static readonly RegistryKey CurrentUser = RegistryKey.GetBaseKey(RegistryKey.HKEY_CURRENT_USER);
-
- /**
- * Local Machine Key.
- *
- * This key should be used as the root for all machine specific settings.
- */
- public static readonly RegistryKey LocalMachine = RegistryKey.GetBaseKey(RegistryKey.HKEY_LOCAL_MACHINE);
- }
-}
-
diff --git a/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryKey.Windows.cs b/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryKey.Windows.cs
index 6b0cc8962..b9221327e 100644
--- a/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryKey.Windows.cs
+++ b/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryKey.Windows.cs
@@ -4,6 +4,7 @@
using Microsoft.Win32.SafeHandles;
using System;
+using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@@ -75,14 +76,14 @@ namespace Microsoft.Win32
// the dispose below and usage elsewhere (other threads). This is By Design.
// This is less of an issue when OS > NT5 (i.e Vista & higher), we can close the perfkey
// (to release & refresh PERFLIB resources) and the OS will rebuild PERFLIB as necessary.
- Interop.mincore.RegCloseKey(HKEY_PERFORMANCE_DATA);
+ Interop.Advapi32.RegCloseKey(HKEY_PERFORMANCE_DATA);
}
private void FlushCore()
{
if (_hkey != null && IsDirty())
{
- Interop.mincore.RegFlushKey(_hkey);
+ Interop.Advapi32.RegFlushKey(_hkey);
}
}
@@ -93,7 +94,7 @@ namespace Microsoft.Win32
// By default, the new key will be writable.
SafeRegistryHandle result = null;
- int ret = Interop.mincore.RegCreateKeyEx(_hkey,
+ int ret = Interop.Advapi32.RegCreateKeyEx(_hkey,
subkey,
0,
null,
@@ -185,7 +186,7 @@ namespace Microsoft.Win32
private RegistryKey InternalOpenSubKeyCore(string name, RegistryRights rights, bool throwOnPermissionFailure)
{
SafeRegistryHandle result = null;
- int ret = Interop.mincore.RegOpenKeyEx(_hkey, name, 0, ((int)rights | (int)_regView), out result);
+ int ret = Interop.Advapi32.RegOpenKeyEx(_hkey, name, 0, ((int)rights | (int)_regView), out result);
if (ret == 0 && !result.IsInvalid)
{
RegistryKey key = new RegistryKey(result, IsWritable((int)rights), false, _remoteKey, false, _regView);
@@ -242,7 +243,7 @@ namespace Microsoft.Win32
// open the base key so that RegistryKey.Handle will return a valid handle
SafeRegistryHandle result;
- ret = Interop.mincore.RegOpenKeyEx(baseKey,
+ ret = Interop.Advapi32.RegOpenKeyEx(baseKey,
null,
0,
(int)GetRegistryKeyRights(IsWritable()) | (int)_regView,
@@ -264,7 +265,7 @@ namespace Microsoft.Win32
{
int subkeys = 0;
int junk = 0;
- int ret = Interop.mincore.RegQueryInfoKey(_hkey,
+ int ret = Interop.Advapi32.RegQueryInfoKey(_hkey,
null,
null,
IntPtr.Zero,
@@ -285,43 +286,52 @@ namespace Microsoft.Win32
return subkeys;
}
- private unsafe string[] InternalGetSubKeyNamesCore(int subkeys)
+ private string[] InternalGetSubKeyNamesCore(int subkeys)
{
- string[] names = new string[subkeys];
- char[] name = new char[MaxKeyLength + 1];
+ var names = new List<string>(subkeys);
+ char[] name = ArrayPool<char>.Shared.Rent(MaxKeyLength + 1);
- int namelen;
-
- fixed (char* namePtr = &name[0])
+ try
{
- for (int i = 0; i < subkeys; i++)
+ int result;
+ int nameLength = name.Length;
+
+ while ((result = Interop.Advapi32.RegEnumKeyEx(
+ _hkey,
+ names.Count,
+ name,
+ ref nameLength,
+ null,
+ null,
+ null,
+ null)) != Interop.Errors.ERROR_NO_MORE_ITEMS)
{
- namelen = name.Length; // Don't remove this. The API's doesn't work if this is not properly initialized.
- int ret = Interop.mincore.RegEnumKeyEx(_hkey,
- i,
- namePtr,
- ref namelen,
- null,
- null,
- null,
- null);
- if (ret != 0)
+ switch (result)
{
- Win32Error(ret, null);
+ case Interop.Errors.ERROR_SUCCESS:
+ names.Add(new string(name, 0, nameLength));
+ nameLength = name.Length;
+ break;
+ default:
+ // Throw the error
+ Win32Error(result, null);
+ break;
}
-
- names[i] = new string(namePtr);
}
}
+ finally
+ {
+ ArrayPool<char>.Shared.Return(name);
+ }
- return names;
+ return names.ToArray();
}
private int InternalValueCountCore()
{
int values = 0;
int junk = 0;
- int ret = Interop.mincore.RegQueryInfoKey(_hkey,
+ int ret = Interop.Advapi32.RegQueryInfoKey(_hkey,
null,
null,
IntPtr.Zero,
@@ -345,37 +355,79 @@ namespace Microsoft.Win32
/// <returns>All value names.</returns>
private unsafe string[] GetValueNamesCore(int values)
{
- string[] names = new string[values];
- char[] name = new char[MaxValueLength + 1];
- int namelen;
+ var names = new List<string>(values);
+
+ // Names in the registry aren't usually very long, although they can go to as large
+ // as 16383 characters (MaxValueLength).
+ //
+ // Every call to RegEnumValue will allocate another buffer to get the data from
+ // NtEnumerateValueKey before copying it back out to our passed in buffer. This can
+ // add up quickly- we'll try to keep the memory pressure low and grow the buffer
+ // only if needed.
+
+ char[] name = ArrayPool<char>.Shared.Rent(100);
- fixed (char* namePtr = &name[0])
+ try
{
- for (int i = 0; i < values; i++)
+ int result;
+ int nameLength = name.Length;
+
+ while ((result = Interop.Advapi32.RegEnumValue(
+ _hkey,
+ names.Count,
+ name,
+ ref nameLength,
+ IntPtr.Zero,
+ null,
+ null,
+ null)) != Interop.Errors.ERROR_NO_MORE_ITEMS)
{
- namelen = name.Length;
-
- int ret = Interop.mincore.RegEnumValue(_hkey,
- i,
- namePtr,
- ref namelen,
- IntPtr.Zero,
- null,
- null,
- null);
-
- if (ret != 0)
+ switch (result)
{
- // ignore ERROR_MORE_DATA if we're querying HKEY_PERFORMANCE_DATA
- if (!(IsPerfDataKey() && ret == Interop.Errors.ERROR_MORE_DATA))
- Win32Error(ret, null);
+ // The size is only ever reported back correctly in the case
+ // of ERROR_SUCCESS. It will almost always be changed, however.
+ case Interop.Errors.ERROR_SUCCESS:
+ names.Add(new string(name, 0, nameLength));
+ break;
+ case Interop.Errors.ERROR_MORE_DATA:
+ if (IsPerfDataKey())
+ {
+ // Enumerating the values for Perf keys always returns
+ // ERROR_MORE_DATA, but has a valid name. Buffer does need
+ // to be big enough however. 8 characters is the largest
+ // known name. The size isn't returned, but the string is
+ // null terminated.
+ fixed (char* c = &name[0])
+ {
+ names.Add(new string(c));
+ }
+ }
+ else
+ {
+ char[] oldName = name;
+ int oldLength = oldName.Length;
+ name = null;
+ ArrayPool<char>.Shared.Return(oldName);
+ name = ArrayPool<char>.Shared.Rent(checked(oldLength * 2));
+ }
+ break;
+ default:
+ // Throw the error
+ Win32Error(result, null);
+ break;
}
- names[i] = new string(namePtr);
+ // Always set the name length back to the buffer size
+ nameLength = name.Length;
}
}
+ finally
+ {
+ if (name != null)
+ ArrayPool<char>.Shared.Return(name);
+ }
- return names;
+ return names.ToArray();
}
private object InternalGetValueCore(string name, object defaultValue, bool doNotExpand)
@@ -384,7 +436,7 @@ namespace Microsoft.Win32
int type = 0;
int datasize = 0;
- int ret = Interop.mincore.RegQueryValueEx(_hkey, name, null, ref type, (byte[])null, ref datasize);
+ int ret = Interop.Advapi32.RegQueryValueEx(_hkey, name, null, ref type, (byte[])null, ref datasize);
if (ret != 0)
{
@@ -395,17 +447,17 @@ namespace Microsoft.Win32
int r;
byte[] blob = new byte[size];
- while (Interop.Errors.ERROR_MORE_DATA == (r = Interop.mincore.RegQueryValueEx(_hkey, name, null, ref type, blob, ref sizeInput)))
+ while (Interop.Errors.ERROR_MORE_DATA == (r = Interop.Advapi32.RegQueryValueEx(_hkey, name, null, ref type, blob, ref sizeInput)))
{
- if (size == Int32.MaxValue)
+ if (size == int.MaxValue)
{
- // ERROR_MORE_DATA was returned however we cannot increase the buffer size beyond Int32.MaxValue
+ // ERROR_MORE_DATA was returned however we cannot increase the buffer size beyond int.MaxValue
Win32Error(r, name);
}
- else if (size > (Int32.MaxValue / 2))
+ else if (size > (int.MaxValue / 2))
{
// at this point in the loop "size * 2" would cause an overflow
- size = Int32.MaxValue;
+ size = int.MaxValue;
}
else
{
@@ -441,47 +493,47 @@ namespace Microsoft.Win32
switch (type)
{
- case Interop.mincore.RegistryValues.REG_NONE:
- case Interop.mincore.RegistryValues.REG_DWORD_BIG_ENDIAN:
- case Interop.mincore.RegistryValues.REG_BINARY:
+ case Interop.Advapi32.RegistryValues.REG_NONE:
+ case Interop.Advapi32.RegistryValues.REG_DWORD_BIG_ENDIAN:
+ case Interop.Advapi32.RegistryValues.REG_BINARY:
{
byte[] blob = new byte[datasize];
- ret = Interop.mincore.RegQueryValueEx(_hkey, name, null, ref type, blob, ref datasize);
+ ret = Interop.Advapi32.RegQueryValueEx(_hkey, name, null, ref type, blob, ref datasize);
data = blob;
}
break;
- case Interop.mincore.RegistryValues.REG_QWORD:
+ case Interop.Advapi32.RegistryValues.REG_QWORD:
{ // also REG_QWORD_LITTLE_ENDIAN
if (datasize > 8)
{
// prevent an AV in the edge case that datasize is larger than sizeof(long)
- goto case Interop.mincore.RegistryValues.REG_BINARY;
+ goto case Interop.Advapi32.RegistryValues.REG_BINARY;
}
long blob = 0;
Debug.Assert(datasize == 8, "datasize==8");
// Here, datasize must be 8 when calling this
- ret = Interop.mincore.RegQueryValueEx(_hkey, name, null, ref type, ref blob, ref datasize);
+ ret = Interop.Advapi32.RegQueryValueEx(_hkey, name, null, ref type, ref blob, ref datasize);
data = blob;
}
break;
- case Interop.mincore.RegistryValues.REG_DWORD:
+ case Interop.Advapi32.RegistryValues.REG_DWORD:
{ // also REG_DWORD_LITTLE_ENDIAN
if (datasize > 4)
{
// prevent an AV in the edge case that datasize is larger than sizeof(int)
- goto case Interop.mincore.RegistryValues.REG_QWORD;
+ goto case Interop.Advapi32.RegistryValues.REG_QWORD;
}
int blob = 0;
Debug.Assert(datasize == 4, "datasize==4");
// Here, datasize must be four when calling this
- ret = Interop.mincore.RegQueryValueEx(_hkey, name, null, ref type, ref blob, ref datasize);
+ ret = Interop.Advapi32.RegQueryValueEx(_hkey, name, null, ref type, ref blob, ref datasize);
data = blob;
}
break;
- case Interop.mincore.RegistryValues.REG_SZ:
+ case Interop.Advapi32.RegistryValues.REG_SZ:
{
if (datasize % 2 == 1)
{
@@ -497,7 +549,7 @@ namespace Microsoft.Win32
}
char[] blob = new char[datasize / 2];
- ret = Interop.mincore.RegQueryValueEx(_hkey, name, null, ref type, blob, ref datasize);
+ ret = Interop.Advapi32.RegQueryValueEx(_hkey, name, null, ref type, blob, ref datasize);
if (blob.Length > 0 && blob[blob.Length - 1] == (char)0)
{
data = new string(blob, 0, blob.Length - 1);
@@ -511,7 +563,7 @@ namespace Microsoft.Win32
}
break;
- case Interop.mincore.RegistryValues.REG_EXPAND_SZ:
+ case Interop.Advapi32.RegistryValues.REG_EXPAND_SZ:
{
if (datasize % 2 == 1)
{
@@ -527,7 +579,7 @@ namespace Microsoft.Win32
}
char[] blob = new char[datasize / 2];
- ret = Interop.mincore.RegQueryValueEx(_hkey, name, null, ref type, blob, ref datasize);
+ ret = Interop.Advapi32.RegQueryValueEx(_hkey, name, null, ref type, blob, ref datasize);
if (blob.Length > 0 && blob[blob.Length - 1] == (char)0)
{
@@ -546,7 +598,7 @@ namespace Microsoft.Win32
}
}
break;
- case Interop.mincore.RegistryValues.REG_MULTI_SZ:
+ case Interop.Advapi32.RegistryValues.REG_MULTI_SZ:
{
if (datasize % 2 == 1)
{
@@ -562,7 +614,7 @@ namespace Microsoft.Win32
}
char[] blob = new char[datasize / 2];
- ret = Interop.mincore.RegQueryValueEx(_hkey, name, null, ref type, blob, ref datasize);
+ ret = Interop.Advapi32.RegQueryValueEx(_hkey, name, null, ref type, blob, ref datasize);
// make sure the string is null terminated before processing the data
if (blob.Length > 0 && blob[blob.Length - 1] != (char)0)
@@ -622,7 +674,7 @@ namespace Microsoft.Win32
data = strings;
}
break;
- case Interop.mincore.RegistryValues.REG_LINK:
+ case Interop.Advapi32.RegistryValues.REG_LINK:
default:
break;
}
@@ -634,14 +686,14 @@ namespace Microsoft.Win32
{
int type = 0;
int datasize = 0;
- int ret = Interop.mincore.RegQueryValueEx(_hkey, name, null, ref type, (byte[])null, ref datasize);
+ int ret = Interop.Advapi32.RegQueryValueEx(_hkey, name, null, ref type, (byte[])null, ref datasize);
if (ret != 0)
{
Win32Error(ret, null);
}
return
- type == Interop.mincore.RegistryValues.REG_NONE ? RegistryValueKind.None :
+ type == Interop.Advapi32.RegistryValues.REG_NONE ? RegistryValueKind.None :
!Enum.IsDefined(typeof(RegistryValueKind), type) ? RegistryValueKind.Unknown :
(RegistryValueKind)type;
}
@@ -719,8 +771,8 @@ namespace Microsoft.Win32
private static bool IsWritable(int rights)
{
- return (rights & (Interop.mincore.RegistryOperations.KEY_SET_VALUE |
- Interop.mincore.RegistryOperations.KEY_CREATE_SUB_KEY |
+ return (rights & (Interop.Advapi32.RegistryOperations.KEY_SET_VALUE |
+ Interop.Advapi32.RegistryOperations.KEY_CREATE_SUB_KEY |
(int)RegistryRights.Delete |
(int)RegistryRights.TakeOwnership |
(int)RegistryRights.ChangePermissions)) != 0;
diff --git a/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryKey.cs b/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryKey.cs
index 1fd407afa..ecf8376ed 100644
--- a/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryKey.cs
+++ b/src/System.Private.CoreLib/src/Microsoft/Win32/RegistryKey.cs
@@ -167,6 +167,11 @@ namespace Microsoft.Win32
DeleteValueCore(name, throwOnMissingValue);
}
+ public static RegistryKey OpenBaseKey(RegistryHive hKey)
+ {
+ return OpenBaseKey(hKey, RegistryView.Default);
+ }
+
public static RegistryKey OpenBaseKey(RegistryHive hKey, RegistryView view)
{
ValidateKeyView(view);
@@ -530,7 +535,7 @@ namespace Microsoft.Win32
// the dispose below and usage elsewhere (other threads). This is By Design.
// This is less of an issue when OS > NT5 (i.e Vista & higher), we can close the perfkey
// (to release & refresh PERFLIB resources) and the OS will rebuild PERFLIB as necessary.
- Interop.mincore.RegCloseKey(RegistryKey.HKEY_PERFORMANCE_DATA);
+ Interop.Advapi32.RegCloseKey(RegistryKey.HKEY_PERFORMANCE_DATA);
}
}
}
@@ -552,5 +557,9 @@ namespace Microsoft.Win32
key._keyName = s_hkeyNames[index];
return key;
}
+
+ // This dummy method is added to have the same implemenatation of Registry class.
+ // Its not being used anywhere.
+ public void SetValue(string name, object value, RegistryValueKind valueKind) { }
}
}
diff --git a/src/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.Unix.cs b/src/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.Unix.cs
new file mode 100644
index 000000000..35e464b67
--- /dev/null
+++ b/src/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.Unix.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Threading;
+
+namespace Microsoft.Win32.SafeHandles
+{
+ public sealed partial class SafeWaitHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ protected override bool ReleaseHandle()
+ {
+ WaitSubsystem.DeleteHandle(handle);
+ return true;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs b/src/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs
deleted file mode 100644
index 7527395fe..000000000
--- a/src/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-/*============================================================
-**
-**
-**
-** A wrapper for Win32 events (mutexes, auto reset events, and
-** manual reset events). Used by WaitHandle.
-**
-**
-===========================================================*/
-
-using System;
-using System.Security;
-using System.Runtime.InteropServices;
-using System.Runtime.CompilerServices;
-using System.Runtime.Versioning;
-using Microsoft.Win32;
-using System.Threading;
-
-namespace Microsoft.Win32.SafeHandles
-{
- public sealed class SafeWaitHandle : SafeHandleZeroOrMinusOneIsInvalid
- {
- // Called by P/Invoke marshaler
- private SafeWaitHandle() : base(true)
- {
- }
-
- public SafeWaitHandle(IntPtr existingHandle, bool ownsHandle) : base(ownsHandle)
- {
- SetHandle(existingHandle);
- }
-
- protected override bool ReleaseHandle()
- {
-#if PLATFORM_UNIX
- WaitSubsystem.DeleteHandle(handle);
-#else
- Interop.Kernel32.CloseHandle(handle);
-#endif
- return true;
- }
- }
-}
diff --git a/src/System.Private.CoreLib/src/Resources/Strings.resx b/src/System.Private.CoreLib/src/Resources/Strings.resx
index 2eedd405c..8c132237e 100644
--- a/src/System.Private.CoreLib/src/Resources/Strings.resx
+++ b/src/System.Private.CoreLib/src/Resources/Strings.resx
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
- <!--
- Microsoft ResX Schema
-
+ <!--
+ Microsoft ResX Schema
+
Version 2.0
-
- The primary goals of this format is to allow a simple XML format
- that is mostly human readable. The generation and parsing of the
- various data types are done through the TypeConverter classes
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
associated with the data types.
-
+
Example:
-
+
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
@@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
-
- There are any number of "resheader" rows that contain simple
+
+ There are any number of "resheader" rows that contain simple
name/value pairs.
-
- Each data row contains a name, and value. The row also contains a
- type or mimetype. Type corresponds to a .NET class that support
- text/value conversion through the TypeConverter architecture.
- Classes that don't support this are serialized and stored with the
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
mimetype set.
-
- The mimetype is used for serialized objects, and tells the
- ResXResourceReader how to depersist the object. This is currently not
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
-
- Note - application/x-microsoft.net.object.binary.base64 is the format
- that the ResXResourceWriter will generate, however the reader can
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
-
+
mimetype: application/x-microsoft.net.object.binary.base64
- value : The object must be serialized with
+ value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
-
+
mimetype: application/x-microsoft.net.object.soap.base64
- value : The object must be serialized with
+ value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
- value : The object must be serialized into a byte array
+ value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@@ -156,6 +156,9 @@
<data name="Arg_CannotHaveNegativeValue" xml:space="preserve">
<value>String cannot contain a minus sign if the base is not 10.</value>
</data>
+ <data name="Arg_CannotMixComparisonInfrastructure" xml:space="preserve">
+ <value>The usage of IKeyComparer and IHashCodeProvider/IComparer interfaces cannot be mixed; use one or the other.</value>
+ </data>
<data name="Arg_CopyNonBlittableArray" xml:space="preserve">
<value>Arrays must contain only blittable data in order to be copied to unmanaged memory.</value>
</data>
@@ -189,6 +192,9 @@
<data name="Arg_DuplicateWaitObjectException" xml:space="preserve">
<value>Duplicate objects in argument.</value>
</data>
+ <data name="Arg_EHClauseNotFilter" xml:space="preserve">
+ <value>This ExceptionHandlingClause is not a filter.</value>
+ </data>
<data name="Arg_EnumAndObjectMustBeSameType" xml:space="preserve">
<value>Object must be the same type as the enum. The type passed in was '{0}'; the enum type was '{1}'.</value>
</data>
@@ -420,6 +426,9 @@
<data name="Arg_RegKeyNotFound" xml:space="preserve">
<value>The specified registry key does not exist.</value>
</data>
+ <data name="Arg_RegInvalidKeyName" xml:space="preserve">
+ <value>Registry key name must start with a valid base key name.</value>
+ </data>
<data name="Arg_SecurityException" xml:space="preserve">
<value>Security error.</value>
</data>
@@ -663,6 +672,9 @@
<data name="Argument_MustBeFalse" xml:space="preserve">
<value>Argument must be initialized to false</value>
</data>
+ <data name="Argument_MustBeRuntimeType" xml:space="preserve">
+ <value>Type must be a runtime Type object.</value>
+ </data>
<data name="Argument_NoEra" xml:space="preserve">
<value>No Era was supplied.</value>
</data>
@@ -708,9 +720,6 @@
<data name="ArgumentOutOfRange_NeedNonNegNum" xml:space="preserve">
<value>Non-negative number required.</value>
</data>
- <data name="ArgumentOutOfRange_NeedNonNegNumRequired" xml:space="preserve">
- <value>Non-negative number required.</value>
- </data>
<data name="ArgumentOutOfRange_NeedValidId" xml:space="preserve">
<value>The ID parameter must be in the range {0} through {1}.</value>
</data>
@@ -780,6 +789,9 @@
<data name="ArgumentNull_ArrayValue" xml:space="preserve">
<value>Found a null value within an array.</value>
</data>
+ <data name="ArgumentNull_Dictionary" xml:space="preserve">
+ <value>Dictionary cannot be null.</value>
+ </data>
<data name="ArgumentNull_Generic" xml:space="preserve">
<value>Value cannot be null.</value>
</data>
@@ -798,9 +810,6 @@
<data name="ArgumentNull_Waithandles" xml:space="preserve">
<value>The waitHandles parameter cannot be null.</value>
</data>
- <data name="ArgumentNull_WithParamName" xml:space="preserve">
- <value>Parameter '{0}' cannot be null.</value>
- </data>
<data name="ArgumentOutOfRange_AddValue" xml:space="preserve">
<value>Value to add was out of range.</value>
</data>
@@ -876,6 +885,9 @@
<data name="ArgumentOutOfRange_GetCharCountOverflow" xml:space="preserve">
<value>Too many bytes. The resulting number of chars is larger than what can be returned as an int.</value>
</data>
+ <data name="ArgumentOutOfRange_HashtableLoadFactor" xml:space="preserve">
+ <value>Load factor needs to be between 0.1 and 1.0.</value>
+ </data>
<data name="ArgumentOutOfRange_IndexCount" xml:space="preserve">
<value>Index and count must refer to a location within the string.</value>
</data>
@@ -1122,6 +1134,9 @@
<data name="InvalidOperation_HandleIsNotInitialized" xml:space="preserve">
<value>Handle is not initialized.</value>
</data>
+ <data name="InvalidOperation_HashInsertFailed" xml:space="preserve">
+ <value>Hashtable insert failed. Load factor too high. The most common cause is multiple threads writing to the Hashtable simultaneously.</value>
+ </data>
<data name="InvalidOperation_IComparerFailed" xml:space="preserve">
<value>Failed to compare two elements in the array.</value>
</data>
@@ -1194,8 +1209,11 @@
<data name="InvalidTimeZone_InvalidFileData" xml:space="preserve">
<value>The time zone ID '{0}' was found on the local computer, but the file at '{1}' was corrupt.</value>
</data>
- <data name="InvalidTimeZone_JulianDayNotSupported" xml:space="preserve">
- <value>Julian dates in POSIX strings are unsupported.</value>
+ <data name="InvalidTimeZone_InvalidJulianDay" xml:space="preserve">
+ <value>Invalid Julian day in POSIX strings.</value>
+ </data>
+ <data name="InvalidTimeZone_NJulianDayNotSupported" xml:space="preserve">
+ <value>Julian n day in POSIX strings is not supported.</value>
</data>
<data name="InvalidTimeZone_NoTTInfoStructures" xml:space="preserve">
<value>There are no ttinfo structures in the tzfile. At least one ttinfo structure is required in order to construct a TimeZoneInfo object.</value>
@@ -1852,6 +1870,9 @@
<data name="PlatformNotSupported_OSXFileLocking" xml:space="preserve">
<value>Locking/unlocking file regions is not supported on this platform. Use FileShare on the entire file instead.</value>
</data>
+ <data name="PlatformNotSupported_ReflectionEmit" xml:space="preserve">
+ <value>Dynamic code generation is not supported on this platform.</value>
+ </data>
<data name="MissingMember_Name" xml:space="preserve">
<value>Member '{0}' not found.</value>
</data>
@@ -2302,6 +2323,9 @@
<data name="Serialization_InvalidFieldState" xml:space="preserve">
<value>Object fields may not be properly initialized.</value>
</data>
+ <data name="Serialization_InvalidOnDeser" xml:space="preserve">
+ <value>OnDeserialization method was called while the object was not being deserialized.</value>
+ </data>
<data name="Acc_CreateAbst" xml:space="preserve">
<value>Cannot create an abstract class.</value>
</data>
@@ -2368,14 +2392,20 @@
<data name="Serialization_MissingDateTimeData" xml:space="preserve">
<value>Invalid serialized DateTime data. Unable to find 'ticks' or 'dateData'.</value>
</data>
+ <data name="Serialization_MissingValues" xml:space="preserve">
+ <value>The values for this dictionary are missing.</value>
+ </data>
<data name="Serialization_DateTimeTicksOutOfRange" xml:space="preserve">
<value>Invalid serialized DateTime data. Ticks must be between DateTime.MinValue.Ticks and DateTime.MaxValue.Ticks.</value>
</data>
+ <data name="FeatureRemoved_Message" xml:space="preserve">
+ <value>Code to support feature '{0}' was removed during publishing. If this is in error, update the project configuration to not disable feature '{0}'.</value>
+ </data>
<data name="Arg_InvalidANSIString" xml:space="preserve">
<value>The ANSI string passed in could not be converted from the default ANSI code page to Unicode.</value>
</data>
- <data name="Arg_ExpectedNulTermination" xml:space="preserve">
- <value>The value passed was not NUL terminated.</value>
+ <data name="Arg_MustBeNullTerminatedString" xml:space="preserve">
+ <value>The string must be null-terminated.</value>
</data>
<data name="PlatformNotSupported_ArgIterator" xml:space="preserve">
<value>ArgIterator is not supported on this platform.</value>
@@ -2392,6 +2422,9 @@
<data name="Serialization_InvalidPtrValue" xml:space="preserve">
<value>An IntPtr or UIntPtr with an eight byte value cannot be deserialized on a machine with a four byte word size.</value>
</data>
+ <data name="Serialization_KeyValueDifferentSizes" xml:space="preserve">
+ <value>The keys and values arrays have different sizes.</value>
+ </data>
<data name="EventSource_AbstractMustNotDeclareEventMethods" xml:space="preserve">
<value>Abstract event source must not declare event methods ({0} with ID {1}).</value>
</data>
@@ -2725,4 +2758,37 @@
<data name="Arg_NullArgumentNullRef" xml:space="preserve">
<value>The method was called with a null array argument.</value>
</data>
+ <data name="Arg_InsufficientNumberOfElements" xml:space="preserve">
+ <value>At least {0} element(s) are expected in the parameter "{1}".</value>
+ </data>
+ <data name="NullReference_InvokeNullRefReturned" xml:space="preserve">
+ <value>The target method returned a null reference.</value>
+ </data>
+ <data name="InvalidOperation_ConcurrentOperationsNotSupported" xml:space="preserve">
+ <value>Operations that change non-concurrent collections must have exclusive access. A concurrent update was performed on this collection and corrupted its state. The collection's state is no longer correct.</value>
+ </data>
+ <data name="Thread_Operation_RequiresCurrentThread" xml:space="preserve">
+ <value>This operation must be performed on the same thread as that represented by the Thread instance.</value>
+ </data>
+ <data name="ConcurrentCollection_SyncRoot_NotSupported" xml:space="preserve">
+ <value>The SyncRoot property may not be used for the synchronization of concurrent collections.</value>
+ </data>
+ <data name="Arg_WrongAsyncResult" xml:space="preserve">
+ <value>IAsyncResult object did not come from the corresponding async method on this type.</value>
+ </data>
+ <data name="InvalidOperation_EndReadCalledMultiple" xml:space="preserve">
+ <value>EndRead can only be called once for each asynchronous operation.</value>
+ </data>
+ <data name="InvalidOperation_EndWriteCalledMultiple" xml:space="preserve">
+ <value>EndWrite can only be called once for each asynchronous operation.</value>
+ </data>
+ <data name="InvalidOperation_WrongAsyncResultOrEndReadCalledMultiple" xml:space="preserve">
+ <value>Either the IAsyncResult object did not come from the corresponding async method on this type, or EndRead was called multiple times with the same IAsyncResult.</value>
+ </data>
+ <data name="InvalidOperation_WrongAsyncResultOrEndWriteCalledMultiple" xml:space="preserve">
+ <value>Either the IAsyncResult object did not come from the corresponding async method on this type, or EndWrite was called multiple times with the same IAsyncResult.</value>
+ </data>
+ <data name="ArgumentOutOfRange_Week_ISO" xml:space="preserve">
+ <value>The week parameter must be in the range 1 through 53.</value>
+ </data>
</root>
diff --git a/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj
index 9f041c462..5efa4931c 100644
--- a/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj
+++ b/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj
@@ -26,7 +26,7 @@
<ExcludeMscorlibFacade>true</ExcludeMscorlibFacade>
<ExcludeAssemblyInfoPartialFile>true</ExcludeAssemblyInfoPartialFile>
<UseSyncTable>true</UseSyncTable>
- <DefineConstants>EETYPE_TYPE_MANAGER;ES_BUILD_PN;ES_SESSION_INFO;$(DefineConstants)</DefineConstants>
+ <DefineConstants>netcoreapp;EETYPE_TYPE_MANAGER;ES_BUILD_PN;ES_SESSION_INFO;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup>
<DefineConstants Condition="'$(UseSyncTable)' == 'true'">FEATURE_SYNCTABLE;$(DefineConstants)</DefineConstants>
@@ -148,8 +148,8 @@
<Compile Include="Internal\Threading\Tasks\Tracing\TaskTrace.cs" />
<Compile Include="Interop\Interop.manual.cs" />
<Compile Include="Interop\Interop.WinRT.cs" Condition="'$(EnableWinRT)' == 'true'" />
- <Compile Include="Microsoft\Win32\SafeHandles\SafeWaitHandle.cs" />
<Compile Include="System\Runtime\CompilerServices\CastableObject.cs" />
+ <Compile Include="System\Runtime\CompilerServices\FeatureRemovedException.cs" />
<Compile Include="System\Reflection\AssemblyNameHelpers.StrongName.cs" />
<Compile Include="System\Reflection\AssemblyNameHelpers.cs" />
<Compile Include="System\Reflection\AssemblyNameLexer.cs" />
@@ -162,20 +162,31 @@
<Compile Include="System\Reflection\CustomAttributeExtensions.cs" />
<Compile Include="System\Reflection\CustomAttributeNamedArgument.cs" />
<Compile Include="System\Reflection\CustomAttributeTypedArgument.cs" />
- <Compile Include="System\Reflection\ExceptionHandlingClause.cs" />
+ <Compile Include="System\Reflection\Emit\AssemblyBuilder.cs" />
+ <Compile Include="System\Reflection\Emit\ConstructorBuilder.cs" />
+ <Compile Include="System\Reflection\Emit\CustomAttributeBuilder.cs" />
+ <Compile Include="System\Reflection\Emit\DynamicMethod.cs" />
+ <Compile Include="System\Reflection\Emit\EnumBuilder.cs" />
+ <Compile Include="System\Reflection\Emit\EventBuilder.cs" />
+ <Compile Include="System\Reflection\Emit\FieldBuilder.cs" />
+ <Compile Include="System\Reflection\Emit\GenericTypeParameterBuilder.cs" />
+ <Compile Include="System\Reflection\Emit\ILGenerator.cs" />
+ <Compile Include="System\Reflection\Emit\LocalBuilder.cs" />
+ <Compile Include="System\Reflection\Emit\MethodBuilder.cs" />
+ <Compile Include="System\Reflection\Emit\ModuleBuilder.cs" />
+ <Compile Include="System\Reflection\Emit\ParameterBuilder.cs" />
+ <Compile Include="System\Reflection\Emit\PropertyBuilder.cs" />
+ <Compile Include="System\Reflection\Emit\ReflectionEmitThrower.cs" />
+ <Compile Include="System\Reflection\Emit\SignatureHelper.cs" />
+ <Compile Include="System\Reflection\Emit\TypeBuilder.cs" />
<Compile Include="System\Reflection\FieldInfo.CoreRT.cs" />
<Compile Include="System\Reflection\LegacyCustomAttributeApis.cs" />
- <Compile Include="System\Reflection\LocalVariableInfo.cs" />
<Compile Include="System\Reflection\MethodBase.CoreRT.cs" />
- <Compile Include="System\Reflection\MethodBody.cs" />
<Compile Include="System\Reflection\Runtime\CustomAttributes\RuntimeImplementedCustomAttributeData.cs" />
- <Compile Include="System\Resources\FastResourceComparer.cs" />
<Compile Include="System\Resources\FileBasedResourceGroveler.cs" />
<Compile Include="System\Resources\IResourceGroveler.cs" />
<Compile Include="System\Resources\ManifestBasedResourceGroveler.cs" />
<Compile Include="System\Resources\ResourceManager.cs" />
- <Compile Include="System\Resources\ResourceReader.cs" />
- <Compile Include="System\Resources\ResourceSet.cs" />
<Compile Include="System\Runtime\InteropServices\CriticalHandle.cs" />
<Compile Include="System\Text\CodePageDataItem.cs" />
<Compile Include="System\__Canon.cs" Condition="'$(IsProjectNLibrary)' == 'true'" />
@@ -183,16 +194,14 @@
<Compile Include="System\AppContext.cs" />
<Compile Include="System\AppContextConfigHelper.cs" />
<Compile Include="System\AppContextDefaultValues.cs" />
+ <Compile Include="System\AppContextSwitches.cs" />
<Compile Include="System\Buffer.cs" />
<Compile Include="System\ByReference.cs" />
- <Compile Include="System\Collections\Concurrent\LowLevelConcurrentQueue.cs" />
- <Compile Include="System\Collections\Generic\ArraySortHelper.cs" />
+ <Compile Include="System\Collections\Generic\ArraySortHelper.CoreRT.cs" />
<Compile Include="System\Collections\Generic\Comparer.cs" />
<Compile Include="System\Collections\Generic\CompatibilityEqualityComparers.cs" />
<Compile Include="System\Collections\Generic\EqualityComparer.cs" />
<Compile Include="System\Collections\Generic\EqualOnlyComparer.cs" />
- <Compile Include="System\CurrentSystemTimeZone.Cache.cs" />
- <Compile Include="System\Decimal.DecCalc.cs" />
<Compile Include="System\DefaultBinder.CanConvert.cs" />
<Compile Include="System\Diagnostics\Contracts\ContractsBCL.cs" />
<Compile Include="System\Globalization\CharUnicodeInfoData.cs" />
@@ -201,11 +210,9 @@
<Compile Include="System\Globalization\GlobalizationMode.Unix.cs" Condition="'$(TargetsUnix)'=='true'" />
<Compile Include="System\Guid.CoreRT.cs" />
<Compile Include="System\InvokeUtils.cs" />
- <Compile Include="System\IO\BinaryReader.cs" />
<Compile Include="System\IO\FileLoadException.CoreRT.cs" />
- <Compile Include="System\IO\Stream.cs" />
+ <Compile Include="System\IO\Stream.CoreRT.cs" />
<Compile Include="System\RuntimeMethodHandle.cs" />
- <Compile Include="System\Decimal.cs" />
<Compile Include="System\Diagnostics\Contracts\Contracts.cs" />
<Compile Include="System\Diagnostics\Debug.CoreRT.cs" />
<Compile Include="System\Diagnostics\Debug.Windows.cs" Condition="'$(TargetsWindows)'=='true'" />
@@ -213,7 +220,6 @@
<Compile Include="System\Diagnostics\LowLevelDebugFuncEval.cs" />
<Compile Include="System\Diagnostics\DebuggerGuidedStepThroughAttribute.cs" />
<Compile Include="System\Diagnostics\DebugAnnotations.cs" />
- <Compile Include="System\Diagnostics\StackFrame.cs" />
<Compile Include="System\Diagnostics\StackFrame.CoreRT.cs" />
<Compile Include="System\Diagnostics\StackFrameExtensions.cs" />
<Compile Include="System\Diagnostics\StackTrace.cs" />
@@ -223,19 +229,13 @@
<Compile Include="System\Environment.cs" />
<Compile Include="System\GC.cs" />
<Compile Include="System\Globalization\CultureInfo.cs" />
- <Compile Include="System\Guid.Windows.cs" Condition="'$(TargetsWindows)'=='true'" />
- <Compile Include="System\Guid.Unix.cs" Condition="'$(TargetsUnix)'=='true'" />
<Compile Include="System\Helpers.cs" />
- <Compile Include="System\InsufficientMemoryException.cs" />
- <Compile Include="System\Marvin.cs" />
<Compile Include="System\Math.CoreRT.cs" />
<Compile Include="System\MathF.CoreRT.cs" />
- <Compile Include="System\MissingFieldException.cs" />
- <Compile Include="System\MissingMemberException.cs" />
+ <Compile Include="System\MissingMemberException.CoreRT.cs" />
<Compile Include="System\MulticastDelegate.cs" />
<Compile Include="System\Number.CoreRT.cs" />
<Compile Include="System\Object.cs" />
- <Compile Include="System\OutOfMemoryException.cs" />
<Compile Include="System\Reflection\MissingMetadataException.cs" />
<Compile Include="System\RuntimeArgumentHandle.cs" />
<Compile Include="System\Runtime\CompilerServices\ConditionalWeakTable.cs" />
@@ -246,14 +246,12 @@
<Compile Include="System\Runtime\CompilerServices\EagerStaticClassConstructionAttribute.cs" />
<Compile Include="System\Runtime\CompilerServices\ForceDictionaryLookupsAttribute.cs" />
<Compile Include="System\Runtime\CompilerServices\ILTransformInjectedAttribute.cs" />
- <Compile Include="System\Runtime\CompilerServices\ICastable.cs" />
<Compile Include="System\Runtime\CompilerServices\InitializedDataAttributes.cs" />
<Compile Include="System\Runtime\CompilerServices\InternalCompilerAttributes.cs" />
<Compile Include="System\Runtime\CompilerServices\ReflectionBlockedAttribute.cs" />
<Compile Include="System\Runtime\CompilerServices\StaticClassConstructionContext.cs" />
<Compile Include="System\Runtime\CompilerServices\NetNativeToolsVersionAttribute.cs" />
<Compile Include="System\Runtime\CompilerServices\FakeElementAttribute.cs" />
- <Compile Include="System\Runtime\ConstrainedExecution\CriticalFinalizerObject.cs" />
<Compile Include="System\Runtime\ExceptionIDs.cs" />
<Compile Include="System\Runtime\ExceptionServices\ExceptionDispatchInfo.cs" />
<Compile Include="System\Runtime\GcSettings.cs" />
@@ -262,7 +260,6 @@
<Compile Include="System\Runtime\InteropServices\GCHandle.cs" />
<Compile Include="System\Runtime\InteropServices\GCHandleType.cs" />
<Compile Include="System\Runtime\InteropServices\InteropExtensions.cs" />
- <Compile Include="System\Runtime\InteropServices\NativeCallableAttribute.cs" />
<Compile Include="System\Runtime\InteropServices\NativeFunctionPointerWrapper.cs" />
<Compile Include="System\Runtime\InteropServices\PInvokeMarshal.cs" />
<Compile Include="System\Runtime\InteropServices\Marshal.cs" />
@@ -270,9 +267,6 @@
<Compile Include="System\Runtime\InteropServices\UnsafeGCHandle.cs" />
<Compile Include="System\Runtime\InteropServices\WindowsRuntime\EventRegistrationToken.cs" />
<Compile Include="System\Runtime\Loader\AssemblyLoadContext.cs" />
- <Compile Include="System\Runtime\Serialization\SerializationInfo.cs" />
- <Compile Include="System\String.cs" />
- <Compile Include="System\String.Comparison.cs" />
<Compile Include="System\String.CoreRT.cs" />
<Compile Include="System\String.Intern.cs" />
<Compile Include="System\Array.cs" />
@@ -289,39 +283,27 @@
<Compile Include="System\ModuleHandle.cs" />
<Compile Include="System\RuntimeFieldHandle.cs" />
<Compile Include="System\Runtime\CompilerServices\AsyncMethodBuilder.cs" />
- <Compile Include="System\Runtime\CompilerServices\TaskAwaiter.cs" />
<Compile Include="System\Text\EncodingData.cs" />
<Compile Include="System\Text\EncodingTable.cs" />
<Compile Include="System\Text\StringBuilder.CoreRT.cs" />
- <Compile Include="System\Text\StringBuilderCache.cs" />
- <Compile Include="System\Threading\CancellationToken.cs" />
<Compile Include="System\Threading\CancellationTokenRegistration.cs" />
<Compile Include="System\Threading\CancellationTokenSource.cs" />
<Compile Include="System\Threading\ManagedThreadId.cs" />
<Compile Include="System\Threading\Lock.cs" />
<Compile Include="System\Threading\Condition.cs" />
- <Compile Include="System\Threading\EventWaitHandle.cs" />
<Compile Include="System\Threading\FirstLevelSpinWaiter.cs" />
<Compile Include="System\Threading\Interlocked.cs" />
<Compile Include="System\Threading\IOCompletionCallback.cs" />
<Compile Include="System\Threading\LockHolder.cs" />
<Compile Include="System\Threading\LowLevelLock.cs" />
<Compile Include="System\Threading\LowLevelMonitor.cs" />
- <Compile Include="System\Threading\ManualResetEventSlim.cs" />
<Compile Include="System\Threading\Monitor.cs" />
- <Compile Include="System\Threading\Mutex.cs" />
- <Compile Include="System\Threading\NativeOverlapped.cs" />
<Compile Include="System\Threading\ObjectHeader.cs" Condition="'$(UseSyncTable)' == 'true'" />
<Compile Include="System\Threading\Overlapped.cs" />
- <Compile Include="System\Threading\PinnableBufferCache.cs" />
- <Compile Include="System\Threading\Semaphore.cs" />
- <Compile Include="System\Threading\SemaphoreSlim.cs" />
- <Compile Include="System\Threading\SpinLock.cs" />
<Compile Include="System\Threading\SynchronizationContext.cs" />
<Compile Include="System\Threading\SynchronizationContext.WinRT.cs" Condition="'$(EnableWinRT)' == 'true'" />
<Compile Include="System\Threading\SynchronizationContext.Dummy.cs" Condition="'$(EnableWinRT)' != 'true'" />
<Compile Include="System\Threading\SyncTable.cs" Condition="'$(UseSyncTable)' == 'true'" />
- <Compile Include="System\Threading\Tasks\ConcurrentExclusiveSchedulerPair.cs" />
<Compile Include="System\Threading\Tasks\DebuggerSupport.cs" />
<Compile Include="System\Threading\Tasks\DebuggerSupport.WinRT.cs" Condition="'$(EnableWinRT)' == 'true'" />
<Compile Include="System\Threading\Tasks\DebuggerSupport.Dummy.cs" Condition="'$(EnableWinRT)' != 'true'" />
@@ -334,8 +316,6 @@
<Compile Include="System\Threading\Tasks\TaskFactory.cs" />
<Compile Include="System\Threading\Tasks\TaskScheduler.cs" />
<Compile Include="System\Threading\Tasks\ThreadPoolTaskScheduler.cs" />
- <Compile Include="System\Threading\ThreadInterruptedException.cs" />
- <Compile Include="System\Threading\ThreadLocal.cs" />
<Compile Include="System\Threading\ThreadPool.cs" />
<Compile Include="System\Threading\ThreadPoolCallbackWrapper.cs" />
<Compile Include="System\Threading\Timer.cs" />
@@ -365,51 +345,9 @@
<Compile Include="System\WeakReferenceOfT.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetsWindows)'=='true' and '$(EnableWinRT)'!='true'">
- <Compile Include="Microsoft\Win32\SafeHandles\SafeRegistryHandle.cs" />
- <Compile Include="Microsoft\Win32\SafeHandles\SafeRegistryHandle.Windows.cs" />
- <Compile Include="Microsoft\Win32\Registry.cs" />
- <Compile Include="Microsoft\Win32\RegistryHive.cs" />
<Compile Include="Microsoft\Win32\RegistryKey.cs" />
<Compile Include="Microsoft\Win32\RegistryKey.Windows.cs" />
- <Compile Include="Microsoft\Win32\RegistryOptions.cs" />
- <Compile Include="Microsoft\Win32\RegistryValueKind.cs" />
- <Compile Include="Microsoft\Win32\RegistryValueOptions.cs" />
- <Compile Include="Microsoft\Win32\RegistryView.cs" />
<Compile Include="Microsoft\Win32\ThrowHelper.cs" />
- <Compile Include="System\Security\AccessControl\RegistryRights.cs" />
- <Compile Include="..\..\Common\src\Interop\Windows\advapi32\Interop.RegDeleteValue.cs">
- <Link>Interop\Windows\advapi32\Interop.RegDeleteValue.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\src\Interop\Windows\advapi32\Interop.RegSetValueEx.cs">
- <Link>Interop\Windows\advapi32\Interop.RegSetValueEx.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\src\Interop\Windows\mincore\Interop.RegistryOptions.cs">
- <Link>Interop\Windows\mincore\Interop.RegistryOptions.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\src\Interop\Windows\mincore\Interop.RegCloseKey.cs">
- <Link>Interop\Windows\mincore\Interop.RegCloseKey.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\src\Interop\Windows\mincore\Interop.RegCreateKeyEx.cs">
- <Link>Interop\Windows\mincore\Interop.RegCreateKeyEx.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\src\Interop\Windows\mincore\Interop.RegEnumKeyEx.cs">
- <Link>Interop\Windows\mincore\Interop.RegEnumKeyEx.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\src\Interop\Windows\mincore\Interop.RegEnumValue.cs">
- <Link>Interop\Windows\mincore\Interop.RegEnumValue.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\src\Interop\Windows\mincore\Interop.RegFlushKey.cs">
- <Link>Interop\Windows\mincore\Interop.RegFlushKey.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\src\Interop\Windows\mincore\Interop.RegOpenKeyEx.cs">
- <Link>Interop\Windows\mincore\Interop.RegOpenKeyEx.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\src\Interop\Windows\mincore\Interop.RegQueryInfoKey.cs">
- <Link>Interop\Windows\mincore\Interop.RegQueryInfoKey.cs</Link>
- </Compile>
- <Compile Include="..\..\Common\src\Interop\Windows\mincore\Interop.RegQueryValueEx.cs">
- <Link>Interop\Windows\mincore\Interop.RegQueryValueEx.cs</Link>
- </Compile>
<Compile Include="..\..\Common\src\Interop\Windows\Kernel32\Interop.ExitProcess.cs">
<Link>Interop\Windows\mincore\Interop.ExitProcess.cs</Link>
</Compile>
@@ -429,9 +367,6 @@
<Compile Include="..\..\Common\src\Interop\Windows\kernel32\Interop.Memory.cs">
<Link>Interop\Windows\kernel32\Interop.Memory.cs</Link>
</Compile>
- <Compile Include="..\..\Common\src\Interop\Windows\kernel32\Interop.MultiByteToWideChar.cs">
- <Link>Interop\Windows\kernel32\Interop.MultiByteToWideChar.cs</Link>
- </Compile>
<Compile Include="..\..\Common\src\Interop\Windows\kernel32\Interop.CompletionPort.cs">
<Link>Interop\Windows\kernel32\Interop.CompletionPort.cs</Link>
</Compile>
@@ -474,6 +409,15 @@
<Compile Include="..\..\Common\src\Interop\Windows\ole32\Interop.CoTaskMemAllocFree.cs">
<Link>Interop\Windows\ole32\Interop.CoTaskMemAllocFree.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\src\Interop\Windows\ole32\Interop.CoInitializeEx.cs">
+ <Link>Interop\Windows\ole32\Interop.CoInitializeEx.cs</Link>
+ </Compile>
+ <Compile Include="..\..\Common\src\Interop\Windows\ole32\Interop.CoUninitialize.cs">
+ <Link>Interop\Windows\ole32\Interop.CoUninitialize.cs</Link>
+ </Compile>
+ <Compile Include="..\..\Common\src\Interop\Windows\ole32\Interop.CoGetApartmentType.cs">
+ <Link>Interop\Windows\ole32\Interop.CoGetApartmentType.cs</Link>
+ </Compile>
<Compile Condition="'$(IsProjectNLibrary)' == 'true'" Include="System\Runtime\CommandLine.Windows.cs" />
<Compile Condition="'$(IsProjectNLibrary)' == 'true'" Include="..\..\Common\src\Interop\Windows\mincore\Interop.CommandLine.cs">
<Link>Interop\Windows\mincore\Interop.CommandLine.cs</Link>
@@ -503,11 +447,8 @@
<Link>Interop\Windows\mincore\Interop.DynamicLoad.cs</Link>
</Compile>
<Compile Include="System\HighPerformanceCounter.Windows.cs" />
- <Compile Include="System\Threading\EventWaitHandle.Windows.cs" />
<Compile Include="System\Threading\LowLevelMonitor.Windows.cs" />
<Compile Include="System\Threading\LowLevelLifoSemaphore.Windows.cs" />
- <Compile Include="System\Threading\Mutex.Windows.cs" />
- <Compile Include="System\Threading\Semaphore.Windows.cs" />
<Compile Include="System\Threading\ThreadPool.Windows.cs" Condition="'$(FeaturePortableThreadPool)' != 'true'" />
<Compile Include="System\Threading\WaitHandle.Windows.cs" />
<Compile Include="System\Threading\Win32ThreadPoolBoundHandle.cs" />
@@ -530,16 +471,12 @@
<Compile Condition="'$(EnableWinRT)' != 'true'" Include="..\..\Common\src\Interop\Windows\mincore\Interop.GetSystemDirectory.cs">
<Link>Interop\Windows\mincore\Interop.GetSystemDirectory.cs</Link>
</Compile>
- <Compile Include="..\..\Common\src\Interop\Windows\mincore\Interop.CoCreateGuid.cs">
- <Link>Interop\Windows\mincore\Interop.CoCreateGuid.cs</Link>
- </Compile>
<Compile Include="..\..\Common\src\Interop\Windows\mincore\Interop.QueryUnbiasedInterruptTime.cs">
<Link>Interop\Windows\mincore\Interop.QueryUnbiasedInterruptTime.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup Condition="'$(TargetsWindows)'=='true' And '$(EnableDummyGlobalizationImplementation)' != 'true'">
<Compile Include="System\Globalization\CultureInfo.Windows.cs" />
- <Compile Include="System\Globalization\CompareInfo.Windows.cs" />
</ItemGroup>
<ItemGroup Condition="'$(FeaturePortableThreadPool)' == 'true'">
<Compile Include="System\Threading\ThreadPool.Portable.cs" />
@@ -568,10 +505,10 @@
</ItemGroup>
<ItemGroup Condition="'$(TargetsUnix)' == 'true' And '$(EnableDummyGlobalizationImplementation)' != 'true'">
<Compile Include="System\Globalization\CultureInfo.Unix.cs" />
- <Compile Include="System\Globalization\CompareInfo.Unix.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetsUnix)'=='true'">
<Compile Include="Internal\Runtime\Augments\RuntimeThread.Unix.cs" />
+ <Compile Include="Microsoft\Win32\SafeHandles\SafeWaitHandle.Unix.cs" />
<Compile Include="System\AppContext.Unix.cs" />
<Compile Include="System\DateTime.Unix.CoreRT.cs" />
<Compile Include="System\Environment.Unix.cs" />
@@ -595,9 +532,6 @@
<Compile Include="..\..\Common\src\Interop\Unix\System.Native\Interop.GetSystemTimeAsTicks.cs">
<Link>Interop\Unix\System.Private.CoreLib.Native\Interop.GetSystemTimeAsTicks.cs</Link>
</Compile>
- <Compile Include="..\..\Common\src\Interop\Unix\System.Private.CoreLib.Native\Interop.CreateGuid.cs">
- <Link>Interop\Unix\System.Private.CoreLib.Native\Interop.CreateGuid.cs</Link>
- </Compile>
<Compile Include="..\..\Common\src\Interop\Unix\System.Private.CoreLib.Native\Interop.Exit.cs">
<Link>Interop\Unix\System.Private.CoreLib.Native\Interop.Exit.cs</Link>
</Compile>
@@ -637,6 +571,9 @@
<Compile Include="..\..\Common\src\Interop\Unix\System.Private.CoreLib.Native\Interop.ErrNo.cs">
<Link>Interop\Unix\System.Private.CoreLib.Native\Interop.ErrNo.cs</Link>
</Compile>
+ <Compile Include="..\..\Common\src\Interop\Unix\System.Private.CoreLib.Native\Interop.GetEnviron.cs">
+ <Link>Interop\Unix\System.Private.CoreLib.Native\Interop.GetEnviron.cs</Link>
+ </Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\Common\src\TypeSystem\Common\Utilities\LockFreeReaderHashtable.cs">
diff --git a/src/System.Private.CoreLib/src/System/Activator.cs b/src/System.Private.CoreLib/src/System/Activator.cs
index 8ecfa24b8..b098adfd5 100644
--- a/src/System.Private.CoreLib/src/System/Activator.cs
+++ b/src/System.Private.CoreLib/src/System/Activator.cs
@@ -11,6 +11,7 @@ using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
+using System.Runtime.Remoting;
using System.Runtime;
using Internal.Reflection.Augments;
@@ -147,6 +148,50 @@ namespace System
}
private const BindingFlags ConstructorDefault = BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance;
+
+ public static ObjectHandle CreateInstance(string assemblyName, string typeName)
+ {
+ throw new PlatformNotSupportedException(); // https://github.com/dotnet/corefx/issues/30845
+ }
+
+ public static ObjectHandle CreateInstance(string assemblyName,
+ string typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ object[] args,
+ CultureInfo culture,
+ object[] activationAttributes)
+ {
+ throw new PlatformNotSupportedException(); // https://github.com/dotnet/corefx/issues/30845
+ }
+
+ public static ObjectHandle CreateInstance(string assemblyName, string typeName, object[] activationAttributes)
+ {
+ throw new PlatformNotSupportedException(); // https://github.com/dotnet/corefx/issues/30845
+ }
+
+ public static ObjectHandle CreateInstanceFrom(string assemblyFile, string typeName)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ public static ObjectHandle CreateInstanceFrom(string assemblyFile,
+ string typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ object[] args,
+ CultureInfo culture,
+ object[] activationAttributes)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ public static ObjectHandle CreateInstanceFrom(string assemblyFile, string typeName, object[] activationAttributes)
+ {
+ throw new PlatformNotSupportedException();
+ }
}
}
diff --git a/src/System.Private.CoreLib/src/System/AppContext.cs b/src/System.Private.CoreLib/src/System/AppContext.cs
index 6b316a448..0858f357a 100644
--- a/src/System.Private.CoreLib/src/System/AppContext.cs
+++ b/src/System.Private.CoreLib/src/System/AppContext.cs
@@ -25,7 +25,7 @@ namespace System
UnknownValue = 0x8 // Has no default and could not find an override
}
private static readonly Dictionary<string, SwitchValueState> s_switchMap = new Dictionary<string, SwitchValueState>();
- private static Dictionary<String, Object> s_localStore = new Dictionary<String, Object>();
+ private static Dictionary<string, object> s_localStore = new Dictionary<string, object>();
private static string s_defaultBaseDirectory;
// AppDomain lives in CoreFX, but some of this class's events need to pass in AppDomains, so people registering those
// events need to first pass in an AppDomain that we stash here to pass back in the events.
diff --git a/src/System.Private.CoreLib/src/System/AppContextDefaultValues.cs b/src/System.Private.CoreLib/src/System/AppContextDefaultValues.cs
index a0093c94a..3dd5d55f5 100644
--- a/src/System.Private.CoreLib/src/System/AppContextDefaultValues.cs
+++ b/src/System.Private.CoreLib/src/System/AppContextDefaultValues.cs
@@ -32,14 +32,14 @@ namespace System
// - The identifier and version is required, profile is optional
// - Only three components are allowed.
// - The version string must be in the System.Version format; an optional "v" or "V" prefix is allowed
- private static bool TryParseFrameworkName(String frameworkName, out String identifier, out int version, out String profile)
+ private static bool TryParseFrameworkName(string frameworkName, out string identifier, out int version, out string profile)
{
// For parsing a target Framework moniker, from the FrameworkName class
const char c_componentSeparator = ',';
const char c_keyValueSeparator = '=';
const char c_versionValuePrefix = 'v';
- const String c_versionKey = "Version";
- const String c_profileKey = "Profile";
+ const string c_versionKey = "Version";
+ const string c_profileKey = "Profile";
identifier = profile = string.Empty;
version = 0;
@@ -49,7 +49,7 @@ namespace System
return false;
}
- String[] components = frameworkName.Split(c_componentSeparator);
+ string[] components = frameworkName.Split(c_componentSeparator);
version = 0;
// Identifer and Version are required, Profile is optional.
@@ -113,7 +113,7 @@ namespace System
//
else if (key.Equals(c_profileKey, StringComparison.OrdinalIgnoreCase))
{
- if (!String.IsNullOrEmpty(value))
+ if (!string.IsNullOrEmpty(value))
{
profile = value;
}
diff --git a/src/System.Private.CoreLib/src/System/AppContextSwitches.cs b/src/System.Private.CoreLib/src/System/AppContextSwitches.cs
new file mode 100644
index 000000000..f838871e8
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/AppContextSwitches.cs
@@ -0,0 +1,60 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.CompilerServices;
+
+namespace System
+{
+ internal static class AppContextSwitches
+ {
+ private static int _enforceJapaneseEraYearRanges;
+ public static bool EnforceJapaneseEraYearRanges
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ return GetCachedSwitchValue("Switch.System.Globalization.EnforceJapaneseEraYearRanges", ref _enforceJapaneseEraYearRanges);
+ }
+ }
+
+ //
+ // Implementation details
+ //
+
+ private static bool DisableCaching { get; set; }
+
+ static AppContextSwitches()
+ {
+ bool isEnabled;
+ if (AppContext.TryGetSwitch(@"TestSwitch.LocalAppContext.DisableCaching", out isEnabled))
+ {
+ DisableCaching = isEnabled;
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static bool GetCachedSwitchValue(string switchName, ref int switchValue)
+ {
+ if (switchValue < 0) return false;
+ if (switchValue > 0) return true;
+
+ return GetCachedSwitchValueInternal(switchName, ref switchValue);
+ }
+
+ private static bool GetCachedSwitchValueInternal(string switchName, ref int switchValue)
+ {
+ bool isSwitchEnabled;
+ AppContext.TryGetSwitch(switchName, out isSwitchEnabled);
+
+ if (DisableCaching)
+ {
+ return isSwitchEnabled;
+ }
+
+ switchValue = isSwitchEnabled ? 1 /*true*/ : -1 /*false*/;
+ return isSwitchEnabled;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Array.CoreRT.cs b/src/System.Private.CoreLib/src/System/Array.CoreRT.cs
index 80c4d2bbf..f4c57285a 100644
--- a/src/System.Private.CoreLib/src/System/Array.CoreRT.cs
+++ b/src/System.Private.CoreLib/src/System/Array.CoreRT.cs
@@ -445,7 +445,7 @@ namespace System
ref object refDestinationArray = ref Unsafe.As<byte, object>(ref destinationArray.GetRawArrayData());
for (int i = 0; i < length; i++)
{
- Object boxedValue = RuntimeImports.RhBox(sourceElementEEType, pElement);
+ object boxedValue = RuntimeImports.RhBox(sourceElementEEType, pElement);
Unsafe.Add(ref refDestinationArray, destinationIndex + i) = boxedValue;
pElement += sourceElementSize;
}
@@ -474,7 +474,7 @@ namespace System
for (int i = 0; i < length; i++)
{
- Object boxedValue = Unsafe.Add(ref refSourceArray, sourceIndex + i);
+ object boxedValue = Unsafe.Add(ref refSourceArray, sourceIndex + i);
if (boxedValue == null)
{
if (!isNullable)
@@ -918,7 +918,7 @@ namespace System
if (length > MaxArrayLength)
maxArrayDimensionLengthOverflow = true;
totalLength = totalLength * (ulong)length;
- if (totalLength > Int32.MaxValue)
+ if (totalLength > int.MaxValue)
throw new OutOfMemoryException(); // "Array dimensions exceeded supported range."
}
@@ -938,14 +938,14 @@ namespace System
}
// Wraps an IComparer inside an IComparer<Object>.
- private sealed class ComparerAsComparerT : IComparer<Object>
+ private sealed class ComparerAsComparerT : IComparer<object>
{
public ComparerAsComparerT(IComparer comparer)
{
_comparer = (comparer == null) ? Comparer.Default : comparer;
}
- public int Compare(Object x, Object y)
+ public int Compare(object x, object y)
{
return _comparer.Compare(x, y);
}
@@ -999,7 +999,7 @@ namespace System
return Length - 1;
}
- public unsafe Object GetValue(int index)
+ public unsafe object GetValue(int index)
{
if (!IsSzArray)
{
@@ -1018,7 +1018,7 @@ namespace System
return GetValueWithFlattenedIndex_NoErrorCheck(index);
}
- public unsafe Object GetValue(int index1, int index2)
+ public unsafe object GetValue(int index1, int index2)
{
if (Rank != 2)
throw new ArgumentException(SR.Arg_Need2DArray);
@@ -1029,7 +1029,7 @@ namespace System
return GetValue(pIndices, 2);
}
- public unsafe Object GetValue(int index1, int index2, int index3)
+ public unsafe object GetValue(int index1, int index2, int index3)
{
if (Rank != 3)
throw new ArgumentException(SR.Arg_Need3DArray);
@@ -1041,7 +1041,7 @@ namespace System
return GetValue(pIndices, 3);
}
- public unsafe Object GetValue(params int[] indices)
+ public unsafe object GetValue(params int[] indices)
{
if (indices == null)
throw new ArgumentNullException(nameof(indices));
@@ -1059,7 +1059,7 @@ namespace System
return GetValue(pIndices, length);
}
- private unsafe Object GetValue(int* pIndices, int rank)
+ private unsafe object GetValue(int* pIndices, int rank)
{
Debug.Assert(Rank == rank);
Debug.Assert(!IsSzArray);
@@ -1085,7 +1085,7 @@ namespace System
return GetValueWithFlattenedIndex_NoErrorCheck(flattenedIndex);
}
- private Object GetValueWithFlattenedIndex_NoErrorCheck(int flattenedIndex)
+ private object GetValueWithFlattenedIndex_NoErrorCheck(int flattenedIndex)
{
ref byte element = ref Unsafe.AddByteOffset(ref GetRawArrayData(), (nuint)flattenedIndex * ElementSize);
@@ -1101,7 +1101,7 @@ namespace System
}
}
- public unsafe void SetValue(Object value, int index)
+ public unsafe void SetValue(object value, int index)
{
if (!IsSzArray)
{
@@ -1146,7 +1146,7 @@ namespace System
}
}
- public unsafe void SetValue(Object value, int index1, int index2)
+ public unsafe void SetValue(object value, int index1, int index2)
{
if (Rank != 2)
throw new ArgumentException(SR.Arg_Need2DArray);
@@ -1157,7 +1157,7 @@ namespace System
SetValue(value, pIndices, 2);
}
- public unsafe void SetValue(Object value, int index1, int index2, int index3)
+ public unsafe void SetValue(object value, int index1, int index2, int index3)
{
if (Rank != 3)
throw new ArgumentException(SR.Arg_Need3DArray);
@@ -1169,7 +1169,7 @@ namespace System
SetValue(value, pIndices, 3);
}
- public unsafe void SetValue(Object value, params int[] indices)
+ public unsafe void SetValue(object value, params int[] indices)
{
if (indices == null)
throw new ArgumentNullException(nameof(indices));
@@ -1193,7 +1193,7 @@ namespace System
}
}
- private unsafe void SetValue(Object value, int* pIndices, int rank)
+ private unsafe void SetValue(object value, int* pIndices, int rank)
{
Debug.Assert(Rank == rank);
Debug.Assert(!IsSzArray);
@@ -1241,7 +1241,7 @@ namespace System
{
throw new InvalidCastException(SR.InvalidCast_StoreArrayElement);
}
- Unsafe.As<byte, Object>(ref element) = value;
+ Unsafe.As<byte, object>(ref element) = value;
}
}
@@ -1255,7 +1255,7 @@ namespace System
private sealed partial class ArrayEnumerator : IEnumerator, ICloneable
{
- public Object Current
+ public object Current
{
get
{
@@ -1332,9 +1332,9 @@ namespace System
static void SortImpl(Array keys, Array items, int index, int length, IComparer comparer)
{
- IComparer<Object> comparerT = new ComparerAsComparerT(comparer);
- Object[] objKeys = keys as Object[];
- Object[] objItems = items as Object[];
+ IComparer<object> comparerT = new ComparerAsComparerT(comparer);
+ object[] objKeys = keys as object[];
+ object[] objItems = items as object[];
// Unfortunately, on Project N, we don't have the ability to specialize ArraySortHelper<> on demand
// for value types. Rather than incur a boxing cost on every compare and every swap (and maintain a separate introsort algorithm
@@ -1343,12 +1343,12 @@ namespace System
// Check if either of the arrays need to be copied.
if (objKeys == null)
{
- objKeys = new Object[index + length];
+ objKeys = new object[index + length];
Array.CopyImplValueTypeArrayToReferenceArray(keys, index, objKeys, index, length, reliable: false);
}
if (objItems == null && items != null)
{
- objItems = new Object[index + length];
+ objItems = new object[index + length];
Array.CopyImplValueTypeArrayToReferenceArray(items, index, objItems, index, length, reliable: false);
}
diff --git a/src/System.Private.CoreLib/src/System/Array.cs b/src/System.Private.CoreLib/src/System/Array.cs
index 12412a28f..d30a072d8 100644
--- a/src/System.Private.CoreLib/src/System/Array.cs
+++ b/src/System.Private.CoreLib/src/System/Array.cs
@@ -80,7 +80,7 @@ namespace System
bool IList.IsReadOnly
{ get { return false; } }
- Object IList.this[int index]
+ object IList.this[int index]
{
get
{
@@ -93,12 +93,12 @@ namespace System
}
}
- int IList.Add(Object value)
+ int IList.Add(object value)
{
throw new NotSupportedException(SR.NotSupported_FixedSizeCollection);
}
- bool IList.Contains(Object value)
+ bool IList.Contains(object value)
{
return Array.IndexOf(this, value) >= 0;
}
@@ -108,17 +108,17 @@ namespace System
Array.Clear(this, GetLowerBound(0), this.Length);
}
- int IList.IndexOf(Object value)
+ int IList.IndexOf(object value)
{
return Array.IndexOf(this, value);
}
- void IList.Insert(int index, Object value)
+ void IList.Insert(int index, object value)
{
throw new NotSupportedException(SR.NotSupported_FixedSizeCollection);
}
- void IList.Remove(Object value)
+ void IList.Remove(object value)
{
throw new NotSupportedException(SR.NotSupported_FixedSizeCollection);
}
@@ -146,12 +146,12 @@ namespace System
// Make a new array which is a deep copy of the original array.
//
- public Object Clone()
+ public object Clone()
{
return MemberwiseClone();
}
- Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer)
+ int IStructuralComparable.CompareTo(object other, IComparer comparer)
{
if (other == null)
{
@@ -180,14 +180,14 @@ namespace System
return c;
}
- Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer)
+ bool IStructuralEquatable.Equals(object other, IEqualityComparer comparer)
{
if (other == null)
{
return false;
}
- if (Object.ReferenceEquals(this, other))
+ if (object.ReferenceEquals(this, other))
{
return true;
}
@@ -249,7 +249,7 @@ namespace System
// negative result to produce the index of the first element (if any) that
// is larger than the given search value.
//
- public static int BinarySearch(Array array, Object value)
+ public static int BinarySearch(Array array, object value)
{
if (array == null)
throw new ArgumentNullException(nameof(array));
@@ -274,7 +274,7 @@ namespace System
public static void Copy(Array sourceArray, Array destinationArray, long length)
{
- if (length > Int32.MaxValue || length < Int32.MinValue)
+ if (length > int.MaxValue || length < int.MinValue)
throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_HugeArrayNotSupported);
Array.Copy(sourceArray, destinationArray, (int)length);
@@ -282,11 +282,11 @@ namespace System
public static void Copy(Array sourceArray, long sourceIndex, Array destinationArray, long destinationIndex, long length)
{
- if (sourceIndex > Int32.MaxValue || sourceIndex < Int32.MinValue)
+ if (sourceIndex > int.MaxValue || sourceIndex < int.MinValue)
throw new ArgumentOutOfRangeException(nameof(sourceIndex), SR.ArgumentOutOfRange_HugeArrayNotSupported);
- if (destinationIndex > Int32.MaxValue || destinationIndex < Int32.MinValue)
+ if (destinationIndex > int.MaxValue || destinationIndex < int.MinValue)
throw new ArgumentOutOfRangeException(nameof(destinationIndex), SR.ArgumentOutOfRange_HugeArrayNotSupported);
- if (length > Int32.MaxValue || length < Int32.MinValue)
+ if (length > int.MaxValue || length < int.MinValue)
throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_HugeArrayNotSupported);
Array.Copy(sourceArray, (int)sourceIndex, destinationArray, (int)destinationIndex, (int)length);
@@ -294,7 +294,7 @@ namespace System
public void CopyTo(Array array, long index)
{
- if (index > Int32.MaxValue || index < Int32.MinValue)
+ if (index > int.MaxValue || index < int.MinValue)
throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_HugeArrayNotSupported);
this.CopyTo(array, (int)index);
@@ -336,37 +336,37 @@ namespace System
return GetLength(dimension);
}
- public Object GetValue(long index)
+ public object GetValue(long index)
{
- if (index > Int32.MaxValue || index < Int32.MinValue)
+ if (index > int.MaxValue || index < int.MinValue)
throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_HugeArrayNotSupported);
return this.GetValue((int)index);
}
- public Object GetValue(long index1, long index2)
+ public object GetValue(long index1, long index2)
{
- if (index1 > Int32.MaxValue || index1 < Int32.MinValue)
+ if (index1 > int.MaxValue || index1 < int.MinValue)
throw new ArgumentOutOfRangeException(nameof(index1), SR.ArgumentOutOfRange_HugeArrayNotSupported);
- if (index2 > Int32.MaxValue || index2 < Int32.MinValue)
+ if (index2 > int.MaxValue || index2 < int.MinValue)
throw new ArgumentOutOfRangeException(nameof(index2), SR.ArgumentOutOfRange_HugeArrayNotSupported);
return this.GetValue((int)index1, (int)index2);
}
- public Object GetValue(long index1, long index2, long index3)
+ public object GetValue(long index1, long index2, long index3)
{
- if (index1 > Int32.MaxValue || index1 < Int32.MinValue)
+ if (index1 > int.MaxValue || index1 < int.MinValue)
throw new ArgumentOutOfRangeException(nameof(index1), SR.ArgumentOutOfRange_HugeArrayNotSupported);
- if (index2 > Int32.MaxValue || index2 < Int32.MinValue)
+ if (index2 > int.MaxValue || index2 < int.MinValue)
throw new ArgumentOutOfRangeException(nameof(index2), SR.ArgumentOutOfRange_HugeArrayNotSupported);
- if (index3 > Int32.MaxValue || index3 < Int32.MinValue)
+ if (index3 > int.MaxValue || index3 < int.MinValue)
throw new ArgumentOutOfRangeException(nameof(index3), SR.ArgumentOutOfRange_HugeArrayNotSupported);
return this.GetValue((int)index1, (int)index2, (int)index3);
}
- public Object GetValue(params long[] indices)
+ public object GetValue(params long[] indices)
{
if (indices == null)
throw new ArgumentNullException(nameof(indices));
@@ -378,7 +378,7 @@ namespace System
for (int i = 0; i < indices.Length; ++i)
{
long index = indices[i];
- if (index > Int32.MaxValue || index < Int32.MinValue)
+ if (index > int.MaxValue || index < int.MinValue)
throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_HugeArrayNotSupported);
intIndices[i] = (int)index;
}
@@ -398,7 +398,7 @@ namespace System
// Returns an object appropriate for synchronizing access to this
// Array.
- public Object SyncRoot { get { return this; } }
+ public object SyncRoot { get { return this; } }
// Searches a section of an array for a given element using a binary search
// algorithm. Elements of the array are compared to the search value using
@@ -413,7 +413,7 @@ namespace System
// negative result to produce the index of the first element (if any) that
// is larger than the given search value.
//
- public static int BinarySearch(Array array, int index, int length, Object value)
+ public static int BinarySearch(Array array, int index, int length, object value)
{
return BinarySearch(array, index, length, value, null);
}
@@ -432,7 +432,7 @@ namespace System
// negative result to produce the index of the first element (if any) that
// is larger than the given search value.
//
- public static int BinarySearch(Array array, Object value, IComparer comparer)
+ public static int BinarySearch(Array array, object value, IComparer comparer)
{
if (array == null)
throw new ArgumentNullException(nameof(array));
@@ -454,7 +454,7 @@ namespace System
// negative result to produce the index of the first element (if any) that
// is larger than the given search value.
//
- public static int BinarySearch(Array array, int index, int length, Object value, IComparer comparer)
+ public static int BinarySearch(Array array, int index, int length, object value, IComparer comparer)
{
if (array == null)
throw new ArgumentNullException(nameof(array));
@@ -470,7 +470,7 @@ namespace System
int lo = index;
int hi = index + length - 1;
- Object[] objArray = array as Object[];
+ object[] objArray = array as object[];
if (objArray != null)
{
while (lo <= hi)
@@ -561,14 +561,14 @@ namespace System
if (array.Length - index < length)
throw new ArgumentException(SR.Argument_InvalidOffLen);
- return ArraySortHelper<T>.BinarySearch(array, index, length, value, comparer);
+ return ArraySortHelper<T>.Default.BinarySearch(array, index, length, value, comparer);
}
// Returns the index of the first occurrence of a given value in an array.
// The array is searched forwards, and the elements of the array are
// compared to the given value using the Object.Equals method.
//
- public static int IndexOf(Array array, Object value)
+ public static int IndexOf(Array array, object value)
{
if (array == null)
{
@@ -584,7 +584,7 @@ namespace System
// elements of the array are compared to the given value using the
// Object.Equals method.
//
- public static int IndexOf(Array array, Object value, int startIndex)
+ public static int IndexOf(Array array, object value, int startIndex)
{
if (array == null)
{
@@ -601,7 +601,7 @@ namespace System
// elements of the array are compared to the given value using the
// Object.Equals method.
//
- public static int IndexOf(Array array, Object value, int startIndex, int count)
+ public static int IndexOf(Array array, object value, int startIndex, int count)
{
if (array == null)
throw new ArgumentNullException(nameof(array));
@@ -613,7 +613,7 @@ namespace System
if (count < 0 || count > array.Length - startIndex + lb)
throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_Count);
- Object[] objArray = array as Object[];
+ object[] objArray = array as object[];
int endIndex = startIndex + count;
if (objArray != null)
{
@@ -628,7 +628,7 @@ namespace System
{
for (int i = startIndex; i < endIndex; i++)
{
- Object obj = objArray[i];
+ object obj = objArray[i];
if (obj != null && obj.Equals(value)) return i;
}
}
@@ -637,7 +637,7 @@ namespace System
{
for (int i = startIndex; i < endIndex; i++)
{
- Object obj = array.GetValue(i);
+ object obj = array.GetValue(i);
if (obj == null)
{
if (value == null) return i;
@@ -696,7 +696,7 @@ namespace System
return IndexOfImpl(array, value, startIndex, count);
}
- public static int LastIndexOf(Array array, Object value)
+ public static int LastIndexOf(Array array, object value)
{
if (array == null)
throw new ArgumentNullException(nameof(array));
@@ -709,7 +709,7 @@ namespace System
// startIndex and ending at index 0. The elements of the array are
// compared to the given value using the Object.Equals method.
//
- public static int LastIndexOf(Array array, Object value, int startIndex)
+ public static int LastIndexOf(Array array, object value, int startIndex)
{
if (array == null)
throw new ArgumentNullException(nameof(array));
@@ -723,7 +723,7 @@ namespace System
// the array are compared to the given value using the Object.Equals
// method.
//
- public static int LastIndexOf(Array array, Object value, int startIndex, int count)
+ public static int LastIndexOf(Array array, object value, int startIndex, int count)
{
if (array == null)
throw new ArgumentNullException(nameof(array));
@@ -742,7 +742,7 @@ namespace System
if (array.Rank != 1)
throw new RankException(SR.Rank_MultiDimNotSupported);
- Object[] objArray = array as Object[];
+ object[] objArray = array as object[];
int endIndex = startIndex - count + 1;
if (objArray != null)
{
@@ -757,7 +757,7 @@ namespace System
{
for (int i = startIndex; i >= endIndex; i--)
{
- Object obj = objArray[i];
+ object obj = objArray[i];
if (obj != null && obj.Equals(value)) return i;
}
}
@@ -766,7 +766,7 @@ namespace System
{
for (int i = startIndex; i >= endIndex; i--)
{
- Object obj = array.GetValue(i);
+ object obj = array.GetValue(i);
if (obj == null)
{
if (value == null) return i;
@@ -873,7 +873,7 @@ namespace System
if (array.Rank != 1)
throw new RankException(SR.Rank_MultiDimNotSupported);
- Object[] objArray = array as Object[];
+ object[] objArray = array as object[];
if (objArray != null)
{
Array.Reverse<object>(objArray, index, length);
@@ -884,7 +884,7 @@ namespace System
int j = index + length - 1;
while (i < j)
{
- Object temp = array.GetValue(i);
+ object temp = array.GetValue(i);
array.SetValue(array.GetValue(j), i);
array.SetValue(temp, j);
i++;
@@ -910,6 +910,10 @@ namespace System
if (array.Length - index < length)
throw new ArgumentException(SR.Argument_InvalidOffLen);
+ if (length <= 1)
+ return;
+
+#if __MonoCS__
ref T p = ref Unsafe.As<byte, T>(ref array.GetRawSzArrayData());
int i = index;
int j = index + length - 1;
@@ -921,6 +925,18 @@ namespace System
i++;
j--;
}
+#else
+ ref T first = ref Unsafe.Add(ref Unsafe.As<byte, T>(ref array.GetRawSzArrayData()), index);
+ ref T last = ref Unsafe.Add(ref Unsafe.Add(ref first, length), -1);
+ do
+ {
+ T temp = first;
+ first = last;
+ last = temp;
+ first = ref Unsafe.Add(ref first, 1);
+ last = ref Unsafe.Add(ref last, -1);
+ } while (Unsafe.IsAddressLessThan(ref first, ref last));
+#endif
}
public void SetValue(object value, long index)
@@ -1094,7 +1110,7 @@ namespace System
throw new ArgumentException(SR.Argument_InvalidOffLen);
if (length > 1)
- ArraySortHelper<T>.Sort(array, index, length, comparer);
+ ArraySortHelper<T>.Default.Sort(array, index, length, comparer);
}
public static void Sort<T>(T[] array, Comparison<T> comparison)
diff --git a/src/System.Private.CoreLib/src/System/Attribute.cs b/src/System.Private.CoreLib/src/System/Attribute.cs
index 5f20722e2..8c48f16e3 100644
--- a/src/System.Private.CoreLib/src/System/Attribute.cs
+++ b/src/System.Private.CoreLib/src/System/Attribute.cs
@@ -20,7 +20,7 @@ namespace System
//
// This implementation implements the .NET Core behavior.
//
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
if (obj == null)
return false;
@@ -28,14 +28,14 @@ namespace System
if (this.GetType() != obj.GetType())
return false;
- Object[] thisFieldValues = this.ReadFields();
- Object[] thatfieldValues = ((Attribute)obj).ReadFields();
+ object[] thisFieldValues = this.ReadFields();
+ object[] thatfieldValues = ((Attribute)obj).ReadFields();
for (int i = 0; i < thisFieldValues.Length; i++)
{
// Visibility check and consistency check are not necessary.
- Object thisResult = thisFieldValues[i];
- Object thatResult = thatfieldValues[i];
+ object thisResult = thisFieldValues[i];
+ object thatResult = thatfieldValues[i];
if (!AreFieldValuesEqual(thisResult, thatResult))
{
@@ -47,7 +47,7 @@ namespace System
}
// Compares values of custom-attribute fields.
- private static bool AreFieldValuesEqual(Object thisValue, Object thatValue)
+ private static bool AreFieldValuesEqual(object thisValue, object thatValue)
{
if (thisValue == null && thatValue == null)
return true;
@@ -97,12 +97,12 @@ namespace System
public override int GetHashCode()
{
- Object vThis = null;
+ object vThis = null;
- Object[] fieldValues = this.ReadFields();
+ object[] fieldValues = this.ReadFields();
for (int i = 0; i < fieldValues.Length; i++)
{
- Object fieldValue = fieldValues[i];
+ object fieldValue = fieldValues[i];
// The hashcode of an array ignores the contents of the array, so it can produce
// different hashcodes for arrays with the same contents.
@@ -150,7 +150,7 @@ namespace System
// offset inside a caller-supplied array. Attribute.ReadFields() calls _ILT_GetNumFields() to figure out how large an array is needed.
//
[CLSCompliant(false)]
- protected virtual void _ILT_ReadFields(Object[] destination, int offset)
+ protected virtual void _ILT_ReadFields(object[] destination, int offset)
{
}
@@ -158,10 +158,10 @@ namespace System
// ProjectN: Unlike the desktop, low level code such as Attributes cannot go running off to Reflection to fetch the FieldInfo's.
// Instead, we use the ILTransform to generate a method that returns the relevant field values, which we then compare as the desktop does.
//
- private Object[] ReadFields()
+ private object[] ReadFields()
{
int numFields = _ILT_GetNumFields();
- Object[] fieldValues = new Object[numFields];
+ object[] fieldValues = new object[numFields];
_ILT_ReadFields(fieldValues, 0);
return fieldValues;
}
diff --git a/src/System.Private.CoreLib/src/System/Buffer.cs b/src/System.Private.CoreLib/src/System/Buffer.cs
index b8c840e42..35ce0d5a2 100644
--- a/src/System.Private.CoreLib/src/System/Buffer.cs
+++ b/src/System.Private.CoreLib/src/System/Buffer.cs
@@ -98,80 +98,6 @@ namespace System
}
}
- // This is ported from the optimized CRT assembly in memchr.asm. The JIT generates
- // pretty good code here and this ends up being within a couple % of the CRT asm.
- // It is however cross platform as the CRT hasn't ported their fast version to 64-bit
- // platforms.
- //
- internal static unsafe int IndexOfByte(byte* src, byte value, int index, int count)
- {
- byte* pByte = src + index;
-
- // Align up the pointer to sizeof(int).
- while (((int)pByte & 3) != 0)
- {
- if (count == 0)
- return -1;
- else if (*pByte == value)
- return (int)(pByte - src);
-
- count--;
- pByte++;
- }
-
- // Fill comparer with value byte for comparisons
- //
- // comparer = 0/0/value/value
- uint comparer = (((uint)value << 8) + (uint)value);
- // comparer = value/value/value/value
- comparer = (comparer << 16) + comparer;
-
- // Run through buffer until we hit a 4-byte section which contains
- // the byte we're looking for or until we exhaust the buffer.
- while (count > 3)
- {
- // Test the buffer for presence of value. comparer contains the byte
- // replicated 4 times.
- uint t1 = *(uint*)pByte;
- t1 = t1 ^ comparer;
- uint t2 = 0x7efefeff + t1;
- t1 = t1 ^ 0xffffffff;
- t1 = t1 ^ t2;
- t1 = t1 & 0x81010100;
-
- // if t1 is zero then these 4-bytes don't contain a match
- if (t1 != 0)
- {
- // We've found a match for value, figure out which position it's in.
- int foundIndex = (int)(pByte - src);
- if (pByte[0] == value)
- return foundIndex;
- else if (pByte[1] == value)
- return foundIndex + 1;
- else if (pByte[2] == value)
- return foundIndex + 2;
- else if (pByte[3] == value)
- return foundIndex + 3;
- }
-
- count -= 4;
- pByte += 4;
- }
-
- // Catch any bytes that might be left at the tail of the buffer
- while (count > 0)
- {
- if (*pByte == value)
- return (int)(pByte - src);
-
- count--;
- pByte++;
- }
-
- // If we don't have a match return -1;
- return -1;
- }
-
internal static unsafe void ZeroMemory(byte* src, long len)
{
while (len-- > 0)
diff --git a/src/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.CoreRT.cs b/src/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.CoreRT.cs
new file mode 100644
index 000000000..d80eefb7a
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.CoreRT.cs
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Diagnostics;
+using System.Runtime.Versioning;
+
+namespace System.Collections.Generic
+{
+ internal partial class ArraySortHelper<T>
+ {
+ private static readonly ArraySortHelper<T> s_defaultArraySortHelper = new ArraySortHelper<T>();
+
+ public static ArraySortHelper<T> Default
+ {
+ get
+ {
+ return s_defaultArraySortHelper;
+ }
+ }
+ }
+
+ internal partial class ArraySortHelper<TKey, TValue>
+ {
+ private static readonly ArraySortHelper<TKey, TValue> s_defaultArraySortHelper = new ArraySortHelper<TKey, TValue>();
+
+ public static ArraySortHelper<TKey, TValue> Default
+ {
+ get
+ {
+ return s_defaultArraySortHelper;
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.cs b/src/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.cs
deleted file mode 100644
index dcb7d01ac..000000000
--- a/src/System.Private.CoreLib/src/System/Collections/Generic/ArraySortHelper.cs
+++ /dev/null
@@ -1,603 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-
-namespace System.Collections.Generic
-{
- #region ArraySortHelper for single arrays
-
- internal static class IntrospectiveSortUtilities
- {
- // This is the threshold where Introspective sort switches to Insertion sort.
- // Empirically, 16 seems to speed up most cases without slowing down others, at least for integers.
- // Large value types may benefit from a smaller number.
- internal const int IntrosortSizeThreshold = 16;
-
- internal static int FloorLog2PlusOne(int n)
- {
- int result = 0;
- while (n >= 1)
- {
- result++;
- n = n / 2;
- }
- return result;
- }
-
- internal static void ThrowOrIgnoreBadComparer(Object comparer)
- {
- // This is hit when an invarant of QuickSort is violated due to a bad IComparer implementation (for
- // example, imagine an IComparer that returns 0 when items are equal but -1 all other times).
- throw new ArgumentException(SR.Format(SR.Arg_BogusIComparer, comparer));
- }
- }
-
- internal class ArraySortHelper<T>
- {
- #region ArraySortHelper<T> public Members
-
- public static void Sort(T[] keys, int index, int length, IComparer<T> comparer)
- {
- Debug.Assert(keys != null, "Check the arguments in the caller!");
- Debug.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!");
-
- // Add a try block here to detect IComparers (or their
- // underlying IComparables, etc) that are bogus.
- try
- {
- if (comparer == null)
- {
- comparer = Comparer<T>.Default;
- }
-
- IntrospectiveSort(keys, index, length, comparer.Compare);
- }
- catch (IndexOutOfRangeException)
- {
- IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
- }
- catch (Exception e)
- {
- throw new InvalidOperationException(SR.InvalidOperation_IComparerFailed, e);
- }
- }
-
- public static int BinarySearch(T[] array, int index, int length, T value, IComparer<T> comparer)
- {
- try
- {
- if (comparer == null)
- {
- comparer = Comparer<T>.Default;
- }
-
- return InternalBinarySearch(array, index, length, value, comparer);
- }
- catch (Exception e)
- {
- throw new InvalidOperationException(SR.InvalidOperation_IComparerFailed, e);
- }
- }
-
- #endregion
-
- internal static void Sort(T[] keys, int index, int length, Comparison<T> comparer)
- {
- Debug.Assert(keys != null, "Check the arguments in the caller!");
- Debug.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!");
- Debug.Assert(comparer != null, "Check the arguments in the caller!");
-
- // Add a try block here to detect bogus comparisons
- try
- {
- IntrospectiveSort(keys, index, length, comparer);
- }
- catch (IndexOutOfRangeException)
- {
- IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
- }
- catch (Exception e)
- {
- throw new InvalidOperationException(SR.InvalidOperation_IComparerFailed, e);
- }
- }
-
- internal static int InternalBinarySearch(T[] array, int index, int length, T value, IComparer<T> comparer)
- {
- Debug.Assert(array != null, "Check the arguments in the caller!");
- Debug.Assert(index >= 0 && length >= 0 && (array.Length - index >= length), "Check the arguments in the caller!");
-
- int lo = index;
- int hi = index + length - 1;
- while (lo <= hi)
- {
- int i = lo + ((hi - lo) >> 1);
- int order = comparer.Compare(array[i], value);
-
- if (order == 0) return i;
- if (order < 0)
- {
- lo = i + 1;
- }
- else
- {
- hi = i - 1;
- }
- }
-
- return ~lo;
- }
-
- private static void SwapIfGreater(T[] keys, Comparison<T> comparer, int a, int b)
- {
- if (a != b)
- {
- if (comparer(keys[a], keys[b]) > 0)
- {
- T key = keys[a];
- keys[a] = keys[b];
- keys[b] = key;
- }
- }
- }
-
- private static void Swap(T[] a, int i, int j)
- {
- if (i != j)
- {
- T t = a[i];
- a[i] = a[j];
- a[j] = t;
- }
- }
-
- internal static void IntrospectiveSort(T[] keys, int left, int length, Comparison<T> comparer)
- {
- Debug.Assert(keys != null);
- Debug.Assert(comparer != null);
- Debug.Assert(left >= 0);
- Debug.Assert(length >= 0);
- Debug.Assert(length <= keys.Length);
- Debug.Assert(length + left <= keys.Length);
-
- if (length < 2)
- return;
-
- IntroSort(keys, left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2PlusOne(keys.Length), comparer);
- }
-
- private static void IntroSort(T[] keys, int lo, int hi, int depthLimit, Comparison<T> comparer)
- {
- Debug.Assert(keys != null);
- Debug.Assert(comparer != null);
- Debug.Assert(lo >= 0);
- Debug.Assert(hi < keys.Length);
-
- while (hi > lo)
- {
- int partitionSize = hi - lo + 1;
- if (partitionSize <= IntrospectiveSortUtilities.IntrosortSizeThreshold)
- {
- if (partitionSize == 1)
- {
- return;
- }
- if (partitionSize == 2)
- {
- SwapIfGreater(keys, comparer, lo, hi);
- return;
- }
- if (partitionSize == 3)
- {
- SwapIfGreater(keys, comparer, lo, hi - 1);
- SwapIfGreater(keys, comparer, lo, hi);
- SwapIfGreater(keys, comparer, hi - 1, hi);
- return;
- }
-
- InsertionSort(keys, lo, hi, comparer);
- return;
- }
-
- if (depthLimit == 0)
- {
- Heapsort(keys, lo, hi, comparer);
- return;
- }
- depthLimit--;
-
- int p = PickPivotAndPartition(keys, lo, hi, comparer);
- // Note we've already partitioned around the pivot and do not have to move the pivot again.
- IntroSort(keys, p + 1, hi, depthLimit, comparer);
- hi = p - 1;
- }
- }
-
- private static int PickPivotAndPartition(T[] keys, int lo, int hi, Comparison<T> comparer)
- {
- Debug.Assert(keys != null);
- Debug.Assert(comparer != null);
- Debug.Assert(lo >= 0);
- Debug.Assert(hi > lo);
- Debug.Assert(hi < keys.Length);
-
- // Compute median-of-three. But also partition them, since we've done the comparison.
- int middle = lo + ((hi - lo) / 2);
-
- // Sort lo, mid and hi appropriately, then pick mid as the pivot.
- SwapIfGreater(keys, comparer, lo, middle); // swap the low with the mid point
- SwapIfGreater(keys, comparer, lo, hi); // swap the low with the high
- SwapIfGreater(keys, comparer, middle, hi); // swap the middle with the high
-
- T pivot = keys[middle];
- Swap(keys, middle, hi - 1);
- int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
-
- while (left < right)
- {
- while (comparer(keys[++left], pivot) < 0) ;
- while (comparer(pivot, keys[--right]) < 0) ;
-
- if (left >= right)
- break;
-
- Swap(keys, left, right);
- }
-
- // Put pivot in the right location.
- Swap(keys, left, (hi - 1));
- return left;
- }
-
- private static void Heapsort(T[] keys, int lo, int hi, Comparison<T> comparer)
- {
- Debug.Assert(keys != null);
- Debug.Assert(comparer != null);
- Debug.Assert(lo >= 0);
- Debug.Assert(hi > lo);
- Debug.Assert(hi < keys.Length);
-
- int n = hi - lo + 1;
- for (int i = n / 2; i >= 1; i = i - 1)
- {
- DownHeap(keys, i, n, lo, comparer);
- }
- for (int i = n; i > 1; i = i - 1)
- {
- Swap(keys, lo, lo + i - 1);
- DownHeap(keys, 1, i - 1, lo, comparer);
- }
- }
-
- private static void DownHeap(T[] keys, int i, int n, int lo, Comparison<T> comparer)
- {
- Debug.Assert(keys != null);
- Debug.Assert(comparer != null);
- Debug.Assert(lo >= 0);
- Debug.Assert(lo < keys.Length);
-
- T d = keys[lo + i - 1];
- int child;
- while (i <= n / 2)
- {
- child = 2 * i;
- if (child < n && comparer(keys[lo + child - 1], keys[lo + child]) < 0)
- {
- child++;
- }
- if (!(comparer(d, keys[lo + child - 1]) < 0))
- break;
- keys[lo + i - 1] = keys[lo + child - 1];
- i = child;
- }
- keys[lo + i - 1] = d;
- }
-
- private static void InsertionSort(T[] keys, int lo, int hi, Comparison<T> comparer)
- {
- Debug.Assert(keys != null);
- Debug.Assert(lo >= 0);
- Debug.Assert(hi >= lo);
- Debug.Assert(hi <= keys.Length);
-
- int i, j;
- T t;
- for (i = lo; i < hi; i++)
- {
- j = i;
- t = keys[i + 1];
- while (j >= lo && comparer(t, keys[j]) < 0)
- {
- keys[j + 1] = keys[j];
- j--;
- }
- keys[j + 1] = t;
- }
- }
- }
-
-
- #endregion
-
- #region ArraySortHelper for paired key and value arrays
-
- internal class ArraySortHelper<TKey, TValue>
- {
- // WARNING: We allow diagnostic tools to directly inspect this member (s_defaultArraySortHelper).
- // See https://github.com/dotnet/corert/blob/master/Documentation/design-docs/diagnostics/diagnostics-tools-contract.md for more details.
- // Please do not change the type, the name, or the semantic usage of this member without understanding the implication for tools.
- // Get in touch with the diagnostics team if you have questions.
- private static volatile ArraySortHelper<TKey, TValue> s_defaultArraySortHelper;
-
- public static ArraySortHelper<TKey, TValue> Default
- {
- get
- {
- ArraySortHelper<TKey, TValue> sorter = s_defaultArraySortHelper;
- if (sorter == null)
- sorter = CreateArraySortHelper();
-
- return sorter;
- }
- }
-
- private static ArraySortHelper<TKey, TValue> CreateArraySortHelper()
- {
- s_defaultArraySortHelper = new ArraySortHelper<TKey, TValue>();
- return s_defaultArraySortHelper;
- }
-
- public void Sort(TKey[] keys, TValue[] values, int index, int length, IComparer<TKey> comparer)
- {
- Debug.Assert(keys != null, "Check the arguments in the caller!"); // Precondition on interface method
- Debug.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!");
-
- // Add a try block here to detect IComparers (or their
- // underlying IComparables, etc) that are bogus.
- try
- {
- if (comparer == null || comparer == Comparer<TKey>.Default)
- {
- comparer = Comparer<TKey>.Default;
- }
-
- IntrospectiveSort(keys, values, index, length, comparer);
- }
- catch (IndexOutOfRangeException)
- {
- IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
- }
- catch (Exception e)
- {
- throw new InvalidOperationException(SR.InvalidOperation_IComparerFailed, e);
- }
- }
-
- private static void SwapIfGreaterWithItems(TKey[] keys, TValue[] values, IComparer<TKey> comparer, int a, int b)
- {
- Debug.Assert(keys != null);
- Debug.Assert(comparer != null);
- Debug.Assert(0 <= a && a < keys.Length);
- Debug.Assert(0 <= b && b < keys.Length);
- Debug.Assert(values == null || (0 <= a && a < values.Length));
- Debug.Assert(values == null || (0 <= b && b < values.Length));
-
- if (a != b)
- {
- if (comparer.Compare(keys[a], keys[b]) > 0)
- {
- TKey key = keys[a];
- keys[a] = keys[b];
- keys[b] = key;
- if (values != null)
- {
- TValue value = values[a];
- values[a] = values[b];
- values[b] = value;
- }
- }
- }
- }
-
- private static void Swap(TKey[] keys, TValue[] values, int i, int j)
- {
- if (i != j)
- {
- TKey k = keys[i];
- keys[i] = keys[j];
- keys[j] = k;
- if (values != null)
- {
- TValue v = values[i];
- values[i] = values[j];
- values[j] = v;
- }
- }
- }
-
- internal static void IntrospectiveSort(TKey[] keys, TValue[] values, int left, int length, IComparer<TKey> comparer)
- {
- Debug.Assert(keys != null);
- Debug.Assert(values != null);
- Debug.Assert(comparer != null);
- Debug.Assert(left >= 0);
- Debug.Assert(length >= 0);
- Debug.Assert(length <= keys.Length);
- Debug.Assert(length + left <= keys.Length);
- Debug.Assert(length + left <= values.Length);
-
- if (length < 2)
- return;
-
- IntroSort(keys, values, left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2PlusOne(keys.Length), comparer);
- }
-
- private static void IntroSort(TKey[] keys, TValue[] values, int lo, int hi, int depthLimit, IComparer<TKey> comparer)
- {
- Debug.Assert(keys != null);
- Debug.Assert(values != null);
- Debug.Assert(comparer != null);
- Debug.Assert(lo >= 0);
- Debug.Assert(hi < keys.Length);
-
- while (hi > lo)
- {
- int partitionSize = hi - lo + 1;
- if (partitionSize <= IntrospectiveSortUtilities.IntrosortSizeThreshold)
- {
- if (partitionSize == 1)
- {
- return;
- }
- if (partitionSize == 2)
- {
- SwapIfGreaterWithItems(keys, values, comparer, lo, hi);
- return;
- }
- if (partitionSize == 3)
- {
- SwapIfGreaterWithItems(keys, values, comparer, lo, hi - 1);
- SwapIfGreaterWithItems(keys, values, comparer, lo, hi);
- SwapIfGreaterWithItems(keys, values, comparer, hi - 1, hi);
- return;
- }
-
- InsertionSort(keys, values, lo, hi, comparer);
- return;
- }
-
- if (depthLimit == 0)
- {
- Heapsort(keys, values, lo, hi, comparer);
- return;
- }
- depthLimit--;
-
- int p = PickPivotAndPartition(keys, values, lo, hi, comparer);
- // Note we've already partitioned around the pivot and do not have to move the pivot again.
- IntroSort(keys, values, p + 1, hi, depthLimit, comparer);
- hi = p - 1;
- }
- }
-
- private static int PickPivotAndPartition(TKey[] keys, TValue[] values, int lo, int hi, IComparer<TKey> comparer)
- {
- Debug.Assert(keys != null);
- Debug.Assert(values != null);
- Debug.Assert(comparer != null);
- Debug.Assert(lo >= 0);
- Debug.Assert(hi > lo);
- Debug.Assert(hi < keys.Length);
-
- // Compute median-of-three. But also partition them, since we've done the comparison.
- int middle = lo + ((hi - lo) / 2);
-
- // Sort lo, mid and hi appropriately, then pick mid as the pivot.
- SwapIfGreaterWithItems(keys, values, comparer, lo, middle); // swap the low with the mid point
- SwapIfGreaterWithItems(keys, values, comparer, lo, hi); // swap the low with the high
- SwapIfGreaterWithItems(keys, values, comparer, middle, hi); // swap the middle with the high
-
- TKey pivot = keys[middle];
- Swap(keys, values, middle, hi - 1);
- int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
-
- while (left < right)
- {
- while (comparer.Compare(keys[++left], pivot) < 0) ;
- while (comparer.Compare(pivot, keys[--right]) < 0) ;
-
- if (left >= right)
- break;
-
- Swap(keys, values, left, right);
- }
-
- // Put pivot in the right location.
- Swap(keys, values, left, (hi - 1));
- return left;
- }
-
- private static void Heapsort(TKey[] keys, TValue[] values, int lo, int hi, IComparer<TKey> comparer)
- {
- Debug.Assert(keys != null);
- Debug.Assert(values != null);
- Debug.Assert(comparer != null);
- Debug.Assert(lo >= 0);
- Debug.Assert(hi > lo);
- Debug.Assert(hi < keys.Length);
-
- int n = hi - lo + 1;
- for (int i = n / 2; i >= 1; i = i - 1)
- {
- DownHeap(keys, values, i, n, lo, comparer);
- }
- for (int i = n; i > 1; i = i - 1)
- {
- Swap(keys, values, lo, lo + i - 1);
- DownHeap(keys, values, 1, i - 1, lo, comparer);
- }
- }
-
- private static void DownHeap(TKey[] keys, TValue[] values, int i, int n, int lo, IComparer<TKey> comparer)
- {
- Debug.Assert(keys != null);
- Debug.Assert(comparer != null);
- Debug.Assert(lo >= 0);
- Debug.Assert(lo < keys.Length);
-
- TKey d = keys[lo + i - 1];
- TValue dValue = (values != null) ? values[lo + i - 1] : default(TValue);
- int child;
- while (i <= n / 2)
- {
- child = 2 * i;
- if (child < n && comparer.Compare(keys[lo + child - 1], keys[lo + child]) < 0)
- {
- child++;
- }
- if (!(comparer.Compare(d, keys[lo + child - 1]) < 0))
- break;
- keys[lo + i - 1] = keys[lo + child - 1];
- if (values != null)
- values[lo + i - 1] = values[lo + child - 1];
- i = child;
- }
- keys[lo + i - 1] = d;
- if (values != null)
- values[lo + i - 1] = dValue;
- }
-
- private static void InsertionSort(TKey[] keys, TValue[] values, int lo, int hi, IComparer<TKey> comparer)
- {
- Debug.Assert(keys != null);
- Debug.Assert(values != null);
- Debug.Assert(comparer != null);
- Debug.Assert(lo >= 0);
- Debug.Assert(hi >= lo);
- Debug.Assert(hi <= keys.Length);
-
- int i, j;
- TKey t;
- TValue tValue;
- for (i = lo; i < hi; i++)
- {
- j = i;
- t = keys[i + 1];
- tValue = (values != null) ? values[i + 1] : default(TValue);
- while (j >= lo && comparer.Compare(t, keys[j]) < 0)
- {
- keys[j + 1] = keys[j];
- if (values != null)
- values[j + 1] = values[j];
- j--;
- }
- keys[j + 1] = t;
- if (values != null)
- values[j + 1] = tValue;
- }
- }
- }
- #endregion
-}
diff --git a/src/System.Private.CoreLib/src/System/Collections/Generic/CompatibilityEqualityComparers.cs b/src/System.Private.CoreLib/src/System/Collections/Generic/CompatibilityEqualityComparers.cs
index 33aef24b9..c22edd601 100644
--- a/src/System.Private.CoreLib/src/System/Collections/Generic/CompatibilityEqualityComparers.cs
+++ b/src/System.Private.CoreLib/src/System/Collections/Generic/CompatibilityEqualityComparers.cs
@@ -24,7 +24,7 @@ namespace System.Collections.Generic
}
// Equals method for the comparer itself.
- public override bool Equals(Object obj) => obj != null && GetType() == obj.GetType();
+ public override bool Equals(object obj) => obj != null && GetType() == obj.GetType();
public override int GetHashCode() => GetType().GetHashCode();
}
diff --git a/src/System.Private.CoreLib/src/System/Collections/Generic/EqualOnlyComparer.cs b/src/System.Private.CoreLib/src/System/Collections/Generic/EqualOnlyComparer.cs
index 8916147f7..cd52c6c3e 100644
--- a/src/System.Private.CoreLib/src/System/Collections/Generic/EqualOnlyComparer.cs
+++ b/src/System.Private.CoreLib/src/System/Collections/Generic/EqualOnlyComparer.cs
@@ -9,42 +9,42 @@ namespace System.Collections.Generic
{
internal static class EqualOnlyComparerHelper
{
- public static bool Equals(SByte x, SByte y)
+ public static bool Equals(sbyte x, sbyte y)
{
return x == y;
}
- public static bool Equals(Byte x, Byte y)
+ public static bool Equals(byte x, byte y)
{
return x == y;
}
- public static bool Equals(Int16 x, Int16 y)
+ public static bool Equals(short x, short y)
{
return x == y;
}
- public static bool Equals(UInt16 x, UInt16 y)
+ public static bool Equals(ushort x, ushort y)
{
return x == y;
}
- public static bool Equals(Int32 x, Int32 y)
+ public static bool Equals(int x, int y)
{
return x == y;
}
- public static bool Equals(UInt32 x, UInt32 y)
+ public static bool Equals(uint x, uint y)
{
return x == y;
}
- public static bool Equals(Int64 x, Int64 y)
+ public static bool Equals(long x, long y)
{
return x == y;
}
- public static bool Equals(UInt64 x, UInt64 y)
+ public static bool Equals(ulong x, ulong y)
{
return x == y;
}
@@ -59,22 +59,22 @@ namespace System.Collections.Generic
return x == y;
}
- public static bool Equals(Single x, Single y)
+ public static bool Equals(float x, float y)
{
return x == y;
}
- public static bool Equals(Double x, Double y)
+ public static bool Equals(double x, double y)
{
return x == y;
}
- public static bool Equals(Decimal x, Decimal y)
+ public static bool Equals(decimal x, decimal y)
{
return x == y;
}
- public static bool Equals(String x, String y)
+ public static bool Equals(string x, string y)
{
return x == y;
}
@@ -95,33 +95,33 @@ namespace System.Collections.Generic
{
// Specialized Comparers
if (typeof(T) == typeof(System.SByte))
- return EqualOnlyComparerHelper.Equals(((System.SByte)(Object)(x)), ((System.SByte)(Object)(y)));
+ return EqualOnlyComparerHelper.Equals(((System.SByte)(object)(x)), ((System.SByte)(object)(y)));
else if (typeof(T) == typeof(System.Byte))
- return EqualOnlyComparerHelper.Equals(((System.Byte)(Object)(x)), ((System.Byte)(Object)(y)));
+ return EqualOnlyComparerHelper.Equals(((System.Byte)(object)(x)), ((System.Byte)(object)(y)));
else if (typeof(T) == typeof(System.Int16))
- return EqualOnlyComparerHelper.Equals(((System.Int16)(Object)(x)), ((System.Int16)(Object)(y)));
+ return EqualOnlyComparerHelper.Equals(((System.Int16)(object)(x)), ((System.Int16)(object)(y)));
else if (typeof(T) == typeof(System.UInt16))
- return EqualOnlyComparerHelper.Equals(((System.UInt16)(Object)(x)), ((System.UInt16)(Object)(y)));
+ return EqualOnlyComparerHelper.Equals(((System.UInt16)(object)(x)), ((System.UInt16)(object)(y)));
else if (typeof(T) == typeof(System.Int32))
- return EqualOnlyComparerHelper.Equals(((System.Int32)(Object)(x)), ((System.Int32)(Object)(y)));
+ return EqualOnlyComparerHelper.Equals(((System.Int32)(object)(x)), ((System.Int32)(object)(y)));
else if (typeof(T) == typeof(System.UInt32))
- return EqualOnlyComparerHelper.Equals(((System.UInt32)(Object)(x)), ((System.UInt32)(Object)(y)));
+ return EqualOnlyComparerHelper.Equals(((System.UInt32)(object)(x)), ((System.UInt32)(object)(y)));
else if (typeof(T) == typeof(System.Int64))
- return EqualOnlyComparerHelper.Equals(((System.Int64)(Object)(x)), ((System.Int64)(Object)(y)));
+ return EqualOnlyComparerHelper.Equals(((System.Int64)(object)(x)), ((System.Int64)(object)(y)));
else if (typeof(T) == typeof(System.UInt64))
- return EqualOnlyComparerHelper.Equals(((System.UInt64)(Object)(x)), ((System.UInt64)(Object)(y)));
+ return EqualOnlyComparerHelper.Equals(((System.UInt64)(object)(x)), ((System.UInt64)(object)(y)));
else if (typeof(T) == typeof(System.IntPtr))
- return EqualOnlyComparerHelper.Equals(((System.IntPtr)(Object)(x)), ((System.IntPtr)(Object)(y)));
+ return EqualOnlyComparerHelper.Equals(((System.IntPtr)(object)(x)), ((System.IntPtr)(object)(y)));
else if (typeof(T) == typeof(System.UIntPtr))
- return EqualOnlyComparerHelper.Equals(((System.UIntPtr)(Object)(x)), ((System.UIntPtr)(Object)(y)));
+ return EqualOnlyComparerHelper.Equals(((System.UIntPtr)(object)(x)), ((System.UIntPtr)(object)(y)));
else if (typeof(T) == typeof(System.Single))
- return EqualOnlyComparerHelper.Equals(((System.Single)(Object)(x)), ((System.Single)(Object)(y)));
+ return EqualOnlyComparerHelper.Equals(((System.Single)(object)(x)), ((System.Single)(object)(y)));
else if (typeof(T) == typeof(System.Double))
- return EqualOnlyComparerHelper.Equals(((System.Double)(Object)(x)), ((System.Double)(Object)(y)));
+ return EqualOnlyComparerHelper.Equals(((System.Double)(object)(x)), ((System.Double)(object)(y)));
else if (typeof(T) == typeof(System.Decimal))
- return EqualOnlyComparerHelper.Equals(((System.Decimal)(Object)(x)), ((System.Decimal)(Object)(y)));
+ return EqualOnlyComparerHelper.Equals(((System.Decimal)(object)(x)), ((System.Decimal)(object)(y)));
else if (typeof(T) == typeof(System.String))
- return EqualOnlyComparerHelper.Equals(((System.String)(Object)(x)), ((System.String)(Object)(y)));
+ return EqualOnlyComparerHelper.Equals(((System.String)(object)(x)), ((System.String)(object)(y)));
// Default Comparer
diff --git a/src/System.Private.CoreLib/src/System/CurrentSystemTimeZone.Cache.cs b/src/System.Private.CoreLib/src/System/CurrentSystemTimeZone.Cache.cs
deleted file mode 100644
index efa66ece9..000000000
--- a/src/System.Private.CoreLib/src/System/CurrentSystemTimeZone.Cache.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Globalization;
-using System.Collections.Concurrent;
-
-namespace System
-{
- internal partial class CurrentSystemTimeZone
- {
- private DaylightTime GetCachedDaylightChanges(int year) => _daylightChangesUnifier.GetOrAdd(year);
-
- private sealed class DaylightChangesUnifier : ConcurrentUnifier<int, DaylightTime>
- {
- protected sealed override DaylightTime Factory(int key) => CurrentSystemTimeZone.CreateDaylightChanges(key);
- }
-
- private readonly DaylightChangesUnifier _daylightChangesUnifier = new DaylightChangesUnifier();
- }
-}
diff --git a/src/System.Private.CoreLib/src/System/DefaultBinder.CanConvert.cs b/src/System.Private.CoreLib/src/System/DefaultBinder.CanConvert.cs
index 593deba6f..d0e4886a5 100644
--- a/src/System.Private.CoreLib/src/System/DefaultBinder.CanConvert.cs
+++ b/src/System.Private.CoreLib/src/System/DefaultBinder.CanConvert.cs
@@ -16,7 +16,7 @@ namespace System
}
// CanChangePrimitiveObjectToType
- private static bool CanChangePrimitiveObjectToType(Object source, Type type)
+ private static bool CanChangePrimitiveObjectToType(object source, Type type)
{
return CanPrimitiveWiden(source.GetType(), type);
}
diff --git a/src/System.Private.CoreLib/src/System/Delegate.DefaultParameters.cs b/src/System.Private.CoreLib/src/System/Delegate.DefaultParameters.cs
index 1820f68f1..8460fb8fa 100644
--- a/src/System.Private.CoreLib/src/System/Delegate.DefaultParameters.cs
+++ b/src/System.Private.CoreLib/src/System/Delegate.DefaultParameters.cs
@@ -52,7 +52,7 @@ namespace System
// Special encoding for MinInt is 0x0001 (which would normally mean -0).
if (curVal == 0x0001)
{
- return Int64.MinValue;
+ return long.MinValue;
}
// High bit is used to indicate an extended value
@@ -248,7 +248,7 @@ namespace System
decimalBits[1] = dataParser.GetInt();
decimalBits[2] = dataParser.GetInt();
decimalBits[3] = dataParser.GetInt();
- defaultValue = new Decimal(decimalBits);
+ defaultValue = new decimal(decimalBits);
return true;
case DefaultParamTypeDateTime:
defaultValue = new DateTime(dataParser.GetLong());
diff --git a/src/System.Private.CoreLib/src/System/Delegate.cs b/src/System.Private.CoreLib/src/System/Delegate.cs
index e4746b1ab..d44045b6f 100644
--- a/src/System.Private.CoreLib/src/System/Delegate.cs
+++ b/src/System.Private.CoreLib/src/System/Delegate.cs
@@ -31,7 +31,7 @@ namespace System
}
// V1 API: Create closed instance delegates. Method name matching is case sensitive.
- protected Delegate(Object target, String method)
+ protected Delegate(object target, string method)
{
// This constructor cannot be used by application code. To create a delegate by specifying the name of a method, an
// overload of the public static CreateDelegate method is used. This will eventually end up calling into the internal
@@ -41,7 +41,7 @@ namespace System
}
// V1 API: Create open static delegates. Method name matching is case insensitive.
- protected Delegate(Type target, String method)
+ protected Delegate(Type target, string method)
{
// This constructor cannot be used by application code. To create a delegate by specifying the name of a method, an
// overload of the public static CreateDelegate method is used. This will eventually end up calling into the internal
@@ -373,7 +373,22 @@ namespace System
else
{
IntPtr invokeThunk = this.GetThunk(DelegateInvokeThunk);
- object result = System.InvokeUtils.CallDynamicInvokeMethod(this.m_firstParameter, this.m_functionPointer, this, invokeThunk, IntPtr.Zero, this, args, binderBundle: null, wrapInTargetInvocationException: true);
+#if PROJECTN
+ object result = InvokeUtils.CallDynamicInvokeMethod(this.m_firstParameter, this.m_functionPointer, this, invokeThunk, IntPtr.Zero, this, args, binderBundle: null, wrapInTargetInvocationException: true);
+#else
+ IntPtr genericDictionary = IntPtr.Zero;
+ if (FunctionPointerOps.IsGenericMethodPointer(invokeThunk))
+ {
+ unsafe
+ {
+ GenericMethodDescriptor* descriptor = FunctionPointerOps.ConvertToGenericDescriptor(invokeThunk);
+ genericDictionary = descriptor->InstantiationArgument;
+ invokeThunk = descriptor->MethodFunctionPointer;
+ }
+ }
+
+ object result = InvokeUtils.CallDynamicInvokeMethod(this.m_firstParameter, this.m_functionPointer, null, invokeThunk, genericDictionary, this, args, binderBundle: null, wrapInTargetInvocationException: true, invokeMethodHelperIsThisCall: false);
+#endif
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
return result;
}
@@ -479,8 +494,8 @@ namespace System
MulticastDelegate d = (MulticastDelegate)o;
MulticastDelegate dd = (MulticastDelegate)a[index];
- if (Object.ReferenceEquals(dd.m_firstParameter, d.m_firstParameter) &&
- Object.ReferenceEquals(dd.m_helperObject, d.m_helperObject) &&
+ if (object.ReferenceEquals(dd.m_firstParameter, d.m_firstParameter) &&
+ object.ReferenceEquals(dd.m_helperObject, d.m_helperObject) &&
dd.m_extraFunctionPointerOrData == d.m_extraFunctionPointerOrData &&
dd.m_functionPointer == d.m_functionPointer)
{
@@ -495,7 +510,7 @@ namespace System
// to form a new delegate.
protected virtual Delegate CombineImpl(Delegate d)
{
- if ((Object)d == null) // cast to object for a more efficient test
+ if ((object)d == null) // cast to object for a more efficient test
return this;
// Verify that the types are the same...
@@ -724,7 +739,7 @@ namespace System
return RuntimeAugments.Callbacks.GetDelegateMethod(this);
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
// It is expected that all real uses of the Equals method will hit the MulticastDelegate.Equals logic instead of this
// therefore, instead of duplicating the desktop behavior where direct calls to this Equals function do not behave
@@ -734,21 +749,21 @@ namespace System
public static bool operator ==(Delegate d1, Delegate d2)
{
- if ((Object)d1 == null)
- return (Object)d2 == null;
+ if ((object)d1 == null)
+ return (object)d2 == null;
return d1.Equals(d2);
}
public static bool operator !=(Delegate d1, Delegate d2)
{
- if ((Object)d1 == null)
- return (Object)d2 != null;
+ if ((object)d1 == null)
+ return (object)d2 != null;
return !d1.Equals(d2);
}
- public Object Target
+ public object Target
{
get
{
@@ -767,7 +782,7 @@ namespace System
return m_helperObject;
// Other non-closed thunks can be identified as the m_firstParameter field points at this.
- if (Object.ReferenceEquals(m_firstParameter, this))
+ if (object.ReferenceEquals(m_firstParameter, this))
{
return null;
}
@@ -853,7 +868,7 @@ namespace System
// Note that delegates constructed the normal way do not come through here. The IL transformer generates the equivalent of
// this code customized for each delegate type.
//
- internal static Delegate CreateDelegate(EETypePtr delegateEEType, IntPtr ldftnResult, Object thisObject, bool isStatic, bool isOpen)
+ internal static Delegate CreateDelegate(EETypePtr delegateEEType, IntPtr ldftnResult, object thisObject, bool isStatic, bool isOpen)
{
Delegate del = (Delegate)(RuntimeImports.RhNewObject(delegateEEType));
diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Contracts/Contracts.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Contracts/Contracts.cs
index 4ff7706e9..dbc814ded 100644
--- a/src/System.Private.CoreLib/src/System/Diagnostics/Contracts/Contracts.cs
+++ b/src/System.Private.CoreLib/src/System/Diagnostics/Contracts/Contracts.cs
@@ -161,14 +161,14 @@ namespace System.Diagnostics.Contracts
[SuppressMessage("Microsoft.Design", "CA1019:DefineAccessorsForAttributeArguments", Justification = "Thank you very much, but we like the names we've defined for the accessors")]
public sealed class ContractPublicPropertyNameAttribute : Attribute
{
- private String _publicName;
+ private string _publicName;
- public ContractPublicPropertyNameAttribute(String name)
+ public ContractPublicPropertyNameAttribute(string name)
{
_publicName = name;
}
- public String Name
+ public string Name
{
get { return _publicName; }
}
@@ -200,31 +200,31 @@ namespace System.Diagnostics.Contracts
[Conditional("CONTRACTS_FULL")]
public sealed class ContractOptionAttribute : Attribute
{
- private String _category;
- private String _setting;
+ private string _category;
+ private string _setting;
private bool _enabled;
- private String _value;
+ private string _value;
- public ContractOptionAttribute(String category, String setting, bool enabled)
+ public ContractOptionAttribute(string category, string setting, bool enabled)
{
_category = category;
_setting = setting;
_enabled = enabled;
}
- public ContractOptionAttribute(String category, String setting, String value)
+ public ContractOptionAttribute(string category, string setting, string value)
{
_category = category;
_setting = setting;
_value = value;
}
- public String Category
+ public string Category
{
get { return _category; }
}
- public String Setting
+ public string Setting
{
get { return _setting; }
}
@@ -234,7 +234,7 @@ namespace System.Diagnostics.Contracts
get { return _enabled; }
}
- public String Value
+ public string Value
{
get { return _value; }
}
@@ -293,7 +293,7 @@ namespace System.Diagnostics.Contracts
#if FEATURE_RELIABILITY_CONTRACTS
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
#endif
- public static void Assume(bool condition, String userMessage)
+ public static void Assume(bool condition, string userMessage)
{
if (!condition)
{
@@ -332,7 +332,7 @@ namespace System.Diagnostics.Contracts
#if FEATURE_RELIABILITY_CONTRACTS
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
#endif
- public static void Assert(bool condition, String userMessage)
+ public static void Assert(bool condition, string userMessage)
{
if (!condition)
ReportFailure(ContractFailureKind.Assert, userMessage, null, null);
@@ -376,7 +376,7 @@ namespace System.Diagnostics.Contracts
#if FEATURE_RELIABILITY_CONTRACTS
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
#endif
- public static void Requires(bool condition, String userMessage)
+ public static void Requires(bool condition, string userMessage)
{
AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires");
}
@@ -418,7 +418,7 @@ namespace System.Diagnostics.Contracts
#if FEATURE_RELIABILITY_CONTRACTS
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
#endif
- public static void Requires<TException>(bool condition, String userMessage) where TException : Exception
+ public static void Requires<TException>(bool condition, string userMessage) where TException : Exception
{
AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires<TException>");
}
@@ -461,7 +461,7 @@ namespace System.Diagnostics.Contracts
#if FEATURE_RELIABILITY_CONTRACTS
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
#endif
- public static void Ensures(bool condition, String userMessage)
+ public static void Ensures(bool condition, string userMessage)
{
AssertMustUseRewriter(ContractFailureKind.Postcondition, "Ensures");
}
@@ -504,7 +504,7 @@ namespace System.Diagnostics.Contracts
#if FEATURE_RELIABILITY_CONTRACTS
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
#endif
- public static void EnsuresOnThrow<TException>(bool condition, String userMessage) where TException : Exception
+ public static void EnsuresOnThrow<TException>(bool condition, string userMessage) where TException : Exception
{
AssertMustUseRewriter(ContractFailureKind.PostconditionOnException, "EnsuresOnThrow");
}
@@ -598,7 +598,7 @@ namespace System.Diagnostics.Contracts
#if FEATURE_RELIABILITY_CONTRACTS
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
#endif
- public static void Invariant(bool condition, String userMessage)
+ public static void Invariant(bool condition, string userMessage)
{
AssertMustUseRewriter(ContractFailureKind.Invariant, "Invariant");
}
@@ -733,7 +733,7 @@ namespace System.Diagnostics.Contracts
/// The runtime value is 2^64 - 1 or 2^32 - 1.
/// </summary>
[SuppressMessage("Microsoft.Performance", "CA1802", Justification = "FxCop is confused")]
- static readonly ulong MaxWritableExtent = (UIntPtr.Size == 4) ? UInt32.MaxValue : UInt64.MaxValue;
+ static readonly ulong MaxWritableExtent = (UIntPtr.Size == 4) ? uint.MaxValue : ulong.MaxValue;
/// <summary>
/// Allows specifying a writable extent for a UIntPtr, similar to SAL's writable extent.
@@ -851,13 +851,13 @@ namespace System.Diagnostics.Contracts
/// System.Runtime.CompilerServices.ContractHelper.RaiseContractFailedEvent, followed by
/// System.Runtime.CompilerServices.ContractHelper.TriggerFailure.
/// </summary>
- static partial void ReportFailure(ContractFailureKind failureKind, String userMessage, String conditionText, Exception innerException);
+ static partial void ReportFailure(ContractFailureKind failureKind, string userMessage, string conditionText, Exception innerException);
/// <summary>
/// This method is used internally to trigger a failure indicating to the "programmer" that he is using the interface incorrectly.
/// It is NEVER used to indicate failure of actual contracts at runtime.
/// </summary>
- static partial void AssertMustUseRewriter(ContractFailureKind kind, String contractKind);
+ static partial void AssertMustUseRewriter(ContractFailureKind kind, string contractKind);
#endregion
}
@@ -936,9 +936,9 @@ namespace System.Runtime.CompilerServices
#if FEATURE_RELIABILITY_CONTRACTS
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
#endif
- public static string RaiseContractFailedEvent(ContractFailureKind failureKind, String userMessage, String conditionText, Exception innerException)
+ public static string RaiseContractFailedEvent(ContractFailureKind failureKind, string userMessage, string conditionText, Exception innerException)
{
- String resultFailureMessage = "Contract failed"; // default in case implementation does not assign anything.
+ string resultFailureMessage = "Contract failed"; // default in case implementation does not assign anything.
RaiseContractFailedEventImplementation(failureKind, userMessage, conditionText, innerException, ref resultFailureMessage);
return resultFailureMessage;
}
@@ -951,7 +951,7 @@ namespace System.Runtime.CompilerServices
#if FEATURE_RELIABILITY_CONTRACTS
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
#endif
- public static void TriggerFailure(ContractFailureKind kind, String displayMessage, String userMessage, String conditionText, Exception innerException)
+ public static void TriggerFailure(ContractFailureKind kind, string displayMessage, string userMessage, string conditionText, Exception innerException)
{
TriggerFailureImplementation(kind, displayMessage, userMessage, conditionText, innerException);
}
@@ -971,12 +971,12 @@ namespace System.Runtime.CompilerServices
/// <param name="resultFailureMessage">Should really be out (or the return value), but partial methods are not flexible enough.
/// On exit: null if the event was handled and should not trigger a failure.
/// Otherwise, returns the localized failure message</param>
- static partial void RaiseContractFailedEventImplementation(ContractFailureKind failureKind, String userMessage, String conditionText, Exception innerException, ref string resultFailureMessage);
+ static partial void RaiseContractFailedEventImplementation(ContractFailureKind failureKind, string userMessage, string conditionText, Exception innerException, ref string resultFailureMessage);
/// <summary>
/// Implements the default failure behavior of the platform. Under the BCL, it triggers an Assert box.
/// </summary>
- static partial void TriggerFailureImplementation(ContractFailureKind kind, String displayMessage, String userMessage, String conditionText, Exception innerException);
+ static partial void TriggerFailureImplementation(ContractFailureKind kind, string displayMessage, string userMessage, string conditionText, Exception innerException);
#endregion Implementation Stubs
}
} // namespace System.Runtime.CompilerServices
diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Contracts/ContractsBCL.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Contracts/ContractsBCL.cs
index 56626bb8f..38b080bcb 100644
--- a/src/System.Private.CoreLib/src/System/Diagnostics/Contracts/ContractsBCL.cs
+++ b/src/System.Private.CoreLib/src/System/Diagnostics/Contracts/ContractsBCL.cs
@@ -36,7 +36,7 @@ namespace System.Diagnostics.Contracts
/// </summary>
#if FEATURE_UNTRUSTED_CALLERS
#endif
- static partial void AssertMustUseRewriter(ContractFailureKind kind, String contractKind)
+ static partial void AssertMustUseRewriter(ContractFailureKind kind, string contractKind)
{
//TODO: Implement CodeContract failure mechanics including enabling CCIRewrite
@@ -65,7 +65,7 @@ namespace System.Diagnostics.Contracts
//if (probablyNotRewritten == null)
// probablyNotRewritten = thisAssembly;
//String simpleName = probablyNotRewritten.GetName().Name;
- String simpleName = "System.Private.CoreLib";
+ string simpleName = "System.Private.CoreLib";
System.Runtime.CompilerServices.ContractHelper.TriggerFailure(kind, SR.Format(SR.MustUseCCRewrite, contractKind, simpleName), null, null, null);
t_assertingMustUseRewriter = false;
@@ -85,14 +85,14 @@ namespace System.Diagnostics.Contracts
#if FEATURE_RELIABILITY_CONTRACTS
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
#endif
- static partial void ReportFailure(ContractFailureKind failureKind, String userMessage, String conditionText, Exception innerException)
+ static partial void ReportFailure(ContractFailureKind failureKind, string userMessage, string conditionText, Exception innerException)
{
if (failureKind < ContractFailureKind.Precondition || failureKind > ContractFailureKind.Assume)
throw new ArgumentException(SR.Format(SR.Arg_EnumIllegalVal, failureKind), nameof(failureKind));
Contract.EndContractBlock();
// displayMessage == null means: yes we handled it. Otherwise it is the localized failure message
- String displayMessage = System.Runtime.CompilerServices.ContractHelper.RaiseContractFailedEvent(failureKind, userMessage, conditionText, innerException);
+ string displayMessage = System.Runtime.CompilerServices.ContractHelper.RaiseContractFailedEvent(failureKind, userMessage, conditionText, innerException);
if (displayMessage == null) return;
@@ -139,8 +139,8 @@ namespace System.Diagnostics.Contracts
public sealed class ContractFailedEventArgs : EventArgs
{
private ContractFailureKind _failureKind;
- private String _message;
- private String _condition;
+ private string _message;
+ private string _condition;
private Exception _originalException;
private bool _handled;
private bool _unwind;
@@ -150,7 +150,7 @@ namespace System.Diagnostics.Contracts
#if FEATURE_RELIABILITY_CONTRACTS
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
#endif
- public ContractFailedEventArgs(ContractFailureKind failureKind, String message, String condition, Exception originalException)
+ public ContractFailedEventArgs(ContractFailureKind failureKind, string message, string condition, Exception originalException)
{
Contract.Requires(originalException == null || failureKind == ContractFailureKind.PostconditionOnException);
_failureKind = failureKind;
@@ -159,8 +159,8 @@ namespace System.Diagnostics.Contracts
_originalException = originalException;
}
- public String Message { get { return _message; } }
- public String Condition { get { return _condition; } }
+ public string Message { get { return _message; } }
+ public string Condition { get { return _condition; } }
public ContractFailureKind FailureKind { get { return _failureKind; } }
public Exception OriginalException { get { return _originalException; } }
@@ -257,7 +257,7 @@ namespace System.Runtime.CompilerServices
#if !FEATURE_CORECLR
private static volatile EventHandler<ContractFailedEventArgs> s_contractFailedEvent;
- private static readonly Object s_lockObject = new Object();
+ private static readonly object s_lockObject = new object();
#endif // !FEATURE_CORECLR
internal const int COR_E_CODECONTRACTFAILED = unchecked((int)0x80131542);
@@ -321,14 +321,14 @@ namespace System.Runtime.CompilerServices
[System.Diagnostics.DebuggerNonUserCode]
#if FEATURE_RELIABILITY_CONTRACTS
#endif
- static partial void RaiseContractFailedEventImplementation(ContractFailureKind failureKind, String userMessage, String conditionText, Exception innerException, ref string resultFailureMessage)
+ static partial void RaiseContractFailedEventImplementation(ContractFailureKind failureKind, string userMessage, string conditionText, Exception innerException, ref string resultFailureMessage)
{
if (failureKind < ContractFailureKind.Precondition || failureKind > ContractFailureKind.Assume)
throw new ArgumentException(SR.Format(SR.Arg_EnumIllegalVal, failureKind), nameof(failureKind));
Contract.EndContractBlock();
string returnValue;
- String displayMessage = "contract failed."; // Incomplete, but in case of OOM during resource lookup...
+ string displayMessage = "contract failed."; // Incomplete, but in case of OOM during resource lookup...
#if !FEATURE_CORECLR
ContractFailedEventArgs eventArgs = null; // In case of OOM.
#endif // !FEATURE_CORECLR
@@ -392,7 +392,7 @@ namespace System.Runtime.CompilerServices
[System.Diagnostics.DebuggerNonUserCode]
#if FEATURE_UNTRUSTED_CALLERS && !FEATURE_CORECLR
#endif
- static partial void TriggerFailureImplementation(ContractFailureKind kind, String displayMessage, String userMessage, String conditionText, Exception innerException)
+ static partial void TriggerFailureImplementation(ContractFailureKind kind, string displayMessage, string userMessage, string conditionText, Exception innerException)
{
// If we're here, our intent is to pop up a dialog box (if we can). For developers
// interacting live with a debugger, this is a good experience. For Silverlight
@@ -414,7 +414,7 @@ namespace System.Runtime.CompilerServices
//TODO: Implement CodeContract failure mechanics including enabling CCIRewrite
- String stackTrace = null; //@todo: Any reasonable way to get a stack trace here?
+ string stackTrace = null; //@todo: Any reasonable way to get a stack trace here?
bool userSelectedIgnore = DeveloperExperience.Default.OnContractFailure(stackTrace, kind, displayMessage, userMessage, conditionText, innerException);
if (userSelectedIgnore)
return;
@@ -431,9 +431,9 @@ namespace System.Runtime.CompilerServices
// If we got here, the user selected Ignore. Continue.
}
- private static String GetFailureMessage(ContractFailureKind failureKind, String conditionText)
+ private static string GetFailureMessage(ContractFailureKind failureKind, string conditionText)
{
- bool hasConditionText = !String.IsNullOrEmpty(conditionText);
+ bool hasConditionText = !string.IsNullOrEmpty(conditionText);
switch (failureKind)
{
case ContractFailureKind.Assert:
@@ -463,7 +463,7 @@ namespace System.Runtime.CompilerServices
#if FEATURE_RELIABILITY_CONTRACTS
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
#endif
- private static String GetDisplayMessage(ContractFailureKind failureKind, String userMessage, String conditionText)
+ private static string GetDisplayMessage(ContractFailureKind failureKind, string userMessage, string conditionText)
{
// Well-formatted English messages will take one of four forms. A sentence ending in
// either a period or a colon, the condition string, then the message tacked
@@ -471,9 +471,9 @@ namespace System.Runtime.CompilerServices
// Note that both the conditionText and userMessage may be null. Also,
// on Silverlight we may not be able to look up a friendly string for the
// error message. Let's leverage Silverlight's default error message there.
- String failureMessage = GetFailureMessage(failureKind, conditionText);
+ string failureMessage = GetFailureMessage(failureKind, conditionText);
// Now add in the user message, if present.
- if (!String.IsNullOrEmpty(userMessage))
+ if (!string.IsNullOrEmpty(userMessage))
{
return failureMessage + " " + userMessage;
}
diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Debug.Windows.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Debug.Windows.cs
index 9493cadef..9cd935feb 100644
--- a/src/System.Private.CoreLib/src/System/Diagnostics/Debug.Windows.cs
+++ b/src/System.Private.CoreLib/src/System/Diagnostics/Debug.Windows.cs
@@ -22,7 +22,7 @@ namespace System.Diagnostics
}
}
- private static readonly object s_ForLock = new Object();
+ private static readonly object s_ForLock = new object();
private static void WriteCore(string message)
{
diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs
index 10298ebd5..4c47bd66b 100644
--- a/src/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs
+++ b/src/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs
@@ -49,14 +49,14 @@ namespace System.Diagnostics
/// desired events are actually reported to the debugger.
/// Constant representing the default category
/// </summary>
- public static readonly String DefaultCategory = null;
+ public static readonly string DefaultCategory = null;
/// <summary>
/// Posts a message for the attached debugger. If there is no
/// debugger attached, has no effect. The debugger may or may not
/// report the message depending on its settings.
/// </summary>
- public static void Log(int level, String category, String message)
+ public static void Log(int level, string category, string message)
{
if (IsLogging())
{
diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreRT.cs b/src/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreRT.cs
index cc8ac5a3d..31a0da58d 100644
--- a/src/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreRT.cs
+++ b/src/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreRT.cs
@@ -129,15 +129,15 @@ namespace System.Diagnostics
/// </summary>
internal void AppendToStackTrace(StringBuilder builder)
{
- if (_ipAddress == StackTraceHelper.SpecialIP.EdiSeparator)
- {
- builder.AppendLine(SR.StackTrace_EndStackTraceFromPreviousThrow);
- }
- else
+ if (_ipAddress != StackTraceHelper.SpecialIP.EdiSeparator)
{
builder.Append(SR.StackTrace_AtWord);
builder.AppendLine(DeveloperExperience.Default.CreateStackTraceString(_ipAddress, _needFileInfo));
}
+ if (GetIsLastFrameFromForeignExceptionStackTrace())
+ {
+ builder.AppendLine(SR.StackTrace_EndStackTraceFromPreviousThrow);
+ }
}
}
}
diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs b/src/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs
index 4d5a2155c..2aed3264a 100644
--- a/src/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs
+++ b/src/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs
@@ -148,14 +148,35 @@ namespace System.Diagnostics
private void InitializeForIpAddressArray(IntPtr[] ipAddresses, int skipFrames, int endFrameIndex, bool needFileInfo)
{
int frameCount = (skipFrames < endFrameIndex ? endFrameIndex - skipFrames : 0);
- if (frameCount > 0)
+
+ // Calculate true frame count upfront - we need to skip EdiSeparators which get
+ // collapsed onto boolean flags on the preceding stack frame
+ int outputFrameCount = 0;
+ for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
+ {
+ if (ipAddresses[frameIndex + skipFrames] != StackTraceHelper.SpecialIP.EdiSeparator)
+ {
+ outputFrameCount++;
+ }
+ }
+
+ if (outputFrameCount > 0)
{
- _stackFrames = new StackFrame[frameCount];
+ _stackFrames = new StackFrame[outputFrameCount];
+ int outputFrameIndex = 0;
for (int frameIndex = 0; frameIndex < frameCount; frameIndex++)
{
IntPtr ipAddress = ipAddresses[frameIndex + skipFrames];
- _stackFrames[frameIndex] = new StackFrame(ipAddress, needFileInfo);
+ if (ipAddress != StackTraceHelper.SpecialIP.EdiSeparator)
+ {
+ _stackFrames[outputFrameIndex++] = new StackFrame(ipAddress, needFileInfo);
+ }
+ else if (outputFrameIndex > 0)
+ {
+ _stackFrames[outputFrameIndex - 1].SetIsLastFrameFromForeignExceptionStackTrace(true);
+ }
}
+ Debug.Assert(outputFrameIndex == outputFrameCount);
}
}
@@ -201,7 +222,7 @@ namespace System.Diagnostics
/// <summary>
/// Builds a readable representation of the stack trace
/// </summary>
- public override String ToString()
+ public override string ToString()
{
return ToString(TraceFormat.Normal); // default behavior in RT did not have trailing newline
}
@@ -214,7 +235,7 @@ namespace System.Diagnostics
TrailingNewLine, // include a trailing new line character
}
- internal String ToString(TraceFormat traceFormat)
+ internal string ToString(TraceFormat traceFormat)
{
if (_stackFrames == null)
{
diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource_CoreRT.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource_CoreRT.cs
index fc7e17d2a..72ce7c99f 100644
--- a/src/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource_CoreRT.cs
+++ b/src/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventSource_CoreRT.cs
@@ -178,6 +178,9 @@ namespace System.Diagnostics.Tracing
this.Tags = tags;
this.EnabledForAnyListener = enabledForAnyListener;
this.EnabledForETW = enabledForETW;
+#if FEATURE_PERFTRACING
+ this.EnabledForEventPipe = false;
+#endif
this.TriggersActivityTracking = 0;
this.Name = name;
this.Message = message;
@@ -338,10 +341,10 @@ namespace System.Diagnostics.Tracing
if (fmt != null)
return string.Format(fmt, args);
- string sargs = String.Empty;
+ string sargs = string.Empty;
foreach(var arg in args)
{
- if (sargs != String.Empty)
+ if (sargs != string.Empty)
sargs += ", ";
sargs += arg.ToString();
}
diff --git a/src/System.Private.CoreLib/src/System/Diagnostics/Tracing/UnsafeNativeMethods.cs b/src/System.Private.CoreLib/src/System/Diagnostics/Tracing/UnsafeNativeMethods.cs
index 3d2e41eba..c070027e7 100644
--- a/src/System.Private.CoreLib/src/System/Diagnostics/Tracing/UnsafeNativeMethods.cs
+++ b/src/System.Private.CoreLib/src/System/Diagnostics/Tracing/UnsafeNativeMethods.cs
@@ -235,7 +235,7 @@ namespace Microsoft.Win32
[System.Security.SecuritySafeCritical]
// Gets an error message for a Win32 error code.
- internal static String GetMessage(int errorCode)
+ internal static string GetMessage(int errorCode)
{
#if FEATURE_MANAGED_ETW
return Interop.Kernel32.GetMessage(errorCode);
diff --git a/src/System.Private.CoreLib/src/System/EETypePtr.cs b/src/System.Private.CoreLib/src/System/EETypePtr.cs
index fa5abb6b0..d4778aeb1 100644
--- a/src/System.Private.CoreLib/src/System/EETypePtr.cs
+++ b/src/System.Private.CoreLib/src/System/EETypePtr.cs
@@ -41,7 +41,7 @@ namespace System
return _value;
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
if (obj is EETypePtr)
{
@@ -396,6 +396,7 @@ namespace System
}
[Intrinsic]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static EETypePtr EETypePtrOf<T>()
{
// Compilers are required to provide a low level implementation of this method.
diff --git a/src/System.Private.CoreLib/src/System/Enum.cs b/src/System.Private.CoreLib/src/System/Enum.cs
index 06da1b117..578c8f995 100644
--- a/src/System.Private.CoreLib/src/System/Enum.cs
+++ b/src/System.Private.CoreLib/src/System/Enum.cs
@@ -19,7 +19,7 @@ namespace System
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public abstract class Enum : ValueType, IComparable, IFormattable, IConvertible
{
- public int CompareTo(Object target)
+ public int CompareTo(object target)
{
if (target == null)
return 1;
@@ -77,7 +77,7 @@ namespace System
}
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
if (obj == null)
return false;
@@ -137,7 +137,7 @@ namespace System
}
}
- public static String Format(Type enumType, Object value, String format)
+ public static string Format(Type enumType, object value, string format)
{
if (enumType == null)
throw new ArgumentNullException(nameof(enumType));
@@ -170,7 +170,7 @@ namespace System
return Format(enumInfo, value, format);
}
- private static String Format(EnumInfo enumInfo, Object value, String format)
+ private static string Format(EnumInfo enumInfo, object value, string format)
{
ulong rawValue;
if (!TryGetUnboxedValueOfEnumOrInteger(value, out rawValue))
@@ -213,20 +213,20 @@ namespace System
//
// Helper for Enum.Format(,,"d")
//
- private static String DoFormatD(ulong rawValue, RuntimeImports.RhCorElementType corElementType)
+ private static string DoFormatD(ulong rawValue, RuntimeImports.RhCorElementType corElementType)
{
switch (corElementType)
{
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I1:
{
- SByte result = (SByte)rawValue;
+ sbyte result = (sbyte)rawValue;
return result.ToString();
}
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U1:
{
- Byte result = (Byte)rawValue;
+ byte result = (byte)rawValue;
return result.ToString();
}
@@ -240,49 +240,49 @@ namespace System
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I2:
{
- Int16 result = (Int16)rawValue;
+ short result = (short)rawValue;
return result.ToString();
}
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U2:
{
- UInt16 result = (UInt16)rawValue;
+ ushort result = (ushort)rawValue;
return result.ToString();
}
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR:
{
- Char result = (Char)rawValue;
+ char result = (char)rawValue;
return result.ToString();
}
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U4:
{
- UInt32 result = (UInt32)rawValue;
+ uint result = (uint)rawValue;
return result.ToString();
}
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I4:
{
- Int32 result = (Int32)rawValue;
+ int result = (int)rawValue;
return result.ToString();
}
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U8:
{
- UInt64 result = (UInt64)rawValue;
+ ulong result = (ulong)rawValue;
return result.ToString();
}
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I8:
{
- Int64 result = (Int64)rawValue;
+ long result = (long)rawValue;
return result.ToString();
}
@@ -297,20 +297,20 @@ namespace System
//
// Helper for Enum.Format(,,"x")
//
- private static String DoFormatX(ulong rawValue, RuntimeImports.RhCorElementType corElementType)
+ private static string DoFormatX(ulong rawValue, RuntimeImports.RhCorElementType corElementType)
{
switch (corElementType)
{
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I1:
{
- Byte result = (byte)(sbyte)rawValue;
+ byte result = (byte)(sbyte)rawValue;
return result.ToString("X2", null);
}
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U1:
{
- Byte result = (byte)rawValue;
+ byte result = (byte)rawValue;
return result.ToString("X2", null);
}
@@ -318,56 +318,56 @@ namespace System
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_BOOLEAN:
{
// direct cast from bool to byte is not allowed
- Byte result = (byte)rawValue;
+ byte result = (byte)rawValue;
return result.ToString("X2", null);
}
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I2:
{
- UInt16 result = (UInt16)(Int16)rawValue;
+ ushort result = (ushort)(short)rawValue;
return result.ToString("X4", null);
}
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U2:
{
- UInt16 result = (UInt16)rawValue;
+ ushort result = (ushort)rawValue;
return result.ToString("X4", null);
}
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR:
{
- UInt16 result = (UInt16)(Char)rawValue;
+ ushort result = (ushort)(char)rawValue;
return result.ToString("X4", null);
}
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U4:
{
- UInt32 result = (UInt32)rawValue;
+ uint result = (uint)rawValue;
return result.ToString("X8", null);
}
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I4:
{
- UInt32 result = (UInt32)(int)rawValue;
+ uint result = (uint)(int)rawValue;
return result.ToString("X8", null);
}
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U8:
{
- UInt64 result = (UInt64)rawValue;
+ ulong result = (ulong)rawValue;
return result.ToString("X16", null);
}
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I8:
{
- UInt64 result = (UInt64)(Int64)rawValue;
+ ulong result = (ulong)(long)rawValue;
return result.ToString("X16", null);
}
@@ -381,13 +381,13 @@ namespace System
//
// Helper for Enum.Format(,,"g")
//
- private static String DoFormatG(EnumInfo enumInfo, ulong rawValue)
+ private static string DoFormatG(EnumInfo enumInfo, ulong rawValue)
{
Debug.Assert(enumInfo != null);
if (!enumInfo.HasFlagsAttribute) // Not marked with Flags attribute
{
// Try to see if its one of the enum values, then we return a String back else the value
- String name = GetNameIfAny(enumInfo, rawValue);
+ string name = GetNameIfAny(enumInfo, rawValue);
if (name == null)
return DoFormatD(rawValue, enumInfo.UnderlyingType.TypeHandle.ToEETypePtr().CorElementType);
else
@@ -402,12 +402,12 @@ namespace System
//
// Helper for Enum.Format(,,"f")
//
- private static String DoFormatF(EnumInfo enumInfo, ulong rawValue)
+ private static string DoFormatF(EnumInfo enumInfo, ulong rawValue)
{
Debug.Assert(enumInfo != null);
// These values are sorted by value. Don't change this
- KeyValuePair<String, ulong>[] namesAndValues = enumInfo.NamesAndValues;
+ KeyValuePair<string, ulong>[] namesAndValues = enumInfo.NamesAndValues;
int index = namesAndValues.Length - 1;
StringBuilder retval = new StringBuilder();
@@ -451,7 +451,7 @@ namespace System
return retval.ToString(); // Built a list of matching names. Return it.
}
- internal Object GetValue()
+ internal object GetValue()
{
ref byte pValue = ref this.GetRawData();
@@ -483,7 +483,7 @@ namespace System
}
}
- public static String GetName(Type enumType, Object value)
+ public static string GetName(Type enumType, object value)
{
if (enumType == null)
throw new ArgumentNullException(nameof(enumType));
@@ -502,11 +502,11 @@ namespace System
throw new ArgumentException(SR.Arg_MustBeEnum);
EnumInfo enumInfo = GetEnumInfo(enumType);
- String nameOrNull = GetNameIfAny(enumInfo, rawValue);
+ string nameOrNull = GetNameIfAny(enumInfo, rawValue);
return nameOrNull;
}
- public static String[] GetNames(Type enumType)
+ public static string[] GetNames(Type enumType)
{
if (enumType == null)
throw new ArgumentNullException(nameof(enumType));
@@ -517,8 +517,8 @@ namespace System
if (!enumType.IsEnum)
throw new ArgumentException(SR.Arg_MustBeEnum);
- KeyValuePair<String, ulong>[] namesAndValues = GetEnumInfo(enumType).NamesAndValues;
- String[] names = new String[namesAndValues.Length];
+ KeyValuePair<string, ulong>[] namesAndValues = GetEnumInfo(enumType).NamesAndValues;
+ string[] names = new string[namesAndValues.Length];
for (int i = 0; i < namesAndValues.Length; i++)
names[i] = namesAndValues[i].Key;
return names;
@@ -551,13 +551,24 @@ namespace System
Array values = GetEnumInfo(enumType).Values;
int count = values.Length;
+#if PROJECTN
Array result = Array.CreateInstance(enumType, count);
+#else
+ // Without universal shared generics, chances are slim that we'll have the appropriate
+ // array type available. Offer an escape hatch that avoids a MissingMetadataException
+ // at the cost of a small appcompat risk.
+ Array result;
+ if (AppContext.TryGetSwitch("Switch.System.Enum.RelaxedGetValues", out bool isRelaxed) && isRelaxed)
+ result = Array.CreateInstance(Enum.GetUnderlyingType(enumType), count);
+ else
+ result = Array.CreateInstance(enumType, count);
+#endif
Array.CopyImplValueTypeArrayNoInnerGcRefs(values, 0, result, 0, count);
return result;
}
[Intrinsic]
- public Boolean HasFlag(Enum flag)
+ public bool HasFlag(Enum flag)
{
if (flag == null)
throw new ArgumentNullException(nameof(flag));
@@ -584,7 +595,7 @@ namespace System
}
}
- public static bool IsDefined(Type enumType, Object value)
+ public static bool IsDefined(Type enumType, object value)
{
if (enumType == null)
throw new ArgumentNullException(nameof(enumType));
@@ -601,7 +612,7 @@ namespace System
throw new ArgumentException(SR.Arg_MustBeEnum);
EnumInfo enumInfo = GetEnumInfo(enumType);
- foreach (KeyValuePair<String, ulong> kv in enumInfo.NamesAndValues)
+ foreach (KeyValuePair<string, ulong> kv in enumInfo.NamesAndValues)
{
if (value.Equals(kv.Key))
return true;
@@ -641,33 +652,33 @@ namespace System
throw new ArgumentException(SR.Arg_MustBeEnum);
enumInfo = GetEnumInfo(enumType);
}
- String nameOrNull = GetNameIfAny(enumInfo, rawValue);
+ string nameOrNull = GetNameIfAny(enumInfo, rawValue);
return nameOrNull != null;
}
}
- public static Object Parse(Type enumType, String value)
+ public static object Parse(Type enumType, string value)
{
return Parse(enumType, value, ignoreCase: false);
}
- public static Object Parse(Type enumType, String value, bool ignoreCase)
+ public static object Parse(Type enumType, string value, bool ignoreCase)
{
- Object result;
+ object result;
Exception exception;
if (!TryParseEnum(enumType, value, ignoreCase, out result, out exception))
throw exception;
return result;
}
- public static TEnum Parse<TEnum>(String value) where TEnum : struct
+ public static TEnum Parse<TEnum>(string value) where TEnum : struct
{
return Parse<TEnum>(value, ignoreCase: false);
}
- public static TEnum Parse<TEnum>(String value, bool ignoreCase) where TEnum : struct
+ public static TEnum Parse<TEnum>(string value, bool ignoreCase) where TEnum : struct
{
- Object result;
+ object result;
Exception exception;
if (!TryParseEnum(typeof(TEnum), value, ignoreCase, out result, out exception))
throw exception;
@@ -728,7 +739,7 @@ namespace System
return RuntimeImports.RhBox(enumEEType, pValue);
}
- public static Object ToObject(Type enumType, Object value)
+ public static object ToObject(Type enumType, object value)
{
if (value == null)
throw new ArgumentNullException(nameof(value));
@@ -774,22 +785,22 @@ namespace System
}
}
- public static bool TryParse(Type enumType, String value, bool ignoreCase, out Object result)
+ public static bool TryParse(Type enumType, string value, bool ignoreCase, out object result)
{
Exception exception;
return TryParseEnum(enumType, value, ignoreCase, out result, out exception);
}
- public static bool TryParse(Type enumType, String value, out Object result)
+ public static bool TryParse(Type enumType, string value, out object result)
{
Exception exception;
return TryParseEnum(enumType, value, false, out result, out exception);
}
- public static bool TryParse<TEnum>(String value, bool ignoreCase, out TEnum result) where TEnum : struct
+ public static bool TryParse<TEnum>(string value, bool ignoreCase, out TEnum result) where TEnum : struct
{
Exception exception;
- Object tempResult;
+ object tempResult;
if (!TryParseEnum(typeof(TEnum), value, ignoreCase, out tempResult, out exception))
{
result = default(TEnum);
@@ -799,12 +810,12 @@ namespace System
return true;
}
- public static bool TryParse<TEnum>(String value, out TEnum result) where TEnum : struct
+ public static bool TryParse<TEnum>(string value, out TEnum result) where TEnum : struct
{
return TryParse<TEnum>(value, false, out result);
}
- public override String ToString()
+ public override string ToString()
{
try
{
@@ -816,7 +827,7 @@ namespace System
}
}
- public String ToString(String format)
+ public string ToString(string format)
{
if (format == null || format.Length == 0)
format = "G";
@@ -834,13 +845,13 @@ namespace System
}
[Obsolete("The provider argument is not used. Please use ToString().")]
- public String ToString(String format, IFormatProvider provider)
+ public string ToString(string format, IFormatProvider provider)
{
return ToString(format);
}
[Obsolete("The provider argument is not used. Please use ToString().")]
- public String ToString(IFormatProvider provider)
+ public string ToString(IFormatProvider provider)
{
return ToString();
}
@@ -857,7 +868,7 @@ namespace System
//
// Checks if value.GetType() matches enumType exactly.
//
- private static bool ValueTypeMatchesEnumType(Type enumType, Object value)
+ private static bool ValueTypeMatchesEnumType(Type enumType, object value)
{
EETypePtr enumEEType;
if (!enumType.TryGetEEType(out enumEEType))
@@ -885,7 +896,7 @@ namespace System
//
// The return value is "bool" if "value" is not an enum or an "integer type" as defined by the BCL Enum apis.
//
- private static bool TryGetUnboxedValueOfEnumOrInteger(Object value, out ulong result)
+ private static bool TryGetUnboxedValueOfEnumOrInteger(object value, out ulong result)
{
EETypePtr eeType = value.EETypePtr;
// For now, this check is required to flush out pointers.
@@ -949,10 +960,10 @@ namespace System
//
// Look up a name for rawValue if a matching one exists. Returns null if no matching name exists.
//
- private static String GetNameIfAny(EnumInfo enumInfo, ulong rawValue)
+ private static string GetNameIfAny(EnumInfo enumInfo, ulong rawValue)
{
- KeyValuePair<String, ulong>[] namesAndValues = enumInfo.NamesAndValues;
- KeyValuePair<String, ulong> searchKey = new KeyValuePair<String, ulong>(null, rawValue);
+ KeyValuePair<string, ulong>[] namesAndValues = enumInfo.NamesAndValues;
+ KeyValuePair<string, ulong> searchKey = new KeyValuePair<string, ulong>(null, rawValue);
int index = Array.BinarySearch<KeyValuePair<String, ulong>>(namesAndValues, searchKey, s_nameAndValueComparer);
if (index < 0)
return null;
@@ -962,7 +973,7 @@ namespace System
//
// Common funnel for Enum.Parse methods.
//
- private static bool TryParseEnum(Type enumType, String value, bool ignoreCase, out Object result, out Exception exception)
+ private static bool TryParseEnum(Type enumType, string value, bool ignoreCase, out object result, out Exception exception)
{
exception = null;
result = null;
@@ -1021,7 +1032,7 @@ namespace System
StringComparison comparison = ignoreCase ?
StringComparison.OrdinalIgnoreCase :
StringComparison.Ordinal;
- KeyValuePair<String, ulong>[] actualNamesAndValues = enumInfo.NamesAndValues;
+ KeyValuePair<string, ulong>[] actualNamesAndValues = enumInfo.NamesAndValues;
int valueIndex = firstNonWhitespaceIndex;
while (valueIndex <= value.Length) // '=' is to handle invalid case of an ending comma
{
@@ -1040,11 +1051,11 @@ namespace System
// Try to match this substring against each enum name
bool foundMatch = false;
- foreach (KeyValuePair<String, ulong> kv in actualNamesAndValues)
+ foreach (KeyValuePair<string, ulong> kv in actualNamesAndValues)
{
- String actualName = kv.Key;
+ string actualName = kv.Key;
if (actualName.Length == valueSubstringLength &&
- String.Compare(actualName, 0, value, valueIndex, valueSubstringLength, comparison) == 0)
+ string.Compare(actualName, 0, value, valueIndex, valueSubstringLength, comparison) == 0)
{
v |= kv.Value;
foundMatch = true;
@@ -1067,7 +1078,7 @@ namespace System
return true;
}
- private static bool TryParseAsInteger(EETypePtr enumEEType, String value, int valueOffset, out Object result)
+ private static bool TryParseAsInteger(EETypePtr enumEEType, string value, int valueOffset, out object result)
{
Debug.Assert(value != null, "Expected non-null value");
Debug.Assert(value.Length > 0, "Expected non-empty value");
@@ -1076,7 +1087,7 @@ namespace System
result = null;
char firstNonWhitespaceChar = value[valueOffset];
- if (!(Char.IsDigit(firstNonWhitespaceChar) || firstNonWhitespaceChar == '+' || firstNonWhitespaceChar == '-'))
+ if (!(char.IsDigit(firstNonWhitespaceChar) || firstNonWhitespaceChar == '+' || firstNonWhitespaceChar == '-'))
return false;
RuntimeImports.RhCorElementType corElementType = enumEEType.CorElementType;
@@ -1087,8 +1098,8 @@ namespace System
{
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_BOOLEAN:
{
- Boolean v;
- if (!Boolean.TryParse(value, out v))
+ bool v;
+ if (!bool.TryParse(value, out v))
return false;
result = RuntimeImports.RhBox(enumEEType, &v);
return true;
@@ -1096,8 +1107,8 @@ namespace System
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_CHAR:
{
- Char v;
- if (!Char.TryParse(value, out v))
+ char v;
+ if (!char.TryParse(value, out v))
return false;
result = RuntimeImports.RhBox(enumEEType, &v);
return true;
@@ -1105,8 +1116,8 @@ namespace System
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I1:
{
- SByte v;
- if (!SByte.TryParse(value, out v))
+ sbyte v;
+ if (!sbyte.TryParse(value, out v))
return false;
result = RuntimeImports.RhBox(enumEEType, &v);
return true;
@@ -1114,8 +1125,8 @@ namespace System
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U1:
{
- Byte v;
- if (!Byte.TryParse(value, out v))
+ byte v;
+ if (!byte.TryParse(value, out v))
return false;
result = RuntimeImports.RhBox(enumEEType, &v);
return true;
@@ -1123,8 +1134,8 @@ namespace System
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I2:
{
- Int16 v;
- if (!Int16.TryParse(value, out v))
+ short v;
+ if (!short.TryParse(value, out v))
return false;
result = RuntimeImports.RhBox(enumEEType, &v);
return true;
@@ -1132,8 +1143,8 @@ namespace System
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U2:
{
- UInt16 v;
- if (!UInt16.TryParse(value, out v))
+ ushort v;
+ if (!ushort.TryParse(value, out v))
return false;
result = RuntimeImports.RhBox(enumEEType, &v);
return true;
@@ -1141,8 +1152,8 @@ namespace System
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I4:
{
- Int32 v;
- if (!Int32.TryParse(value, out v))
+ int v;
+ if (!int.TryParse(value, out v))
return false;
result = RuntimeImports.RhBox(enumEEType, &v);
return true;
@@ -1150,8 +1161,8 @@ namespace System
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U4:
{
- UInt32 v;
- if (!UInt32.TryParse(value, out v))
+ uint v;
+ if (!uint.TryParse(value, out v))
return false;
result = RuntimeImports.RhBox(enumEEType, &v);
return true;
@@ -1159,8 +1170,8 @@ namespace System
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_I8:
{
- Int64 v;
- if (!Int64.TryParse(value, out v))
+ long v;
+ if (!long.TryParse(value, out v))
return false;
result = RuntimeImports.RhBox(enumEEType, &v);
return true;
@@ -1168,8 +1179,8 @@ namespace System
case RuntimeImports.RhCorElementType.ELEMENT_TYPE_U8:
{
- UInt64 v;
- if (!UInt64.TryParse(value, out v))
+ ulong v;
+ if (!ulong.TryParse(value, out v))
return false;
result = RuntimeImports.RhBox(enumEEType, &v);
return true;
@@ -1181,7 +1192,7 @@ namespace System
}
}
- private static bool StillLooksLikeInteger(String value, int index)
+ private static bool StillLooksLikeInteger(string value, int index)
{
if (index != value.Length && (value[index] == '-' || value[index] == '+'))
{
@@ -1243,9 +1254,9 @@ namespace System
//
// Sort comparer for NamesAndValues
//
- private class NamesAndValueComparer : IComparer<KeyValuePair<String, ulong>>
+ private class NamesAndValueComparer : IComparer<KeyValuePair<string, ulong>>
{
- public int Compare(KeyValuePair<String, ulong> kv1, KeyValuePair<String, ulong> kv2)
+ public int Compare(KeyValuePair<string, ulong> kv1, KeyValuePair<string, ulong> kv2)
{
ulong x = kv1.Value;
ulong y = kv2.Value;
@@ -1260,11 +1271,11 @@ namespace System
private static NamesAndValueComparer s_nameAndValueComparer = new NamesAndValueComparer();
- private String LastResortToString
+ private string LastResortToString
{
get
{
- return String.Format("{0}", GetValue());
+ return string.Format("{0}", GetValue());
}
}
@@ -1361,17 +1372,17 @@ namespace System
return Convert.ToDouble(GetValue(), CultureInfo.CurrentCulture);
}
- Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(GetValue(), CultureInfo.CurrentCulture);
}
DateTime IConvertible.ToDateTime(IFormatProvider provider)
{
- throw new InvalidCastException(String.Format(SR.InvalidCast_FromTo, "Enum", "DateTime"));
+ throw new InvalidCastException(string.Format(SR.InvalidCast_FromTo, "Enum", "DateTime"));
}
- Object IConvertible.ToType(Type type, IFormatProvider provider)
+ object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
diff --git a/src/System.Private.CoreLib/src/System/Environment.Unix.cs b/src/System.Private.CoreLib/src/System/Environment.Unix.cs
index c45d54bd8..af2e5517a 100644
--- a/src/System.Private.CoreLib/src/System/Environment.Unix.cs
+++ b/src/System.Private.CoreLib/src/System/Environment.Unix.cs
@@ -20,18 +20,6 @@ namespace System
}
}
- private static int ComputeExecutionId()
- {
- int executionId = Interop.Sys.SchedGetCpu();
-
- // sched_getcpu doesn't exist on all platforms. On those it doesn't exist on, the shim
- // returns -1. As a fallback in that case and to spread the threads across the buckets
- // by default, we use the current managed thread ID as a proxy.
- if (executionId < 0) executionId = Environment.CurrentManagedThreadId;
-
- return executionId;
- }
-
#if DEBUG
[Obsolete("ExpandEnvironmentVariables() only called on Windows so not implemented on Unix.")]
public static string ExpandEnvironmentVariables(string name)
diff --git a/src/System.Private.CoreLib/src/System/Environment.Windows.cs b/src/System.Private.CoreLib/src/System/Environment.Windows.cs
index f5fca35ab..71c9e06a4 100644
--- a/src/System.Private.CoreLib/src/System/Environment.Windows.cs
+++ b/src/System.Private.CoreLib/src/System/Environment.Windows.cs
@@ -12,8 +12,6 @@ namespace System
internal static long TickCount64 => (long)Interop.mincore.GetTickCount64();
- private static int ComputeExecutionId() => (int)Interop.mincore.GetCurrentProcessorNumber();
-
public static string ExpandEnvironmentVariables(string name)
{
if (name == null)
diff --git a/src/System.Private.CoreLib/src/System/Environment.cs b/src/System.Private.CoreLib/src/System/Environment.cs
index c1d4ac171..015c68bf9 100644
--- a/src/System.Private.CoreLib/src/System/Environment.cs
+++ b/src/System.Private.CoreLib/src/System/Environment.cs
@@ -50,17 +50,17 @@ namespace System
//// another managed helper method, unless you consult with some CLR Watson experts.
- public static void FailFast(String message)
+ public static void FailFast(string message)
{
RuntimeExceptionHelpers.FailFast(message);
}
- public static void FailFast(String message, Exception exception)
+ public static void FailFast(string message, Exception exception)
{
RuntimeExceptionHelpers.FailFast(message, exception);
}
- internal static void FailFast(String message, Exception exception, String errorSource)
+ internal static void FailFast(string message, Exception exception, string errorSource)
{
// TODO: errorSource originates from CoreCLR (See: https://github.com/dotnet/coreclr/pull/15895)
// For now, we ignore errorSource on CoreRT but we should distinguish the way FailFast prints exception message using errorSource
@@ -82,43 +82,6 @@ namespace System
}
}
- // The upper bits of t_executionIdCache are the executionId. The lower bits of
- // the t_executionIdCache are counting down to get it periodically refreshed.
- // TODO: Consider flushing the executionIdCache on Wait operations or similar
- // actions that are likely to result in changing the executing core
- [ThreadStatic]
- private static int t_executionIdCache;
-
- private const int ExecutionIdCacheShift = 16;
- private const int ExecutionIdCacheCountDownMask = (1 << ExecutionIdCacheShift) - 1;
- private const int ExecutionIdRefreshRate = 5000;
-
- private static int RefreshExecutionId()
- {
- int executionId = ComputeExecutionId();
-
- Debug.Assert(ExecutionIdRefreshRate <= ExecutionIdCacheCountDownMask);
-
- // Mask with Int32.MaxValue to ensure the execution Id is not negative
- t_executionIdCache = ((executionId << ExecutionIdCacheShift) & Int32.MaxValue) + ExecutionIdRefreshRate;
-
- return executionId;
- }
-
- // Cached processor number used as a hint for which per-core stack to access. It is periodically
- // refreshed to trail the actual thread core affinity.
- internal static int CurrentExecutionId
- {
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- get
- {
- int executionIdCache = t_executionIdCache--;
- if ((executionIdCache & ExecutionIdCacheCountDownMask) == 0)
- return RefreshExecutionId();
- return (executionIdCache >> ExecutionIdCacheShift);
- }
- }
-
public static bool HasShutdownStarted
{
get
@@ -135,7 +98,7 @@ namespace System
**Arguments: None.
**Exceptions: None.
==============================================================================*/
- public static String NewLine
+ public static string NewLine
{
get
{
@@ -147,7 +110,7 @@ namespace System
}
}
- public static String StackTrace
+ public static string StackTrace
{
// Disable inlining to have predictable stack frame that EnvironmentAugments can skip
[MethodImpl(MethodImplOptions.NoInlining)]
diff --git a/src/System.Private.CoreLib/src/System/Exception.cs b/src/System.Private.CoreLib/src/System/Exception.cs
index 6e4aba99c..0e3dbf7bd 100644
--- a/src/System.Private.CoreLib/src/System/Exception.cs
+++ b/src/System.Private.CoreLib/src/System/Exception.cs
@@ -29,7 +29,7 @@ namespace System
Init();
}
- public Exception(String message)
+ public Exception(string message)
{
Init();
_message = message;
@@ -40,7 +40,7 @@ namespace System
// Note: the stack trace is not started until the exception
// is thrown
//
- public Exception(String message, Exception innerException)
+ public Exception(string message, Exception innerException)
{
Init();
_message = message;
@@ -63,13 +63,13 @@ namespace System
_source = info.GetString("Source"); // Do not rename (binary serialization)
}
- public virtual String Message
+ public virtual string Message
{
get
{
if (_message == null)
{
- String className = GetClassName();
+ string className = GetClassName();
return SR.Format(SR.Exception_WasThrown, className);
}
else
@@ -177,14 +177,6 @@ namespace System
}
/// <summary>
- /// Allow System.Private.Interop to set HRESULT of an exception
- /// </summary>
- internal void SetErrorCode(int hr)
- {
- HResult = hr;
- }
-
- /// <summary>
/// Allow System.Private.Interop to set message of an exception
/// </summary>
internal void SetMessage(string msg)
@@ -240,18 +232,18 @@ namespace System
_message = Message; // Set the Message information correctly before serialization
}
- info.AddValue("ClassName", GetClassName(), typeof(String)); // Do not rename (binary serialization)
- info.AddValue("Message", _message, typeof(String)); // Do not rename (binary serialization)
+ info.AddValue("ClassName", GetClassName(), typeof(string)); // Do not rename (binary serialization)
+ info.AddValue("Message", _message, typeof(string)); // Do not rename (binary serialization)
info.AddValue("Data", _data, typeof(IDictionary)); // Do not rename (binary serialization)
info.AddValue("InnerException", _innerException, typeof(Exception)); // Do not rename (binary serialization)
- info.AddValue("HelpURL", _helpURL, typeof(String)); // Do not rename (binary serialization)
- info.AddValue("StackTraceString", StackTrace, typeof(String)); // Do not rename (binary serialization)
- info.AddValue("RemoteStackTraceString", null, typeof(String)); // Do not rename (binary serialization)
- info.AddValue("RemoteStackIndex", 0, typeof(Int32)); // Do not rename (binary serialization)
- info.AddValue("ExceptionMethod", null, typeof(String)); // Do not rename (binary serialization)
+ info.AddValue("HelpURL", _helpURL, typeof(string)); // Do not rename (binary serialization)
+ info.AddValue("StackTraceString", StackTrace, typeof(string)); // Do not rename (binary serialization)
+ info.AddValue("RemoteStackTraceString", null, typeof(string)); // Do not rename (binary serialization)
+ info.AddValue("RemoteStackIndex", 0, typeof(int)); // Do not rename (binary serialization)
+ info.AddValue("ExceptionMethod", null, typeof(string)); // Do not rename (binary serialization)
info.AddValue("HResult", HResult); // Do not rename (binary serialization)
- info.AddValue("Source", _source, typeof(String)); // Do not rename (binary serialization)
- info.AddValue("WatsonBuckets", null, typeof(String)); // Do not rename (binary serialization)
+ info.AddValue("Source", _source, typeof(string)); // Do not rename (binary serialization)
+ info.AddValue("WatsonBuckets", null, typeof(string)); // Do not rename (binary serialization)
}
private string GetStackTrace(bool needFileInfo)
@@ -259,7 +251,7 @@ namespace System
return this.StackTrace;
}
- public virtual String HelpLink
+ public virtual string HelpLink
{
get
{
@@ -272,7 +264,7 @@ namespace System
}
}
- public virtual String Source
+ public virtual string Source
{
get
{
@@ -288,15 +280,15 @@ namespace System
}
}
- public override String ToString()
+ public override string ToString()
{
return ToString(true, true);
}
- private String ToString(bool needFileLineInfo, bool needMessage)
+ private string ToString(bool needFileLineInfo, bool needMessage)
{
- String message = (needMessage ? Message : null);
- String s;
+ string message = (needMessage ? Message : null);
+ string s;
if (message == null || message.Length <= 0)
{
@@ -326,26 +318,26 @@ namespace System
// See https://github.com/dotnet/corert/blob/master/Documentation/design-docs/diagnostics/diagnostics-tools-contract.md for more details.
// Please do not change the type, the name, or the semantic usage of this member without understanding the implication for tools.
// Get in touch with the diagnostics team if you have questions.
- internal String _message;
+ internal string _message;
private IDictionary _data;
private Exception _innerException;
- private String _helpURL;
- private String _source; // Mainly used by VB.
+ private string _helpURL;
+ private string _source; // Mainly used by VB.
private int _HResult; // HResult
// To maintain compatibility across runtimes, if this object was deserialized, it will store its stack trace as a string
- private String _stackTrace;
+ private string _stackTrace;
public int HResult
{
get { return _HResult; }
- protected set { _HResult = value; }
+ set { _HResult = value; }
}
// Returns the stack trace as a string. If no stack trace is
// available, null is returned.
- public virtual String StackTrace
+ public virtual string StackTrace
{
get
{
@@ -524,7 +516,7 @@ namespace System
// for a small duration but that sounds reasonable considering
// such scenarios are going to be extremely rare, where timing
// matches precisely.
- private static Object s_EDILock = new Object();
+ private static object s_EDILock = new object();
/// <summary>
/// This is the binary format for serialized exceptions that get saved into a special buffer that is
@@ -536,8 +528,8 @@ namespace System
private struct SERIALIZED_EXCEPTION_HEADER
{
internal IntPtr ExceptionEEType;
- internal Int32 HResult;
- internal Int32 StackTraceElementCount;
+ internal int HResult;
+ internal int StackTraceElementCount;
// IntPtr * N : StackTrace elements
}
internal const int CurrentSerializationSignature = 0x31305845; // 'EX01'
diff --git a/src/System.Private.CoreLib/src/System/GC.cs b/src/System.Private.CoreLib/src/System/GC.cs
index 68d1bc9a3..1fc2846a6 100644
--- a/src/System.Private.CoreLib/src/System/GC.cs
+++ b/src/System.Private.CoreLib/src/System/GC.cs
@@ -61,7 +61,7 @@ namespace System
public static class GC
{
- public static int GetGeneration(Object obj)
+ public static int GetGeneration(object obj)
{
if (obj == null)
{
@@ -84,7 +84,7 @@ namespace System
{
// note - this throws an NRE if given a null weak reference. This isn't
// documented, but it's the behavior of Desktop and CoreCLR.
- Object handleRef = RuntimeImports.RhHandleGet(wo.m_handle);
+ object handleRef = RuntimeImports.RhHandleGet(wo.m_handle);
if (handleRef == null)
{
throw new ArgumentNullException(nameof(wo));
@@ -170,14 +170,14 @@ namespace System
{
throw new ArgumentOutOfRangeException(
nameof(maxGenerationThreshold),
- String.Format(SR.ArgumentOutOfRange_Bounds_Lower_Upper, 1, 99));
+ string.Format(SR.ArgumentOutOfRange_Bounds_Lower_Upper, 1, 99));
}
if (largeObjectHeapThreshold < 1 || largeObjectHeapThreshold > 99)
{
throw new ArgumentOutOfRangeException(
nameof(largeObjectHeapThreshold),
- String.Format(SR.ArgumentOutOfRange_Bounds_Lower_Upper, 1, 99));
+ string.Format(SR.ArgumentOutOfRange_Bounds_Lower_Upper, 1, 99));
}
// This is not documented on MSDN, but CoreCLR throws when the GC's
@@ -394,7 +394,7 @@ namespace System
RuntimeImports.RhWaitForPendingFinalizers(RuntimeThread.ReentrantWaitsEnabled);
}
- public static void SuppressFinalize(Object obj)
+ public static void SuppressFinalize(object obj)
{
if (obj == null)
{
@@ -404,7 +404,7 @@ namespace System
RuntimeImports.RhSuppressFinalize(obj);
}
- public static void ReRegisterForFinalize(Object obj)
+ public static void ReRegisterForFinalize(object obj)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
@@ -414,7 +414,7 @@ namespace System
[Intrinsic]
[MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
- public static void KeepAlive(Object obj)
+ public static void KeepAlive(object obj)
{
}
@@ -516,7 +516,7 @@ namespace System
}
#if !BIT64
- if (bytesAllocated > Int32.MaxValue)
+ if (bytesAllocated > int.MaxValue)
{
throw new ArgumentOutOfRangeException(nameof(bytesAllocated),
SR.ArgumentOutOfRange_MustBeNonNegInt32);
@@ -585,7 +585,7 @@ namespace System
}
#if !BIT64
- if (bytesAllocated > Int32.MaxValue)
+ if (bytesAllocated > int.MaxValue)
{
throw new ArgumentOutOfRangeException(nameof(bytesAllocated),
SR.ArgumentOutOfRange_MustBeNonNegInt32);
@@ -631,5 +631,20 @@ namespace System
{
return RuntimeImports.RhGetAllocatedBytesForCurrentThread();
}
+
+ internal static void GetMemoryInfo(out uint highMemLoadThreshold,
+ out ulong totalPhysicalMem,
+ out uint lastRecordedMemLoad,
+ // The next two are size_t
+ out UIntPtr lastRecordedHeapSize,
+ out UIntPtr lastRecordedFragmentation)
+ {
+ // TODO: https://github.com/dotnet/corert/issues/5680
+ highMemLoadThreshold = default;
+ totalPhysicalMem = default;
+ lastRecordedMemLoad = default;
+ lastRecordedHeapSize = default;
+ lastRecordedFragmentation = default;
+ }
}
}
diff --git a/src/System.Private.CoreLib/src/System/Globalization/CultureInfo.Windows.cs b/src/System.Private.CoreLib/src/System/Globalization/CultureInfo.Windows.cs
index df13759f7..151bb0d63 100644
--- a/src/System.Private.CoreLib/src/System/Globalization/CultureInfo.Windows.cs
+++ b/src/System.Private.CoreLib/src/System/Globalization/CultureInfo.Windows.cs
@@ -78,7 +78,7 @@ namespace System.Globalization
index++;
}
- CultureInfo temp = GetCultureByName(new String(languages, 0, index), true);
+ CultureInfo temp = GetCultureByName(new string(languages, 0, index), true);
temp._isReadOnly = true;
return temp;
}
diff --git a/src/System.Private.CoreLib/src/System/Globalization/CultureInfo.cs b/src/System.Private.CoreLib/src/System/Globalization/CultureInfo.cs
index 10776bcbd..19ccb9fef 100644
--- a/src/System.Private.CoreLib/src/System/Globalization/CultureInfo.cs
+++ b/src/System.Private.CoreLib/src/System/Globalization/CultureInfo.cs
@@ -155,12 +155,12 @@ namespace System.Globalization
////////////////////////////////////////////////////////////////////////
- public CultureInfo(String name)
+ public CultureInfo(string name)
: this(name, true)
{
}
- public CultureInfo(String name, bool useUserOverride)
+ public CultureInfo(string name, bool useUserOverride)
{
if (name == null)
{
@@ -242,7 +242,7 @@ namespace System.Globalization
// Note that we really cannot use an LCID version of this override as the cached
// name we create for it has to include both names, and the logic for this is in
// the GetCultureInfo override *only*.
- internal CultureInfo(String cultureName, String textAndCompareCultureName)
+ internal CultureInfo(string cultureName, string textAndCompareCultureName)
{
if (cultureName == null)
{
@@ -265,7 +265,7 @@ namespace System.Globalization
//
// TODO: It would appear that this is only ever called with userOveride = true
// and this method only has one caller. Can we fold it into the caller?
- private static CultureInfo GetCultureByName(String name, bool userOverride)
+ private static CultureInfo GetCultureByName(string name, bool userOverride)
{
CultureInfo ci = null;
// Try to get our culture
@@ -293,7 +293,7 @@ namespace System.Globalization
// if we can't find a bigger name. That doesn't help with things like "zh" though, so
// the approach is of questionable value
//
- public static CultureInfo CreateSpecificCulture(String name)
+ public static CultureInfo CreateSpecificCulture(string name)
{
CultureInfo culture;
@@ -343,7 +343,7 @@ namespace System.Globalization
return (new CultureInfo(culture._cultureData.SSPECIFICCULTURE));
}
- internal static bool VerifyCultureName(String cultureName, bool throwException)
+ internal static bool VerifyCultureName(string cultureName, bool throwException)
{
// This function is used by ResourceManager.GetResourceFileName().
// ResourceManager searches for resource using CultureInfo.Name,
@@ -353,7 +353,7 @@ namespace System.Globalization
{
char c = cultureName[i];
// TODO: Names can only be RFC4646 names (ie: a-zA-Z0-9) while this allows any unicode letter/digit
- if (Char.IsLetterOrDigit(c) || c == '-' || c == '_')
+ if (char.IsLetterOrDigit(c) || c == '-' || c == '_')
{
continue;
}
@@ -571,7 +571,7 @@ namespace System.Globalization
CultureInfo culture = null;
string parentName = _cultureData.SPARENT;
- if (String.IsNullOrEmpty(parentName))
+ if (string.IsNullOrEmpty(parentName))
{
culture = InvariantCulture;
}
@@ -628,7 +628,7 @@ namespace System.Globalization
// "en-US" This version does NOT include sort information in the name.
//
////////////////////////////////////////////////////////////////////////
- public virtual String Name
+ public virtual string Name
{
get
{
@@ -638,7 +638,7 @@ namespace System.Globalization
_nonSortName = _cultureData.SNAME;
if (_nonSortName == null)
{
- _nonSortName = String.Empty;
+ _nonSortName = string.Empty;
}
}
return _nonSortName;
@@ -646,7 +646,7 @@ namespace System.Globalization
}
// This one has the sort information (ie: de-DE_phoneb)
- internal String SortName
+ internal string SortName
{
get
{
@@ -685,7 +685,7 @@ namespace System.Globalization
// US English, "Ingles (Estados Unidos)" will be returned.
//
////////////////////////////////////////////////////////////////////////
- public virtual String DisplayName
+ public virtual string DisplayName
{
get
{
@@ -704,7 +704,7 @@ namespace System.Globalization
// (United States)" will be returned.
//
////////////////////////////////////////////////////////////////////////
- public virtual String NativeName
+ public virtual string NativeName
{
get
{
@@ -721,7 +721,7 @@ namespace System.Globalization
// (United States)" will be returned.
//
////////////////////////////////////////////////////////////////////////
- public virtual String EnglishName
+ public virtual string EnglishName
{
get
{
@@ -730,7 +730,7 @@ namespace System.Globalization
}
// ie: en
- public virtual String TwoLetterISOLanguageName
+ public virtual string TwoLetterISOLanguageName
{
get
{
@@ -739,7 +739,7 @@ namespace System.Globalization
}
// ie: eng
- public virtual String ThreeLetterISOLanguageName
+ public virtual string ThreeLetterISOLanguageName
{
get
{
@@ -755,7 +755,7 @@ namespace System.Globalization
// The ISO names are much preferred
//
////////////////////////////////////////////////////////////////////////
- public virtual String ThreeLetterWindowsLanguageName
+ public virtual string ThreeLetterWindowsLanguageName
{
get
{
@@ -842,9 +842,9 @@ namespace System.Globalization
////////////////////////////////////////////////////////////////////////
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
- if (Object.ReferenceEquals(this, value))
+ if (object.ReferenceEquals(this, value))
return true;
CultureInfo that = value as CultureInfo;
@@ -887,13 +887,13 @@ namespace System.Globalization
////////////////////////////////////////////////////////////////////////
- public override String ToString()
+ public override string ToString()
{
return _name;
}
- public virtual Object GetFormat(Type formatType)
+ public virtual object GetFormat(Type formatType)
{
if (formatType == typeof(NumberFormatInfo))
return (NumberFormat);
@@ -1131,7 +1131,7 @@ namespace System.Globalization
return (temp);
}
- public virtual Object Clone()
+ public virtual object Clone()
{
CultureInfo ci = (CultureInfo)MemberwiseClone();
ci._isReadOnly = false;
diff --git a/src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs b/src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs
index f292d54dc..eaa126b01 100644
--- a/src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs
+++ b/src/System.Private.CoreLib/src/System/Globalization/GlobalizationMode.Unix.cs
@@ -13,12 +13,17 @@ namespace System.Globalization
bool invariantEnabled = false;
if (!invariantEnabled)
{
+ // WASM TODO: There's no WASM build of LibICU. We may be able to cross-compile it ourselves.
+#if WASM
+ return true;
+#else
if (Interop.Globalization.LoadICU() == 0)
{
string message = "Couldn't find a valid ICU package installed on the system. " +
"Set the configuration flag System.Globalization.Invariant to true if you want to run with no globalization support.";
Environment.FailFast(message);
}
+#endif // !WASM
}
return invariantEnabled;
}
diff --git a/src/System.Private.CoreLib/src/System/Guid.Unix.cs b/src/System.Private.CoreLib/src/System/Guid.Unix.cs
deleted file mode 100644
index 326362d04..000000000
--- a/src/System.Private.CoreLib/src/System/Guid.Unix.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-
-namespace System
-{
- partial struct Guid
- {
- // This will create a new guid. Since we've now decided that constructors should 0-init,
- // we need a method that allows users to create a guid.
- public static Guid NewGuid()
- {
- // CoCreateGuid should never return Guid.Empty, since it attempts to maintain some
- // uniqueness guarantees. It should also never return a known GUID, but it's unclear
- // how extensively it checks for known values.
-
- Interop.Sys.CreateGuid(out Guid g);
- return g;
- }
- }
-}
diff --git a/src/System.Private.CoreLib/src/System/IO/Stream.CoreRT.cs b/src/System.Private.CoreLib/src/System/IO/Stream.CoreRT.cs
new file mode 100644
index 000000000..091b0fcef
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/IO/Stream.CoreRT.cs
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.IO
+{
+ public abstract partial class Stream
+ {
+ private bool HasOverriddenBeginEndRead() => true;
+
+ private bool HasOverriddenBeginEndWrite() => true;
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/IO/Stream.cs b/src/System.Private.CoreLib/src/System/IO/Stream.cs
deleted file mode 100644
index c307ec91e..000000000
--- a/src/System.Private.CoreLib/src/System/IO/Stream.cs
+++ /dev/null
@@ -1,808 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Buffers;
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace System.IO
-{
- public abstract class Stream : MarshalByRefObject, IDisposable
- {
- public static readonly Stream Null = new NullStream();
-
- //We pick a value that is the largest multiple of 4096 that is still smaller than the large object heap threshold (85K).
- // The CopyTo/CopyToAsync buffer is short-lived and is likely to be collected at Gen0, and it offers a significant
- // improvement in Copy performance.
- private const int DefaultCopyBufferSize = 81920;
-
- // To implement Async IO operations on streams that don't support async IO
-
- private SemaphoreSlim _asyncActiveSemaphore;
-
- internal SemaphoreSlim EnsureAsyncActiveSemaphoreInitialized()
- {
- // Lazily-initialize _asyncActiveSemaphore. As we're never accessing the SemaphoreSlim's
- // WaitHandle, we don't need to worry about Disposing it.
- return LazyInitializer.EnsureInitialized(ref _asyncActiveSemaphore, () => new SemaphoreSlim(1, 1));
- }
-
- public abstract bool CanRead
- {
- get;
- }
-
- // If CanSeek is false, Position, Seek, Length, and SetLength should throw.
- public abstract bool CanSeek
- {
- get;
- }
-
- public virtual bool CanTimeout
- {
- get
- {
- return false;
- }
- }
-
- public abstract bool CanWrite
- {
- get;
- }
-
- public abstract long Length
- {
- get;
- }
-
- public abstract long Position
- {
- get;
- set;
- }
-
- public virtual int ReadTimeout
- {
- get
- {
- throw new InvalidOperationException(SR.InvalidOperation_TimeoutsNotSupported);
- }
- set
- {
- throw new InvalidOperationException(SR.InvalidOperation_TimeoutsNotSupported);
- }
- }
-
- public virtual int WriteTimeout
- {
- get
- {
- throw new InvalidOperationException(SR.InvalidOperation_TimeoutsNotSupported);
- }
- set
- {
- throw new InvalidOperationException(SR.InvalidOperation_TimeoutsNotSupported);
- }
- }
-
- public Task CopyToAsync(Stream destination)
- {
- int bufferSize = GetCopyBufferSize();
-
- return CopyToAsync(destination, bufferSize);
- }
-
- public Task CopyToAsync(Stream destination, int bufferSize)
- {
- return CopyToAsync(destination, bufferSize, CancellationToken.None);
- }
-
- public Task CopyToAsync(Stream destination, CancellationToken cancellationToken)
- {
- int bufferSize = GetCopyBufferSize();
-
- return CopyToAsync(destination, bufferSize, cancellationToken);
- }
-
- public virtual Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
- {
- StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize);
-
- return CopyToAsyncInternal(destination, bufferSize, cancellationToken);
- }
-
- private async Task CopyToAsyncInternal(Stream destination, int bufferSize, CancellationToken cancellationToken)
- {
- Debug.Assert(destination != null);
- Debug.Assert(bufferSize > 0);
- Debug.Assert(CanRead);
- Debug.Assert(destination.CanWrite);
-
- byte[] buffer = new byte[bufferSize];
- while (true)
- {
- int bytesRead = await ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false);
- if (bytesRead == 0) break;
- await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
- }
- }
-
- // Reads the bytes from the current stream and writes the bytes to
- // the destination stream until all bytes are read, starting at
- // the current position.
- public void CopyTo(Stream destination)
- {
- int bufferSize = GetCopyBufferSize();
-
- CopyTo(destination, bufferSize);
- }
-
- public virtual void CopyTo(Stream destination, int bufferSize)
- {
- StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize);
-
- byte[] buffer = new byte[bufferSize];
- int read;
- while ((read = Read(buffer, 0, buffer.Length)) != 0)
- {
- destination.Write(buffer, 0, read);
- }
- }
-
- private int GetCopyBufferSize()
- {
- int bufferSize = DefaultCopyBufferSize;
-
- if (CanSeek)
- {
- long length = Length;
- long position = Position;
- if (length <= position) // Handles negative overflows
- {
- // There are no bytes left in the stream to copy.
- // However, because CopyTo{Async} is virtual, we need to
- // ensure that any override is still invoked to provide its
- // own validation, so we use the smallest legal buffer size here.
- bufferSize = 1;
- }
- else
- {
- long remaining = length - position;
- if (remaining > 0)
- {
- // In the case of a positive overflow, stick to the default size
- bufferSize = (int)Math.Min(bufferSize, remaining);
- }
- }
- }
-
- return bufferSize;
- }
-
- public virtual void Close()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- public void Dispose()
- {
- Close();
- }
-
- protected virtual void Dispose(bool disposing)
- {
- // Note: Never change this to call other virtual methods on Stream
- // like Write, since the state on subclasses has already been
- // torn down. This is the last code to run on cleanup for a stream.
- }
-
- public abstract void Flush();
-
- public Task FlushAsync()
- {
- return FlushAsync(CancellationToken.None);
- }
-
- public virtual Task FlushAsync(CancellationToken cancellationToken)
- {
- if (cancellationToken.IsCancellationRequested)
- {
- return Task.FromCanceled(cancellationToken);
- }
-
- return Task.Factory.StartNew(state => ((Stream)state).Flush(), this,
- cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
- }
-
- [Obsolete("CreateWaitHandle will be removed eventually. Please use \"new ManualResetEvent(false)\" instead.")]
- protected virtual WaitHandle CreateWaitHandle()
- {
- return new ManualResetEvent(initialState: false);
- }
-
- public Task<int> ReadAsync(Byte[] buffer, int offset, int count)
- {
- return ReadAsync(buffer, offset, count, CancellationToken.None);
- }
-
- public virtual Task<int> ReadAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
- {
- return cancellationToken.IsCancellationRequested ?
- Task.FromCanceled<int>(cancellationToken) :
- Task.Factory.FromAsync(
- (localBuffer, localOffset, localCount, callback, state) => ((Stream)state).BeginRead(localBuffer, localOffset, localCount, callback, state),
- iar => ((Stream)iar.AsyncState).EndRead(iar),
- buffer, offset, count, this);
- }
-
- public virtual ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken = default(CancellationToken))
- {
- if (MemoryMarshal.TryGetArray(destination, out ArraySegment<byte> array))
- {
- return new ValueTask<int>(ReadAsync(array.Array, array.Offset, array.Count, cancellationToken));
- }
- else
- {
- byte[] buffer = ArrayPool<byte>.Shared.Rent(destination.Length);
- return FinishReadAsync(ReadAsync(buffer, 0, destination.Length, cancellationToken), buffer, destination);
-
- async ValueTask<int> FinishReadAsync(Task<int> readTask, byte[] localBuffer, Memory<byte> localDestination)
- {
- try
- {
- int result = await readTask.ConfigureAwait(false);
- new Span<byte>(localBuffer, 0, result).CopyTo(localDestination.Span);
- return result;
- }
- finally
- {
- ArrayPool<byte>.Shared.Return(localBuffer);
- }
- }
- }
- }
-
- public virtual IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
- {
- if (!CanRead)
- {
- throw new NotSupportedException(SR.NotSupported_UnreadableStream);
- }
-
- return TaskToApm.Begin(ReadAsyncInternal(buffer, offset, count), callback, state);
- }
-
- public virtual int EndRead(IAsyncResult asyncResult) =>
- TaskToApm.End<int>(asyncResult);
-
- private Task<int> ReadAsyncInternal(Byte[] buffer, int offset, int count)
- {
- // To avoid a race with a stream's position pointer & generating race
- // conditions with internal buffer indexes in our own streams that
- // don't natively support async IO operations when there are multiple
- // async requests outstanding, we will serialize the requests.
- return EnsureAsyncActiveSemaphoreInitialized().WaitAsync().ContinueWith((completedWait, s) =>
- {
- Debug.Assert(completedWait.Status == TaskStatus.RanToCompletion);
- var state = (Tuple<Stream, byte[], int, int>)s;
- try
- {
- return state.Item1.Read(state.Item2, state.Item3, state.Item4); // this.Read(buffer, offset, count);
- }
- finally
- {
- state.Item1._asyncActiveSemaphore.Release();
- }
- }, Tuple.Create(this, buffer, offset, count), CancellationToken.None, TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default);
- }
-
- public Task WriteAsync(Byte[] buffer, int offset, int count)
- {
- return WriteAsync(buffer, offset, count, CancellationToken.None);
- }
-
- public virtual Task WriteAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
- {
- return cancellationToken.IsCancellationRequested ?
- Task.FromCanceled<int>(cancellationToken) :
- Task.Factory.FromAsync(
- (localBuffer, localOffset, localCount, callback, state) => ((Stream)state).BeginWrite(localBuffer, localOffset, localCount, callback, state),
- iar => ((Stream)iar.AsyncState).EndWrite(iar),
- buffer, offset, count, this);
- }
-
- public virtual ValueTask WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default(CancellationToken))
- {
- if (MemoryMarshal.TryGetArray(source, out ArraySegment<byte> array))
- {
- return new ValueTask(WriteAsync(array.Array, array.Offset, array.Count, cancellationToken));
- }
- else
- {
- byte[] buffer = ArrayPool<byte>.Shared.Rent(source.Length);
- source.Span.CopyTo(buffer);
- return new ValueTask(FinishWriteAsync(WriteAsync(buffer, 0, source.Length, cancellationToken), buffer));
-
- async Task FinishWriteAsync(Task writeTask, byte[] localBuffer)
- {
- try
- {
- await writeTask.ConfigureAwait(false);
- }
- finally
- {
- ArrayPool<byte>.Shared.Return(localBuffer);
- }
- }
- }
- }
-
- public virtual IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
- {
- if (!CanWrite)
- {
- throw new NotSupportedException(SR.NotSupported_UnwritableStream);
- }
-
- return TaskToApm.Begin(WriteAsyncInternal(buffer, offset, count), callback, state);
- }
-
- public virtual void EndWrite(IAsyncResult asyncResult) =>
- TaskToApm.End(asyncResult);
-
- private Task WriteAsyncInternal(Byte[] buffer, int offset, int count)
- {
- // To avoid a race with a stream's position pointer & generating race
- // conditions with internal buffer indexes in our own streams that
- // don't natively support async IO operations when there are multiple
- // async requests outstanding, we will serialize the requests.
- return EnsureAsyncActiveSemaphoreInitialized().WaitAsync().ContinueWith((completedWait, s) =>
- {
- Debug.Assert(completedWait.Status == TaskStatus.RanToCompletion);
- var state = (Tuple<Stream, byte[], int, int>)s;
- try
- {
- state.Item1.Write(state.Item2, state.Item3, state.Item4); // this.Write(buffer, offset, count);
- }
- finally
- {
- state.Item1._asyncActiveSemaphore.Release();
- }
- }, Tuple.Create(this, buffer, offset, count), CancellationToken.None, TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default);
- }
-
- public abstract long Seek(long offset, SeekOrigin origin);
-
- public abstract void SetLength(long value);
-
- public abstract int Read(byte[] buffer, int offset, int count);
-
- public virtual int Read(Span<byte> destination)
- {
- ArrayPool<byte> pool = ArrayPool<byte>.Shared;
- byte[] buffer = pool.Rent(destination.Length);
- try
- {
- int numRead = Read(buffer, 0, destination.Length);
- if ((uint)numRead > destination.Length)
- {
- throw new IOException(SR.IO_StreamTooLong);
- }
- new Span<byte>(buffer, 0, numRead).CopyTo(destination);
- return numRead;
- }
- finally { pool.Return(buffer); }
- }
-
- // Reads one byte from the stream by calling Read(byte[], int, int).
- // Will return an unsigned byte cast to an int or -1 on end of stream.
- // This implementation does not perform well because it allocates a new
- // byte[] each time you call it, and should be overridden by any
- // subclass that maintains an internal buffer. Then, it can help perf
- // significantly for people who are reading one byte at a time.
- public virtual int ReadByte()
- {
- byte[] oneByteArray = new byte[1];
- int r = Read(oneByteArray, 0, 1);
- if (r == 0)
- {
- return -1;
- }
- return oneByteArray[0];
- }
-
- public abstract void Write(byte[] buffer, int offset, int count);
-
- public virtual void Write(ReadOnlySpan<byte> source)
- {
- ArrayPool<byte> pool = ArrayPool<byte>.Shared;
- byte[] buffer = pool.Rent(source.Length);
- try
- {
- source.CopyTo(buffer);
- Write(buffer, 0, source.Length);
- }
- finally { pool.Return(buffer); }
- }
-
- // Writes one byte from the stream by calling Write(byte[], int, int).
- // This implementation does not perform well because it allocates a new
- // byte[] each time you call it, and should be overridden by any
- // subclass that maintains an internal buffer. Then, it can help perf
- // significantly for people who are writing one byte at a time.
- public virtual void WriteByte(byte value)
- {
- byte[] oneByteArray = new byte[1];
- oneByteArray[0] = value;
- Write(oneByteArray, 0, 1);
- }
-
- public static Stream Synchronized(Stream stream)
- {
- if (stream == null)
- throw new ArgumentNullException(nameof(stream));
-
- if (stream is SyncStream)
- return stream;
-
- return new SyncStream(stream);
- }
-
- [Obsolete("Do not call or override this method.")]
- protected virtual void ObjectInvariant()
- {
- }
-
- private sealed class NullStream : Stream
- {
- internal NullStream() { }
-
- public override bool CanRead => true;
-
- public override bool CanWrite => true;
-
- public override bool CanSeek => true;
-
- public override long Length => 0;
-
- public override long Position
- {
- get { return 0; }
- set { }
- }
-
- public override void CopyTo(Stream destination, int bufferSize)
- {
- StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize);
-
- // After we validate arguments this is a nop.
- }
-
- public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
- {
- // Validate arguments for compat, since previously this
- // method was inherited from Stream, which did check its arguments.
- StreamHelpers.ValidateCopyToArgs(this, destination, bufferSize);
-
- return cancellationToken.IsCancellationRequested ?
- Task.FromCanceled(cancellationToken) :
- Task.CompletedTask;
- }
-
- protected override void Dispose(bool disposing)
- {
- // Do nothing - we don't want NullStream singleton (static) to be closable
- }
-
- public override void Flush()
- {
- }
-
-#pragma warning disable 1998 // async method with no await
- public override async Task FlushAsync(CancellationToken cancellationToken)
- {
- cancellationToken.ThrowIfCancellationRequested();
- }
-#pragma warning restore 1998
-
- public override int Read(byte[] buffer, int offset, int count)
- {
- return 0;
- }
-
- public override int Read(Span<byte> destination)
- {
- return 0;
- }
-
-#pragma warning disable 1998 // async method with no await
- public override async Task<int> ReadAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
- {
- cancellationToken.ThrowIfCancellationRequested();
- return 0;
- }
-
- public override async ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken)
- {
- cancellationToken.ThrowIfCancellationRequested();
- return 0;
- }
-#pragma warning restore 1998
-
- public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) =>
- TaskToApm.Begin(ReadAsync(buffer, offset, count, CancellationToken.None), callback, state);
-
- public override int EndRead(IAsyncResult asyncResult) =>
- TaskToApm.End<int>(asyncResult);
-
- public override int ReadByte()
- {
- return -1;
- }
-
- public override void Write(byte[] buffer, int offset, int count)
- {
- }
-
- public override void Write(ReadOnlySpan<byte> source)
- {
- }
-
-#pragma warning disable 1998 // async method with no await
- public override async Task WriteAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
- {
- cancellationToken.ThrowIfCancellationRequested();
- }
-
- public override async ValueTask WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken)
- {
- cancellationToken.ThrowIfCancellationRequested();
- }
-#pragma warning restore 1998
-
- public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) =>
- TaskToApm.Begin(WriteAsync(buffer, offset, count, CancellationToken.None), callback, state);
-
- public override void EndWrite(IAsyncResult asyncResult) =>
- TaskToApm.End(asyncResult);
-
- public override void WriteByte(byte value)
- {
- }
-
- public override long Seek(long offset, SeekOrigin origin)
- {
- return 0;
- }
-
- public override void SetLength(long length)
- {
- }
- }
-
- // SyncStream is a wrapper around a stream that takes
- // a lock for every operation making it thread safe.
- private sealed class SyncStream : Stream, IDisposable
- {
- private Stream _stream;
-
- internal SyncStream(Stream stream)
- {
- if (stream == null)
- throw new ArgumentNullException(nameof(stream));
-
- _stream = stream;
- }
-
- public override bool CanRead => _stream.CanRead;
-
- public override bool CanWrite => _stream.CanWrite;
-
- public override bool CanSeek => _stream.CanSeek;
-
- public override bool CanTimeout => _stream.CanTimeout;
-
- public override long Length
- {
- get
- {
- lock (_stream)
- {
- return _stream.Length;
- }
- }
- }
-
- public override long Position
- {
- get
- {
- lock (_stream)
- {
- return _stream.Position;
- }
- }
- set
- {
- lock (_stream)
- {
- _stream.Position = value;
- }
- }
- }
-
- public override int ReadTimeout
- {
- get
- {
- return _stream.ReadTimeout;
- }
- set
- {
- _stream.ReadTimeout = value;
- }
- }
-
- public override int WriteTimeout
- {
- get
- {
- return _stream.WriteTimeout;
- }
- set
- {
- _stream.WriteTimeout = value;
- }
- }
-
- // In the off chance that some wrapped stream has different
- // semantics for Close vs. Dispose, let's preserve that.
- public override void Close()
- {
- lock (_stream)
- {
- try
- {
- _stream.Close();
- }
- finally
- {
- base.Dispose(true);
- }
- }
- }
-
- protected override void Dispose(bool disposing)
- {
- lock (_stream)
- {
- try
- {
- // Explicitly pick up a potentially methodimpl'ed Dispose
- if (disposing)
- ((IDisposable)_stream).Dispose();
- }
- finally
- {
- base.Dispose(disposing);
- }
- }
- }
-
- public override void Flush()
- {
- lock (_stream)
- _stream.Flush();
- }
-
- public override int Read(byte[] bytes, int offset, int count)
- {
- lock (_stream)
- return _stream.Read(bytes, offset, count);
- }
-
- public override int Read(Span<byte> destination)
- {
- lock (_stream)
- return _stream.Read(destination);
- }
-
- public override int ReadByte()
- {
- lock (_stream)
- return _stream.ReadByte();
- }
-
- public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)
- {
- throw new NotImplementedException(); // TODO: https://github.com/dotnet/corert/issues/3251
- //bool overridesBeginRead = _stream.HasOverriddenBeginEndRead();
-
- //lock (_stream)
- //{
- // // If the Stream does have its own BeginRead implementation, then we must use that override.
- // // If it doesn't, then we'll use the base implementation, but we'll make sure that the logic
- // // which ensures only one asynchronous operation does so with an asynchronous wait rather
- // // than a synchronous wait. A synchronous wait will result in a deadlock condition, because
- // // the EndXx method for the outstanding async operation won't be able to acquire the lock on
- // // _stream due to this call blocked while holding the lock.
- // return overridesBeginRead ?
- // _stream.BeginRead(buffer, offset, count, callback, state) :
- // _stream.BeginReadInternal(buffer, offset, count, callback, state, serializeAsynchronously: true, apm: true);
- //}
- }
-
- public override int EndRead(IAsyncResult asyncResult)
- {
- if (asyncResult == null)
- throw new ArgumentNullException(nameof(asyncResult));
-
- lock (_stream)
- return _stream.EndRead(asyncResult);
- }
-
- public override long Seek(long offset, SeekOrigin origin)
- {
- lock (_stream)
- return _stream.Seek(offset, origin);
- }
-
- public override void SetLength(long length)
- {
- lock (_stream)
- _stream.SetLength(length);
- }
-
- public override void Write(byte[] bytes, int offset, int count)
- {
- lock (_stream)
- _stream.Write(bytes, offset, count);
- }
-
- public override void Write(ReadOnlySpan<byte> source)
- {
- lock (_stream)
- _stream.Write(source);
- }
-
- public override void WriteByte(byte b)
- {
- lock (_stream)
- _stream.WriteByte(b);
- }
-
- public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)
- {
- throw new NotImplementedException(); // TODO: https://github.com/dotnet/corert/issues/3251
- //bool overridesBeginWrite = _stream.HasOverriddenBeginEndWrite();
-
- //lock (_stream)
- //{
- // // If the Stream does have its own BeginWrite implementation, then we must use that override.
- // // If it doesn't, then we'll use the base implementation, but we'll make sure that the logic
- // // which ensures only one asynchronous operation does so with an asynchronous wait rather
- // // than a synchronous wait. A synchronous wait will result in a deadlock condition, because
- // // the EndXx method for the outstanding async operation won't be able to acquire the lock on
- // // _stream due to this call blocked while holding the lock.
- // return overridesBeginWrite ?
- // _stream.BeginWrite(buffer, offset, count, callback, state) :
- // _stream.BeginWriteInternal(buffer, offset, count, callback, state, serializeAsynchronously: true, apm: true);
- //}
- }
-
- public override void EndWrite(IAsyncResult asyncResult)
- {
- if (asyncResult == null)
- throw new ArgumentNullException(nameof(asyncResult));
-
- lock (_stream)
- _stream.EndWrite(asyncResult);
- }
- }
- }
-}
diff --git a/src/System.Private.CoreLib/src/System/InvokeUtils.cs b/src/System.Private.CoreLib/src/System/InvokeUtils.cs
index 69435aee9..0a66ea6c2 100644
--- a/src/System.Private.CoreLib/src/System/InvokeUtils.cs
+++ b/src/System.Private.CoreLib/src/System/InvokeUtils.cs
@@ -12,6 +12,8 @@ using Internal.Reflection.Core.NonPortable;
using Internal.Runtime.Augments;
using Internal.Runtime.CompilerServices;
+using Interlocked = System.Threading.Interlocked;
+
namespace System
{
[System.Runtime.CompilerServices.ReflectionBlocked]
@@ -39,7 +41,7 @@ namespace System
// This method is targeted by the Delegate ILTransformer.
//
//
- public static Object CheckArgument(Object srcObject, RuntimeTypeHandle dstType, BinderBundle binderBundle)
+ public static object CheckArgument(object srcObject, RuntimeTypeHandle dstType, BinderBundle binderBundle)
{
EETypePtr dstEEType = dstType.ToEETypePtr();
return CheckArgument(srcObject, dstEEType, CheckArgumentSemantics.DynamicInvoke, binderBundle, getExactTypeForCustomBinder: null);
@@ -53,12 +55,16 @@ namespace System
SetFieldDirect, // Throws ArgumentException - other than that, like DynamicInvoke except that enums and integers cannot be intermingled, and null cannot substitute for default(valuetype).
}
- internal static Object CheckArgument(Object srcObject, EETypePtr dstEEType, CheckArgumentSemantics semantics, BinderBundle binderBundle, Func<Type> getExactTypeForCustomBinder = null)
+ internal static object CheckArgument(object srcObject, EETypePtr dstEEType, CheckArgumentSemantics semantics, BinderBundle binderBundle, Func<Type> getExactTypeForCustomBinder = null)
{
if (srcObject == null)
{
// null -> default(T)
- if (dstEEType.IsValueType && !dstEEType.IsNullable)
+ if (dstEEType.IsPointer)
+ {
+ return default(IntPtr);
+ }
+ else if (dstEEType.IsValueType && !dstEEType.IsNullable)
{
if (semantics == CheckArgumentSemantics.SetFieldDirect)
throw CreateChangeTypeException(CommonRuntimeTypes.Object.TypeHandle.ToEETypePtr(), dstEEType, semantics);
@@ -412,9 +418,9 @@ namespace System
s_curIndex = 0;
s_targetMethodOrDelegate = targetMethodOrDelegate;
+ object result;
try
{
- object result = null;
if (invokeMethodHelperIsThisCall)
{
Debug.Assert(methodToCallIsThisCall == true);
@@ -434,8 +440,6 @@ namespace System
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
}
}
-
- return result;
}
catch (Exception e) when (wrapInTargetInvocationException && argSetupState.fComplete)
{
@@ -464,6 +468,11 @@ namespace System
}
}
}
+
+ if (result == NullByRefValueSentinel)
+ throw new NullReferenceException(SR.NullReference_InvokeNullRefReturned);
+
+ return result;
}
finally
{
@@ -730,6 +739,15 @@ namespace System
return finalObjectToReturn;
}
+ internal static object DynamicInvokeUnmanagedPointerReturn(out DynamicInvokeParamLookupType paramLookupType, object boxedPointerType, int index, RuntimeTypeHandle type, DynamicInvokeParamType paramType)
+ {
+ object finalObjectToReturn = boxedPointerType;
+
+ Debug.Assert(finalObjectToReturn is IntPtr);
+ paramLookupType = DynamicInvokeParamLookupType.ValuetypeObjectReturned;
+ return finalObjectToReturn;
+ }
+
public static object DynamicInvokeParamHelperCore(RuntimeTypeHandle type, out DynamicInvokeParamLookupType paramLookupType, out int index, DynamicInvokeParamType paramType)
{
index = s_curIndex++;
@@ -790,17 +808,22 @@ namespace System
incomingParam = InvokeUtils.CheckArgument(incomingParam, type.ToEETypePtr(), InvokeUtils.CheckArgumentSemantics.DynamicInvoke, s_binderBundle, s_getExactTypeForCustomBinder);
if (s_binderBundle == null)
{
- System.Diagnostics.Debug.Assert(s_parameters[index] == null || Object.ReferenceEquals(incomingParam, s_parameters[index]));
+ System.Diagnostics.Debug.Assert(s_parameters[index] == null || object.ReferenceEquals(incomingParam, s_parameters[index]));
}
return DynamicInvokeBoxedValuetypeReturn(out paramLookupType, incomingParam, index, type, paramType);
}
+ else if (type.ToEETypePtr().IsPointer)
+ {
+ incomingParam = InvokeUtils.CheckArgument(incomingParam, type.ToEETypePtr(), InvokeUtils.CheckArgumentSemantics.DynamicInvoke, s_binderBundle, s_getExactTypeForCustomBinder);
+ return DynamicInvokeUnmanagedPointerReturn(out paramLookupType, incomingParam, index, type, paramType);
+ }
else
{
incomingParam = InvokeUtils.CheckArgument(incomingParam, widenAndCompareType.ToEETypePtr(), InvokeUtils.CheckArgumentSemantics.DynamicInvoke, s_binderBundle, s_getExactTypeForCustomBinder);
paramLookupType = DynamicInvokeParamLookupType.IndexIntoObjectArrayReturned;
if (s_binderBundle == null)
{
- System.Diagnostics.Debug.Assert(Object.ReferenceEquals(incomingParam, s_parameters[index]));
+ System.Diagnostics.Debug.Assert(object.ReferenceEquals(incomingParam, s_parameters[index]));
return s_parameters;
}
else
@@ -833,6 +856,19 @@ namespace System
}
}
}
+
+ private static volatile object _nullByRefValueSentinel;
+ public static object NullByRefValueSentinel
+ {
+ get
+ {
+ if (_nullByRefValueSentinel == null)
+ {
+ Interlocked.CompareExchange(ref _nullByRefValueSentinel, new object(), null);
+ }
+ return _nullByRefValueSentinel;
+ }
+ }
}
}
diff --git a/src/System.Private.CoreLib/src/System/MissingMemberException.CoreRT.cs b/src/System.Private.CoreLib/src/System/MissingMemberException.CoreRT.cs
new file mode 100644
index 000000000..f79f086b8
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/MissingMemberException.CoreRT.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.Serialization;
+
+namespace System
+{
+ public partial class MissingMemberException : MemberAccessException
+ {
+ internal static string FormatSignature(byte[] signature)
+ {
+ // This is not the correct implementation, however, it's probably not worth the time to port given that
+ // (1) it's for a diagnostic
+ // (2) Signature is non-null when this exception is created from the native runtime. Which we don't do in .Net Native.
+ // (3) Only other time the signature is non-null is if this exception object is deserialized from a persisted blob from an older runtime.
+ return string.Empty;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/System.Private.CoreLib/src/System/MulticastDelegate.cs b/src/System.Private.CoreLib/src/System/MulticastDelegate.cs
index a3a23e67a..6ab876421 100644
--- a/src/System.Private.CoreLib/src/System/MulticastDelegate.cs
+++ b/src/System.Private.CoreLib/src/System/MulticastDelegate.cs
@@ -18,7 +18,7 @@ namespace System
internal MulticastDelegate() { }
// V1 API: Create closed instance delegates. Method name matching is case sensitive.
- protected MulticastDelegate(Object target, String method)
+ protected MulticastDelegate(object target, string method)
{
// This constructor cannot be used by application code. To create a delegate by specifying the name of a method, an
// overload of the public static CreateDelegate method is used. This will eventually end up calling into the internal
@@ -28,7 +28,7 @@ namespace System
}
// V1 API: Create open static delegates. Method name matching is case insensitive.
- protected MulticastDelegate(Type target, String method)
+ protected MulticastDelegate(Type target, string method)
{
// This constructor cannot be used by application code. To create a delegate by specifying the name of a method, an
// overload of the public static CreateDelegate method is used. This will eventually end up calling into the internal
@@ -54,7 +54,7 @@ namespace System
return true;
}
- public override sealed bool Equals(Object obj)
+ public override sealed bool Equals(object obj)
{
if (obj == null)
return false;
@@ -79,7 +79,7 @@ namespace System
}
else
{
- if (!Object.ReferenceEquals(m_helperObject, d.m_helperObject) ||
+ if (!object.ReferenceEquals(m_helperObject, d.m_helperObject) ||
(!FunctionPointerOps.Compare(m_extraFunctionPointerOrData, d.m_extraFunctionPointerOrData)) ||
(!FunctionPointerOps.Compare(m_functionPointer, d.m_functionPointer)))
{
@@ -88,12 +88,12 @@ namespace System
// Those delegate kinds with thunks put themselves into the m_firstParamter, so we can't
// blindly compare the m_firstParameter fields for equality.
- if (Object.ReferenceEquals(m_firstParameter, this))
+ if (object.ReferenceEquals(m_firstParameter, this))
{
- return Object.ReferenceEquals(d.m_firstParameter, d);
+ return object.ReferenceEquals(d.m_firstParameter, d);
}
- return Object.ReferenceEquals(m_firstParameter, d.m_firstParameter);
+ return object.ReferenceEquals(m_firstParameter, d.m_firstParameter);
}
}
diff --git a/src/System.Private.CoreLib/src/System/Number.CoreRT.cs b/src/System.Private.CoreLib/src/System/Number.CoreRT.cs
index 1c7fdadce..7cfc5899d 100644
--- a/src/System.Private.CoreLib/src/System/Number.CoreRT.cs
+++ b/src/System.Private.CoreLib/src/System/Number.CoreRT.cs
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System.Globalization;
-using System.Text;
namespace System
{
@@ -283,112 +282,6 @@ namespace System
{
private const int _CVTBUFSIZE = 349;
- public static bool IsPositiveInfinity(string s, IFormatProvider provider)
- {
- NumberFormatInfo nfi = provider == null ? NumberFormatInfo.CurrentInfo : NumberFormatInfo.GetInstance(provider);
- return s.Equals(nfi.PositiveInfinitySymbol);
- }
-
- public static bool IsNegativeInfinity(string s, IFormatProvider provider)
- {
- NumberFormatInfo nfi = provider == null ? NumberFormatInfo.CurrentInfo : NumberFormatInfo.GetInstance(provider);
- return s.Equals(nfi.NegativeInfinitySymbol);
- }
-
- public static bool IsNaNSymbol(string s, IFormatProvider provider)
- {
- NumberFormatInfo nfi = provider == null ? NumberFormatInfo.CurrentInfo : NumberFormatInfo.GetInstance(provider);
- return s.Equals(nfi.NaNSymbol);
- }
-
- #region Decimal Number Formatting Helpers
- private static unsafe bool NumberBufferToDecimal(ref Number.NumberBuffer number, ref Decimal value)
- {
- Decimal d = new Decimal();
-
- char* p = number.digits;
- int e = number.scale;
- if (*p == 0)
- {
- // To avoid risking an app-compat issue with pre 4.5 (where some app was illegally using Reflection to examine the internal scale bits), we'll only force
- // the scale to 0 if the scale was previously positive (previously, such cases were unparsable to a bug.)
- if (e > 0)
- {
- e = 0;
- }
- }
- else
- {
- if (e > DecimalPrecision)
- return false;
-
- while (((e > 0) || ((*p != 0) && (e > -28))) &&
- ((d.High < 0x19999999) || ((d.High == 0x19999999) &&
- ((d.Mid < 0x99999999) || ((d.Mid == 0x99999999) &&
- ((d.Low < 0x99999999) || ((d.Low == 0x99999999) &&
- (*p <= '5'))))))))
- {
- Decimal.DecMul10(ref d);
- if (*p != 0)
- Decimal.DecAddInt32(ref d, (uint)(*p++ - '0'));
- e--;
- }
-
- if (*p++ >= '5')
- {
- bool round = true;
- if ((*(p - 1) == '5') && ((*(p - 2) % 2) == 0))
- {
- // Check if previous digit is even, only if the when we are unsure whether hows to do
- // Banker's rounding. For digits > 5 we will be roundinp up anyway.
- int count = 20; // Look at the next 20 digits to check to round
- while ((*p == '0') && (count != 0))
- {
- p++;
- count--;
- }
- if ((*p == '\0') || (count == 0))
- round = false;// Do nothing
- }
-
- if (round)
- {
- Decimal.DecAddInt32(ref d, 1);
- if ((d.High | d.Mid | d.Low) == 0)
- {
- d.High = 0x19999999;
- d.Mid = 0x99999999;
- d.Low = 0x9999999A;
- e++;
- }
- }
- }
- }
-
- if (e > 0)
- return false;
-
- if (e <= -DecimalPrecision)
- {
- // Parsing a large scale zero can give you more precision than fits in the decimal.
- // This should only happen for actual zeros or very small numbers that round to zero.
- d.High = 0;
- d.Low = 0;
- d.Mid = 0;
- d.Scale = DecimalPrecision - 1;
- }
- else
- {
- d.Scale = -e;
- }
- d.IsNegative = number.sign;
-
- value = d;
- return true;
- }
-
- #endregion
-
/*===========================================================
Portable NumberToDouble implementation
--------------------------------------
diff --git a/src/System.Private.CoreLib/src/System/Number.Unix.cs b/src/System.Private.CoreLib/src/System/Number.Unix.cs
index 19cb02135..39e2dfcb1 100644
--- a/src/System.Private.CoreLib/src/System/Number.Unix.cs
+++ b/src/System.Private.CoreLib/src/System/Number.Unix.cs
@@ -30,14 +30,9 @@ namespace System
char* dst = number.digits;
number.scale = 0;
- number.sign = false;
+ number.sign = double.IsNegative(value);
*dst = '\0';
- if (value < 0.0)
- {
- number.sign = true;
- }
-
if (value == 0.0)
{
for (int j = 0; j < precision; j++)
diff --git a/src/System.Private.CoreLib/src/System/Object.cs b/src/System.Private.CoreLib/src/System/Object.cs
index 17a2f99cf..ffe36ea88 100644
--- a/src/System.Private.CoreLib/src/System/Object.cs
+++ b/src/System.Private.CoreLib/src/System/Object.cs
@@ -80,7 +80,7 @@ namespace System
return RuntimeTypeUnifier.GetRuntimeTypeForEEType(EETypePtr);
}
- public virtual String ToString()
+ public virtual string ToString()
{
return GetType().ToString();
}
@@ -90,7 +90,7 @@ namespace System
// For Value Types, the toolchain (will) generate a ValueType.Equals override method,
// and will not be using this routine.
- public virtual bool Equals(Object obj)
+ public virtual bool Equals(object obj)
{
if (this == obj)
return true;
@@ -102,7 +102,7 @@ namespace System
return false;
}
- public static bool Equals(Object objA, Object objB)
+ public static bool Equals(object objA, object objB)
{
if (objA == objB)
{
@@ -116,7 +116,7 @@ namespace System
}
//[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
- public static bool ReferenceEquals(Object objA, Object objB)
+ public static bool ReferenceEquals(object objA, object objB)
{
return objA == objB;
}
diff --git a/src/System.Private.CoreLib/src/System/PrimitivesRuntimeContracts.cs b/src/System.Private.CoreLib/src/System/PrimitivesRuntimeContracts.cs
deleted file mode 100644
index b0ca615fe..000000000
--- a/src/System.Private.CoreLib/src/System/PrimitivesRuntimeContracts.cs
+++ /dev/null
@@ -1,409 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-
-// This file contains the basic primitive type definitions (int etc)
-// These types are well known to the compiler and the runtime and are basic interchange types that do not change
-
-// CONTRACT with Runtime
-// Each of the data types has a data contract with the runtime. See the contract in the type definition
-//
-
-using System.Runtime.InteropServices;
-using System.Runtime.CompilerServices;
-
-namespace System
-{
- // CONTRACT with Runtime
- // Place holder type for type hierarchy, Compiler/Runtime requires this class
- public abstract class ValueType
- {
- }
-
- // CONTRACT with Runtime, Compiler/Runtime requires this class
- // Place holder type for type hierarchy
- public abstract class Enum : ValueType
- {
- }
-
- /*============================================================
- **
- ** Class: Boolean
- **
- **
- ** Purpose: The boolean class serves as a wrapper for the primitive
- ** type boolean.
- **
- **
- ===========================================================*/
-
- // CONTRACT with Runtime
- // The Boolean type is one of the primitives understood by the compilers and runtime
- // Data Contract: Single field of type bool
-
- public struct Boolean
- {
- private bool m_value;
- }
-
-
- /*============================================================
- **
- ** Class: Char
- **
- **
- ** Purpose: This is the value class representing a Unicode character
- **
- **
- ===========================================================*/
-
-
-
- // CONTRACT with Runtime
- // The Char type is one of the primitives understood by the compilers and runtime
- // Data Contract: Single field of type char
- // This type is LayoutKind Sequential
-
- [StructLayout(LayoutKind.Sequential)]
- public struct Char
- {
- private char m_value;
- }
-
-
- /*============================================================
- **
- ** Class: SByte
- **
- **
- ** Purpose: A representation of a 8 bit 2's complement integer.
- **
- **
- ===========================================================*/
-
- // CONTRACT with Runtime
- // The SByte type is one of the primitives understood by the compilers and runtime
- // Data Contract: Single field of type sbyte
- // This type is LayoutKind Sequential
-
- [StructLayout(LayoutKind.Sequential)]
- public struct SByte
- {
- private sbyte m_value;
- }
-
-
- /*============================================================
- **
- ** Class: Byte
- **
- **
- ** Purpose: A representation of a 8 bit integer (byte)
- **
- **
- ===========================================================*/
-
-
- // CONTRACT with Runtime
- // The Byte type is one of the primitives understood by the compilers and runtime
- // Data Contract: Single field of type bool
- // This type is LayoutKind Sequential
-
- [StructLayout(LayoutKind.Sequential)]
- public struct Byte
- {
- private byte m_value;
- }
-
-
- /*============================================================
- **
- ** Class: Int16
- **
- **
- ** Purpose: A representation of a 16 bit 2's complement integer.
- **
- **
- ===========================================================*/
-
-
- // CONTRACT with Runtime
- // The Int16 type is one of the primitives understood by the compilers and runtime
- // Data Contract: Single field of type short
- // This type is LayoutKind Sequential
-
- [StructLayout(LayoutKind.Sequential)]
- public struct Int16
- {
- private short m_value;
- }
-
- /*============================================================
- **
- ** Class: UInt16
- **
- **
- ** Purpose: A representation of a short (unsigned 16-bit) integer.
- **
- **
- ===========================================================*/
-
- // CONTRACT with Runtime
- // The Uint16 type is one of the primitives understood by the compilers and runtime
- // Data Contract: Single field of type ushort
- // This type is LayoutKind Sequential
-
- [StructLayout(LayoutKind.Sequential)]
- public struct UInt16
- {
- private ushort m_value;
- }
-
- /*============================================================
- **
- ** Class: Int32
- **
- **
- ** Purpose: A representation of a 32 bit 2's complement integer.
- **
- **
- ===========================================================*/
-
- // CONTRACT with Runtime
- // The Int32 type is one of the primitives understood by the compilers and runtime
- // Data Contract: Single field of type int
- // This type is LayoutKind Sequential
-
- [StructLayout(LayoutKind.Sequential)]
- public struct Int32
- {
- private int m_value;
- }
-
-
- /*============================================================
- **
- ** Class: UInt32
- **
- **
- ** Purpose: A representation of a 32 bit unsigned integer.
- **
- **
- ===========================================================*/
-
- // CONTRACT with Runtime
- // The Uint32 type is one of the primitives understood by the compilers and runtime
- // Data Contract: Single field of type uint
- // This type is LayoutKind Sequential
-
- [StructLayout(LayoutKind.Sequential)]
- public struct UInt32
- {
- private uint m_value;
- }
-
-
- /*============================================================
- **
- ** Class: Int64
- **
- **
- ** Purpose: A representation of a 64 bit 2's complement integer.
- **
- **
- ===========================================================*/
-
- // CONTRACT with Runtime
- // The Int64 type is one of the primitives understood by the compilers and runtime
- // Data Contract: Single field of type long
- // This type is LayoutKind Sequential
-
- [StructLayout(LayoutKind.Sequential)]
- public struct Int64
- {
- private long m_value;
- }
-
-
- /*============================================================
- **
- ** Class: UInt64
- **
- **
- ** Purpose: A representation of a 64 bit unsigned integer.
- **
- **
- ===========================================================*/
-
- // CONTRACT with Runtime
- // The UInt64 type is one of the primitives understood by the compilers and runtime
- // Data Contract: Single field of type ulong
- // This type is LayoutKind Sequential
-
- [StructLayout(LayoutKind.Sequential)]
- public struct UInt64
- {
- private ulong m_value;
- }
-
-
- /*============================================================
- **
- ** Class: Single
- **
- **
- ** Purpose: A wrapper class for the primitive type float.
- **
- **
- ===========================================================*/
-
- // CONTRACT with Runtime
- // The Single type is one of the primitives understood by the compilers and runtime
- // Data Contract: Single field of type float
- // This type is LayoutKind Sequential
-
- [StructLayout(LayoutKind.Sequential)]
- public struct Single
- {
- private float m_value;
- }
-
-
- /*============================================================
- **
- ** Class: Double
- **
- **
- ** Purpose: A representation of an IEEE double precision
- ** floating point number.
- **
- **
- ===========================================================*/
-
- // CONTRACT with Runtime
- // The Double type is one of the primitives understood by the compilers and runtime
- // Data Contract: Single field of type double
- // This type is LayoutKind Sequential
-
- [StructLayout(LayoutKind.Sequential)]
- public struct Double
- {
- private double m_value;
- }
-
-
-
- /*============================================================
- **
- ** Class: IntPtr
- **
- **
- ** Purpose: Platform independent integer
- **
- **
- ===========================================================*/
-
- // CONTRACT with Runtime
- // The IntPtr type is one of the primitives understood by the compilers and runtime
- // Data Contract: Single field of type void *
-
- // This type implements == without overriding GetHashCode, disable compiler warning
-#pragma warning disable 0659, 0661
- public struct IntPtr
- {
- unsafe private void* m_value; // The compiler treats void* closest to uint hence explicit casts are required to preserve int behavior
-
- public static readonly IntPtr Zero;
-
- public unsafe IntPtr(void* value)
- {
- m_value = value;
- }
-
- public unsafe IntPtr(long value)
- {
-#if BIT64
- m_value = (void*)value;
-#else
- m_value = (void*)checked((int)value);
-#endif
- }
-
- public unsafe override bool Equals(Object obj)
- {
- if (obj is IntPtr)
- {
- return (m_value == ((IntPtr)obj).m_value);
- }
- return false;
- }
-
- public unsafe bool Equals(IntPtr obj)
- {
- return (m_value == obj.m_value);
- }
-
- public static unsafe explicit operator IntPtr(void* value)
- {
- return new IntPtr(value);
- }
-
- public static unsafe explicit operator long (IntPtr value)
- {
-#if BIT64
- return (long)value.m_value;
-#else
- return (long)(int)value.m_value;
-#endif
- }
-
- public static unsafe bool operator ==(IntPtr value1, IntPtr value2)
- {
- return value1.m_value == value2.m_value;
- }
-
- public static unsafe bool operator !=(IntPtr value1, IntPtr value2)
- {
- return value1.m_value != value2.m_value;
- }
-
- public unsafe void* ToPointer()
- {
- return m_value;
- }
- }
-#pragma warning restore 0659, 0661
-
-
- /*============================================================
- **
- ** Class: UIntPtr
- **
- **
- ** Purpose: Platform independent integer
- **
- **
- ===========================================================*/
-
- // CONTRACT with Runtime
- // The UIntPtr type is one of the primitives understood by the compilers and runtime
- // Data Contract: Single field of type void *
-
- public struct UIntPtr
- {
- // Disable compile warning about unused m_value field
-#pragma warning disable 0169
- unsafe private void* m_value;
-#pragma warning restore 0169
-
- public static readonly UIntPtr Zero;
- }
-
- // Decimal class is not supported in RH. Only here to keep compiler happy
- [TypeNeededIn(TypeNeededInOptions.SOURCE)]
- internal struct Decimal
- {
- }
-}
-
diff --git a/src/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs b/src/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs
index 3dadda396..34b2fbcc3 100644
--- a/src/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs
+++ b/src/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs
@@ -6,16 +6,27 @@ using System.Globalization;
using System.Runtime.Serialization;
using System.Configuration.Assemblies;
-using Internal.Reflection.Augments;
-
namespace System.Reflection
{
public sealed class AssemblyName : ICloneable, IDeserializationCallback, ISerializable
{
+ private string _name;
+ private byte[] _publicKey;
+ private byte[] _publicKeyToken;
+ private CultureInfo _cultureInfo;
+ private string _codeBase;
+ private Version _version;
+
+ private StrongNameKeyPair _strongNameKeyPair;
+ private AssemblyHashAlgorithm _hashAlgorithm;
+
+ private AssemblyVersionCompatibility _versionCompatibility;
+ private AssemblyNameFlags _flags;
+
public AssemblyName()
{
- HashAlgorithm = AssemblyHashAlgorithm.None;
- VersionCompatibility = AssemblyVersionCompatibility.SameMachine;
+ _hashAlgorithm = AssemblyHashAlgorithm.None;
+ _versionCompatibility = AssemblyVersionCompatibility.SameMachine;
_flags = AssemblyNameFlags.None;
}
@@ -28,19 +39,55 @@ namespace System.Reflection
runtimeAssemblyName.CopyToAssemblyName(this);
}
- public object Clone()
+ // Set and get the name of the assembly. If this is a weak Name
+ // then it optionally contains a site. For strong assembly names,
+ // the name partitions up the strong name's namespace
+ public string Name
{
- AssemblyName n = new AssemblyName();
- n.Name = Name;
- n._publicKey = (byte[])_publicKey?.Clone();
- n._publicKeyToken = (byte[])_publicKeyToken?.Clone();
- n.CultureInfo = CultureInfo;
- n.Version = (Version)Version?.Clone();
- n._flags = _flags;
- n.CodeBase = CodeBase;
- n.HashAlgorithm = HashAlgorithm;
- n.VersionCompatibility = VersionCompatibility;
- return n;
+ get { return _name; }
+ set { _name = value; }
+ }
+
+ public Version Version
+ {
+ get { return _version; }
+ set { _version = value; }
+ }
+
+ // Locales, internally the LCID is used for the match.
+ public CultureInfo CultureInfo
+ {
+ get { return _cultureInfo; }
+ set { _cultureInfo = value; }
+ }
+
+ public string CultureName
+ {
+ get
+ {
+ return (_cultureInfo == null) ? null : _cultureInfo.Name;
+ }
+ set
+ {
+ _cultureInfo = (value == null) ? null : new CultureInfo(value);
+ }
+ }
+
+ public string CodeBase
+ {
+ get { return _codeBase; }
+ set { _codeBase = value; }
+ }
+
+ public string EscapedCodeBase
+ {
+ get
+ {
+ if (_codeBase == null)
+ return null;
+ else
+ return EscapeCodeBase(_codeBase);
+ }
}
public ProcessorArchitecture ProcessorArchitecture
@@ -83,85 +130,105 @@ namespace System.Reflection
}
}
- public string CultureName
+ // Make a copy of this assembly name.
+ public object Clone()
{
- get
- {
- return CultureInfo?.Name;
- }
- set
- {
- CultureInfo = (value == null) ? null : new CultureInfo(value);
- }
+ AssemblyName name = new AssemblyName();
+ name._name = _name;
+ name._publicKey = (byte[])_publicKey?.Clone();
+ name._publicKeyToken = (byte[])_publicKeyToken?.Clone();
+ name._cultureInfo = _cultureInfo;
+ name._version = (Version)_version?.Clone();
+ name._flags = _flags;
+ name._codeBase = _codeBase;
+ name._hashAlgorithm = _hashAlgorithm;
+ name._versionCompatibility = _versionCompatibility;
+ return name;
}
- public CultureInfo CultureInfo { get; set; }
+ public static AssemblyName GetAssemblyName(string assemblyFile)
+ {
+ throw new PlatformNotSupportedException(SR.Arg_PlatformNotSupported_AssemblyName_GetAssemblyName);
+ }
- public AssemblyNameFlags Flags
+ // The public key that is used to verify an assemblies
+ // inclusion into the namespace. If the public key associated
+ // with the namespace cannot verify the assembly the assembly
+ // will fail to load.
+ public byte[] GetPublicKey()
{
- get { return (AssemblyNameFlags)((uint)_flags & 0xFFFFF10F); }
- set
- {
- _flags &= unchecked((AssemblyNameFlags)0x00000EF0);
- _flags |= (value & unchecked((AssemblyNameFlags)0xFFFFF10F));
- }
+ return _publicKey;
}
- public string FullName
+ public void SetPublicKey(byte[] publicKey)
{
- get
- {
- if (this.Name == null)
- return string.Empty;
- // Do not call GetPublicKeyToken() here - that latches the result into AssemblyName which isn't a side effect we want.
- byte[] pkt = _publicKeyToken ?? AssemblyNameHelpers.ComputePublicKeyToken(_publicKey);
- return AssemblyNameFormatter.ComputeDisplayName(Name, Version, CultureName, pkt, Flags, ContentType);
- }
+ _publicKey = publicKey;
+
+ if (publicKey == null)
+ _flags &= ~AssemblyNameFlags.PublicKey;
+ else
+ _flags |= AssemblyNameFlags.PublicKey;
}
- public string Name { get; set; }
- public Version Version { get; set; }
- public string CodeBase { get; set; }
- public AssemblyHashAlgorithm HashAlgorithm { get; set; }
- public AssemblyVersionCompatibility VersionCompatibility { get; set; }
- public StrongNameKeyPair KeyPair { get; set; }
+ // The compressed version of the public key formed from a truncated hash.
+ // Will throw a SecurityException if _PublicKey is invalid
+ public byte[] GetPublicKeyToken()
+ {
+ if (_publicKeyToken == null)
+ _publicKeyToken = AssemblyNameHelpers.ComputePublicKeyToken(_publicKey);
+ return _publicKeyToken;
+ }
- public string EscapedCodeBase
+ public void SetPublicKeyToken(byte[] publicKeyToken)
{
- get
+ _publicKeyToken = publicKeyToken;
+ }
+
+ // Flags modifying the name. So far the only flag is PublicKey, which
+ // indicates that a full public key and not the compressed version is
+ // present.
+ // Processor Architecture flags are set only through ProcessorArchitecture
+ // property and can't be set or retrieved directly
+ // Content Type flags are set only through ContentType property and can't be
+ // set or retrieved directly
+ public AssemblyNameFlags Flags
+ {
+ get { return (AssemblyNameFlags)((uint)_flags & 0xFFFFF10F); }
+ set
{
- if (CodeBase == null)
- return null;
- else
- return EscapeCodeBase(CodeBase);
+ _flags &= unchecked((AssemblyNameFlags)0x00000EF0);
+ _flags |= (value & unchecked((AssemblyNameFlags)0xFFFFF10F));
}
}
- public byte[] GetPublicKey()
+ public AssemblyHashAlgorithm HashAlgorithm
{
- return _publicKey;
+ get { return _hashAlgorithm; }
+ set { _hashAlgorithm = value; }
}
- public byte[] GetPublicKeyToken()
+ public AssemblyVersionCompatibility VersionCompatibility
{
- if (_publicKeyToken == null)
- _publicKeyToken = AssemblyNameHelpers.ComputePublicKeyToken(_publicKey);
- return _publicKeyToken;
+ get { return _versionCompatibility; }
+ set { _versionCompatibility = value; }
}
- public void SetPublicKey(byte[] publicKey)
+ public StrongNameKeyPair KeyPair
{
- _publicKey = publicKey;
-
- if (publicKey == null)
- _flags &= ~AssemblyNameFlags.PublicKey;
- else
- _flags |= AssemblyNameFlags.PublicKey;
+ get { return _strongNameKeyPair; }
+ set { _strongNameKeyPair = value; }
}
- public void SetPublicKeyToken(byte[] publicKeyToken)
+ public string FullName
{
- _publicKeyToken = publicKeyToken;
+ get
+ {
+ if (this.Name == null)
+ return string.Empty;
+ // Do not call GetPublicKeyToken() here - that latches the result into AssemblyName which isn't a side effect we want.
+ byte[] pkt = _publicKeyToken ?? AssemblyNameHelpers.ComputePublicKeyToken(_publicKey);
+ return AssemblyNameFormatter.ComputeDisplayName(Name, Version, CultureName, pkt, Flags, ContentType);
+ }
}
public override string ToString()
@@ -183,11 +250,6 @@ namespace System.Reflection
throw new PlatformNotSupportedException();
}
- public static AssemblyName GetAssemblyName(string assemblyFile)
- {
- throw new PlatformNotSupportedException(SR.Arg_PlatformNotSupported_AssemblyName_GetAssemblyName);
- }
-
/// <summary>
/// Compares the simple names disregarding Version, Culture and PKT. While this clearly does not
/// match the intent of this api, this api has been broken this way since its debut and we cannot
@@ -210,10 +272,6 @@ namespace System.Reflection
}
internal static string EscapeCodeBase(string codebase) { throw new PlatformNotSupportedException(); }
-
- private AssemblyNameFlags _flags;
- private byte[] _publicKey;
- private byte[] _publicKeyToken;
}
}
diff --git a/src/System.Private.CoreLib/src/System/Reflection/AssemblyNameLexer.cs b/src/System.Private.CoreLib/src/System/Reflection/AssemblyNameLexer.cs
index 4838e5d5d..9b4571493 100644
--- a/src/System.Private.CoreLib/src/System/Reflection/AssemblyNameLexer.cs
+++ b/src/System.Private.CoreLib/src/System/Reflection/AssemblyNameLexer.cs
@@ -16,7 +16,7 @@ namespace System.Reflection
//
internal struct AssemblyNameLexer
{
- internal AssemblyNameLexer(String s)
+ internal AssemblyNameLexer(string s)
{
// Convert string to char[] with NUL terminator. (An actual NUL terminator in the input string will be treated
// as an actual end of string: this is compatible with desktop behavior.)
@@ -32,7 +32,7 @@ namespace System.Reflection
//
internal Token GetNext()
{
- String ignore;
+ string ignore;
return GetNext(out ignore);
}
@@ -40,10 +40,10 @@ namespace System.Reflection
// Return the next token in assembly name. If the result is DisplayNameToken.String,
// sets "tokenString" to the tokenized string.
//
- internal Token GetNext(out String tokenString)
+ internal Token GetNext(out string tokenString)
{
tokenString = null;
- while (Char.IsWhiteSpace(_chars[_index]))
+ while (char.IsWhiteSpace(_chars[_index]))
_index++;
char c = _chars[_index++];
@@ -87,7 +87,7 @@ namespace System.Reflection
{
c = _chars[_index++];
bool matched = false;
- foreach (KeyValuePair<char, String> kv in AssemblyNameFormatter.EscapeSequences)
+ foreach (KeyValuePair<char, string> kv in AssemblyNameFormatter.EscapeSequences)
{
if (c == kv.Key)
{
diff --git a/src/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs b/src/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs
index f963e0323..8ace065fc 100644
--- a/src/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs
+++ b/src/System.Private.CoreLib/src/System/Reflection/AssemblyNameParser.cs
@@ -18,7 +18,7 @@ namespace System.Reflection
[System.Runtime.CompilerServices.ReflectionBlocked]
public static class AssemblyNameParser
{
- public static void Parse(AssemblyName blank, String s)
+ public static void Parse(AssemblyName blank, string s)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -26,7 +26,7 @@ namespace System.Reflection
runtimeAssemblyName.CopyToAssemblyName(blank);
}
- public static RuntimeAssemblyName Parse(String s)
+ public static RuntimeAssemblyName Parse(string s)
{
Debug.Assert(s != null);
@@ -39,26 +39,26 @@ namespace System.Reflection
AssemblyNameLexer lexer = new AssemblyNameLexer(s);
// Name must come first.
- String name;
+ string name;
AssemblyNameLexer.Token token = lexer.GetNext(out name);
if (token != AssemblyNameLexer.Token.String)
throw new FileLoadException(SR.InvalidAssemblyName);
- if (name == String.Empty || name.IndexOfAny(s_illegalCharactersInSimpleName) != -1)
+ if (name == string.Empty || name.IndexOfAny(s_illegalCharactersInSimpleName) != -1)
throw new FileLoadException(SR.InvalidAssemblyName);
Version version = null;
- String cultureName = null;
+ string cultureName = null;
byte[] pkt = null;
AssemblyNameFlags flags = 0;
- LowLevelList<String> alreadySeen = new LowLevelList<String>();
+ LowLevelList<string> alreadySeen = new LowLevelList<string>();
token = lexer.GetNext();
while (token != AssemblyNameLexer.Token.End)
{
if (token != AssemblyNameLexer.Token.Comma)
throw new FileLoadException(SR.InvalidAssemblyName);
- String attributeName;
+ string attributeName;
token = lexer.GetNext(out attributeName);
if (token != AssemblyNameLexer.Token.String)
@@ -73,12 +73,12 @@ namespace System.Reflection
if (token != AssemblyNameLexer.Token.Equals)
throw new FileLoadException(SR.InvalidAssemblyName);
- String attributeValue;
+ string attributeValue;
token = lexer.GetNext(out attributeValue);
if (token != AssemblyNameLexer.Token.String)
throw new FileLoadException(SR.InvalidAssemblyName);
- if (attributeName == String.Empty)
+ if (attributeName == string.Empty)
throw new FileLoadException(SR.InvalidAssemblyName);
for (int i = 0; i < alreadySeen.Count; i++)
@@ -134,9 +134,9 @@ namespace System.Reflection
return new RuntimeAssemblyName(name, version, cultureName, flags, pkt);
}
- private static Version ParseVersion(String attributeValue)
+ private static Version ParseVersion(string attributeValue)
{
- String[] parts = attributeValue.Split('.');
+ string[] parts = attributeValue.Split('.');
if (parts.Length > 4)
throw new FileLoadException(SR.InvalidAssemblyName);
ushort[] versionNumbers = new ushort[4];
@@ -149,7 +149,7 @@ namespace System.Reflection
// Desktop compat: TryParse is a little more forgiving than Fusion.
for (int j = 0; j < parts[i].Length; j++)
{
- if (!Char.IsDigit(parts[i][j]))
+ if (!char.IsDigit(parts[i][j]))
throw new FileLoadException(SR.InvalidAssemblyName);
}
if (!(ushort.TryParse(parts[i], out versionNumbers[i])))
@@ -168,7 +168,7 @@ namespace System.Reflection
return new Version(versionNumbers[0], versionNumbers[1], versionNumbers[2], versionNumbers[3]);
}
- private static String ParseCulture(String attributeValue)
+ private static string ParseCulture(string attributeValue)
{
if (attributeValue.Equals("Neutral", StringComparison.OrdinalIgnoreCase))
{
@@ -181,9 +181,9 @@ namespace System.Reflection
}
}
- private static byte[] ParsePKT(String attributeValue)
+ private static byte[] ParsePKT(string attributeValue)
{
- if (attributeValue.Equals("null", StringComparison.OrdinalIgnoreCase) || attributeValue == String.Empty)
+ if (attributeValue.Equals("null", StringComparison.OrdinalIgnoreCase) || attributeValue == string.Empty)
return Array.Empty<byte>();
if (attributeValue.Length != 8 * 2)
@@ -200,7 +200,7 @@ namespace System.Reflection
return pkt;
}
- private static ProcessorArchitecture ParseProcessorArchitecture(String attributeValue)
+ private static ProcessorArchitecture ParseProcessorArchitecture(string attributeValue)
{
if (attributeValue.Equals("msil", StringComparison.OrdinalIgnoreCase))
return ProcessorArchitecture.MSIL;
diff --git a/src/System.Private.CoreLib/src/System/Reflection/CustomAttributeData.cs b/src/System.Private.CoreLib/src/System/Reflection/CustomAttributeData.cs
index bdf6d56c2..71b85feae 100644
--- a/src/System.Private.CoreLib/src/System/Reflection/CustomAttributeData.cs
+++ b/src/System.Private.CoreLib/src/System/Reflection/CustomAttributeData.cs
@@ -12,7 +12,7 @@ namespace System.Reflection
{
protected CustomAttributeData() { }
- public Type AttributeType
+ public virtual Type AttributeType
{
get
{
diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs
new file mode 100644
index 000000000..e812e7ec2
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs
@@ -0,0 +1,96 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.IO;
+
+namespace System.Reflection.Emit
+{
+ public sealed class AssemblyBuilder : Assembly
+ {
+ internal AssemblyBuilder()
+ {
+ // Prevent generating a default constructor
+ }
+
+ public override string FullName
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsDynamic
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Module ManifestModule
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public static AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ return default;
+ }
+
+ public static AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access, IEnumerable<CustomAttributeBuilder> assemblyAttributes)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ return default;
+ }
+
+ public ModuleBuilder DefineDynamicModule(string name)
+ {
+ return default;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return default;
+ }
+
+ public ModuleBuilder GetDynamicModule(string name)
+ {
+ return default;
+ }
+
+ public override int GetHashCode()
+ {
+ return default;
+ }
+
+ public override ManifestResourceInfo GetManifestResourceInfo(string resourceName)
+ {
+ return default;
+ }
+
+ public override string[] GetManifestResourceNames()
+ {
+ return default;
+ }
+
+ public override Stream GetManifestResourceStream(string name)
+ {
+ return default;
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/ConstructorBuilder.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/ConstructorBuilder.cs
new file mode 100644
index 000000000..d0f02d7f5
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/ConstructorBuilder.cs
@@ -0,0 +1,150 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Globalization;
+
+namespace System.Reflection.Emit
+{
+ public sealed class ConstructorBuilder : ConstructorInfo
+ {
+ internal ConstructorBuilder()
+ {
+ // Prevent generating a default constructor
+ }
+
+ public override MethodAttributes Attributes
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override CallingConventions CallingConvention
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type DeclaringType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public bool InitLocals
+ {
+ get
+ {
+ return default;
+ }
+ set
+ {
+ }
+ }
+
+ public override RuntimeMethodHandle MethodHandle
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Module Module
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override string Name
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type ReflectedType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public ParameterBuilder DefineParameter(int iSequence, ParameterAttributes attributes, string strParamName)
+ {
+ return default;
+ }
+
+ public override object[] GetCustomAttributes(bool inherit)
+ {
+ return default;
+ }
+
+ public override object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ return default;
+ }
+
+ public ILGenerator GetILGenerator()
+ {
+ return default;
+ }
+
+ public ILGenerator GetILGenerator(int streamSize)
+ {
+ return default;
+ }
+
+ public override MethodImplAttributes GetMethodImplementationFlags()
+ {
+ return default;
+ }
+
+ public override ParameterInfo[] GetParameters()
+ {
+ return default;
+ }
+
+ public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
+ {
+ return default;
+ }
+
+ public override object Invoke(BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
+ {
+ return default;
+ }
+
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ return default;
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ }
+
+ public void SetImplementationFlags(MethodImplAttributes attributes)
+ {
+ }
+
+ public override string ToString()
+ {
+ return default;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/CustomAttributeBuilder.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/CustomAttributeBuilder.cs
new file mode 100644
index 000000000..27060a966
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/CustomAttributeBuilder.cs
@@ -0,0 +1,29 @@
+// Licensed to the.NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Reflection.Emit
+{
+ public class CustomAttributeBuilder
+ {
+ public CustomAttributeBuilder(ConstructorInfo con, object[] constructorArgs)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ }
+
+ public CustomAttributeBuilder(ConstructorInfo con, object[] constructorArgs, FieldInfo[] namedFields, object[] fieldValues)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ }
+
+ public CustomAttributeBuilder(ConstructorInfo con, object[] constructorArgs, PropertyInfo[] namedProperties, object[] propertyValues)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ }
+
+ public CustomAttributeBuilder(ConstructorInfo con, object[] constructorArgs, PropertyInfo[] namedProperties, object[] propertyValues, FieldInfo[] namedFields, object[] fieldValues)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs
new file mode 100644
index 000000000..0f5b41c19
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs
@@ -0,0 +1,194 @@
+// Licensed to the.NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Globalization;
+
+namespace System.Reflection.Emit
+{
+ public sealed class DynamicMethod : MethodInfo
+ {
+ public DynamicMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ }
+
+ public DynamicMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ }
+
+ public DynamicMethod(string name, Type returnType, Type[] parameterTypes)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ }
+
+ public DynamicMethod(string name, Type returnType, Type[] parameterTypes, bool restrictedSkipVisibility)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ }
+
+ public DynamicMethod(string name, Type returnType, Type[] parameterTypes, Module m)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ }
+
+ public DynamicMethod(string name, Type returnType, Type[] parameterTypes, Module m, bool skipVisibility)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ }
+
+ public DynamicMethod(string name, Type returnType, Type[] parameterTypes, Type owner)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ }
+
+ public DynamicMethod(string name, Type returnType, Type[] parameterTypes, Type owner, bool skipVisibility)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ }
+
+ public override MethodAttributes Attributes
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override CallingConventions CallingConvention
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type DeclaringType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public bool InitLocals
+ {
+ get
+ {
+ return default;
+ }
+ set
+ {
+ }
+ }
+
+ public override RuntimeMethodHandle MethodHandle
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override string Name
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type ReflectedType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override ParameterInfo ReturnParameter
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type ReturnType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override ICustomAttributeProvider ReturnTypeCustomAttributes
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public sealed override Delegate CreateDelegate(Type delegateType)
+ {
+ return default;
+ }
+
+ public sealed override Delegate CreateDelegate(Type delegateType, object target)
+ {
+ return default;
+ }
+
+ public override MethodInfo GetBaseDefinition()
+ {
+ return default;
+ }
+
+ public override object[] GetCustomAttributes(bool inherit)
+ {
+ return default;
+ }
+
+ public override object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ return default;
+ }
+
+ public ILGenerator GetILGenerator()
+ {
+ return default;
+ }
+
+ public ILGenerator GetILGenerator(int streamSize)
+ {
+ return default;
+ }
+
+ public override MethodImplAttributes GetMethodImplementationFlags()
+ {
+ return default;
+ }
+
+ public override ParameterInfo[] GetParameters()
+ {
+ return default;
+ }
+
+ public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
+ {
+ return default;
+ }
+
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ return default;
+ }
+
+ public override string ToString()
+ {
+ return default;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/EnumBuilder.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/EnumBuilder.cs
new file mode 100644
index 000000000..b9e2f8922
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/EnumBuilder.cs
@@ -0,0 +1,361 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Reflection.Emit
+{
+ public sealed partial class EnumBuilder : TypeInfo
+ {
+ internal EnumBuilder()
+ {
+ // Prevent generating a default constructor
+ }
+
+ public override Assembly Assembly
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override string AssemblyQualifiedName
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type BaseType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type DeclaringType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override string FullName
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Guid GUID
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsConstructedGenericType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Module Module
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override string Name
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override string Namespace
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type ReflectedType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override RuntimeTypeHandle TypeHandle
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public FieldBuilder UnderlyingField
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type UnderlyingSystemType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public TypeInfo CreateTypeInfo()
+ {
+ return default;
+ }
+
+ public FieldBuilder DefineLiteral(string literalName, object literalValue)
+ {
+ return default;
+ }
+
+ protected override TypeAttributes GetAttributeFlagsImpl()
+ {
+ return default;
+ }
+
+ protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
+ {
+ return default;
+ }
+
+ public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override object[] GetCustomAttributes(bool inherit)
+ {
+ return default;
+ }
+
+ public override object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ return default;
+ }
+
+ public override Type GetElementType()
+ {
+ return default;
+ }
+
+ public override Type GetEnumUnderlyingType()
+ {
+ return default;
+ }
+
+ public override EventInfo GetEvent(string name, BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override EventInfo[] GetEvents()
+ {
+ return default;
+ }
+
+ public override EventInfo[] GetEvents(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override FieldInfo GetField(string name, BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override FieldInfo[] GetFields(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override Type GetInterface(string name, bool ignoreCase)
+ {
+ return default;
+ }
+
+ public override InterfaceMapping GetInterfaceMap(Type interfaceType)
+ {
+ return default;
+ }
+
+ public override Type[] GetInterfaces()
+ {
+ return default;
+ }
+
+ public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, System.Type[] types, ParameterModifier[] modifiers)
+ {
+ return default;
+ }
+
+ public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override Type GetNestedType(string name, BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override Type[] GetNestedTypes(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
+ {
+ return default;
+ }
+
+ protected override bool HasElementTypeImpl()
+ {
+ return default;
+ }
+
+ public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters)
+ {
+ return default;
+ }
+
+ protected override bool IsArrayImpl()
+ {
+ return default;
+ }
+
+ public override bool IsAssignableFrom(TypeInfo typeInfo)
+ {
+ return default;
+ }
+
+ protected override bool IsByRefImpl()
+ {
+ return default;
+ }
+
+ public override bool IsByRefLike
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ protected override bool IsCOMObjectImpl()
+ {
+ return default;
+ }
+
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ return default;
+ }
+
+ protected override bool IsPointerImpl()
+ {
+ return default;
+ }
+
+ protected override bool IsPrimitiveImpl()
+ {
+ return default;
+ }
+
+ public override bool IsTypeDefinition
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsSZArray
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsVariableBoundArray
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ protected override bool IsValueTypeImpl()
+ {
+ return default;
+ }
+
+ public override Type MakeArrayType()
+ {
+ return default;
+ }
+
+ public override Type MakeArrayType(int rank)
+ {
+ return default;
+ }
+
+ public override Type MakeByRefType()
+ {
+ return default;
+ }
+
+ public override Type MakePointerType()
+ {
+ return default;
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/EventBuilder.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/EventBuilder.cs
new file mode 100644
index 000000000..80f4b2c5b
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/EventBuilder.cs
@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Reflection.Emit
+{
+ public sealed class EventBuilder
+ {
+ internal EventBuilder()
+ {
+ // Prevent generating a default constructor
+ }
+
+ public void AddOtherMethod(MethodBuilder mdBuilder)
+ {
+ }
+
+ public void SetAddOnMethod(MethodBuilder mdBuilder)
+ {
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ }
+
+ public void SetRaiseMethod(MethodBuilder mdBuilder)
+ {
+ }
+
+ public void SetRemoveOnMethod(MethodBuilder mdBuilder)
+ {
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/FieldBuilder.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/FieldBuilder.cs
new file mode 100644
index 000000000..ff0765e5c
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/FieldBuilder.cs
@@ -0,0 +1,105 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Globalization;
+
+namespace System.Reflection.Emit
+{
+
+ public sealed class FieldBuilder : FieldInfo
+ {
+ internal FieldBuilder()
+ {
+ // Prevent generating a default constructor
+ }
+
+ public override FieldAttributes Attributes
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type DeclaringType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override RuntimeFieldHandle FieldHandle
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type FieldType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override string Name
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type ReflectedType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override object[] GetCustomAttributes(bool inherit)
+ {
+ return default;
+ }
+
+ public override object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ return default;
+ }
+
+ public override object GetValue(object obj)
+ {
+ return default;
+ }
+
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ return default;
+ }
+
+ public void SetConstant(object defaultValue)
+ {
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ }
+
+ public void SetOffset(int iOffset)
+ {
+ }
+
+ public override void SetValue(object obj, object val, BindingFlags invokeAttr, Binder binder, CultureInfo culture)
+ {
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/GenericTypeParameterBuilder.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/GenericTypeParameterBuilder.cs
new file mode 100644
index 000000000..f374fea33
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/GenericTypeParameterBuilder.cs
@@ -0,0 +1,446 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Reflection.Emit
+{
+ public sealed partial class GenericTypeParameterBuilder : TypeInfo
+ {
+ internal GenericTypeParameterBuilder()
+ {
+ // Prevent generating a default constructor
+ }
+
+ public override Assembly Assembly
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override string AssemblyQualifiedName
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type BaseType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool ContainsGenericParameters
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override MethodBase DeclaringMethod
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type DeclaringType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override string FullName
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override GenericParameterAttributes GenericParameterAttributes
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override int GenericParameterPosition
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Guid GUID
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsConstructedGenericType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsGenericParameter
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsGenericType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsGenericTypeDefinition
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Module Module
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override string Name
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override string Namespace
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type ReflectedType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override RuntimeTypeHandle TypeHandle
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type UnderlyingSystemType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool Equals(object o)
+ {
+ return default;
+ }
+
+ protected override TypeAttributes GetAttributeFlagsImpl()
+ {
+ return default;
+ }
+
+ protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
+ {
+ return default;
+ }
+
+ public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override object[] GetCustomAttributes(bool inherit)
+ {
+ return default;
+ }
+
+ public override object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ return default;
+ }
+
+ public override Type GetElementType()
+ {
+ return default;
+ }
+
+ public override EventInfo GetEvent(string name, BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override EventInfo[] GetEvents()
+ {
+ return default;
+ }
+
+ public override EventInfo[] GetEvents(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override FieldInfo GetField(string name, BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override FieldInfo[] GetFields(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override Type[] GetGenericArguments()
+ {
+ return default;
+ }
+
+ public override Type GetGenericTypeDefinition()
+ {
+ return default;
+ }
+
+ public override int GetHashCode()
+ {
+ return default;
+ }
+
+ public override Type GetInterface(string name, bool ignoreCase)
+ {
+ return default;
+ }
+
+ public override InterfaceMapping GetInterfaceMap(Type interfaceType)
+ {
+ return default;
+ }
+
+ public override Type[] GetInterfaces()
+ {
+ return default;
+ }
+
+ public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
+ {
+ return default;
+ }
+
+ public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override Type GetNestedType(string name, BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override Type[] GetNestedTypes(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
+ {
+ return default;
+ }
+
+ protected override bool HasElementTypeImpl()
+ {
+ return default;
+ }
+
+ public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, Globalization.CultureInfo culture, string[] namedParameters)
+ {
+ return default;
+ }
+
+ protected override bool IsArrayImpl()
+ {
+ return default;
+ }
+
+ public override bool IsAssignableFrom(TypeInfo typeInfo)
+ {
+ return default;
+ }
+
+ public override bool IsAssignableFrom(Type c)
+ {
+ return default;
+ }
+
+ protected override bool IsByRefImpl()
+ {
+ return default;
+ }
+
+ public override bool IsByRefLike
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ protected override bool IsCOMObjectImpl()
+ {
+ return default;
+ }
+
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ return default;
+ }
+
+ protected override bool IsPointerImpl()
+ {
+ return default;
+ }
+
+ protected override bool IsPrimitiveImpl()
+ {
+ return default;
+ }
+
+ public override bool IsSubclassOf(Type c)
+ {
+ return default;
+ }
+
+ public override bool IsTypeDefinition
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsSZArray
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsVariableBoundArray
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ protected override bool IsValueTypeImpl()
+ {
+ return default;
+ }
+
+ public override Type MakeArrayType()
+ {
+ return default;
+ }
+
+ public override Type MakeArrayType(int rank)
+ {
+ return default;
+ }
+
+ public override Type MakeByRefType()
+ {
+ return default;
+ }
+
+ public override Type MakeGenericType(params Type[] typeArguments)
+ {
+ return default;
+ }
+
+ public override Type MakePointerType()
+ {
+ return default;
+ }
+
+ public void SetBaseTypeConstraint(Type baseTypeConstraint)
+ {
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ }
+
+ public void SetGenericParameterAttributes(GenericParameterAttributes genericParameterAttributes)
+ {
+ }
+
+ public void SetInterfaceConstraints(params Type[] interfaceConstraints)
+ {
+ }
+
+ public override string ToString()
+ {
+ return default;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs
new file mode 100644
index 000000000..bb52d48d0
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/ILGenerator.cs
@@ -0,0 +1,177 @@
+// Licensed to the.NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+
+namespace System.Reflection.Emit
+{
+ public partial class ILGenerator
+ {
+ internal ILGenerator()
+ {
+ // Prevent generating a default constructor
+ }
+
+ public virtual int ILOffset
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public virtual void BeginCatchBlock(Type exceptionType)
+ {
+ }
+
+ public virtual void BeginExceptFilterBlock()
+ {
+ }
+
+ public virtual Label BeginExceptionBlock()
+ {
+ return default;
+ }
+
+ public virtual void BeginFaultBlock()
+ {
+ }
+
+ public virtual void BeginFinallyBlock()
+ {
+ }
+
+ public virtual void BeginScope()
+ {
+ }
+
+ public virtual LocalBuilder DeclareLocal(Type localType)
+ {
+ return default;
+ }
+
+ public virtual LocalBuilder DeclareLocal(Type localType, bool pinned)
+ {
+ return default;
+ }
+
+ public virtual Label DefineLabel()
+ {
+ return default;
+ }
+
+ public virtual void Emit(OpCode opcode)
+ {
+ }
+
+ public virtual void Emit(OpCode opcode, byte arg)
+ {
+ }
+
+ public virtual void Emit(OpCode opcode, double arg)
+ {
+ }
+
+ public virtual void Emit(OpCode opcode, short arg)
+ {
+ }
+
+ public virtual void Emit(OpCode opcode, int arg)
+ {
+ }
+
+ public virtual void Emit(OpCode opcode, long arg)
+ {
+ }
+
+ public virtual void Emit(OpCode opcode, ConstructorInfo con)
+ {
+ }
+
+ public virtual void Emit(OpCode opcode, Label label)
+ {
+ }
+
+ public virtual void Emit(OpCode opcode, Label[] labels)
+ {
+ }
+
+ public virtual void Emit(OpCode opcode, LocalBuilder local)
+ {
+ }
+
+ public virtual void Emit(OpCode opcode, SignatureHelper signature)
+ {
+ }
+
+ public virtual void Emit(OpCode opcode, FieldInfo field)
+ {
+ }
+
+ public virtual void Emit(OpCode opcode, MethodInfo meth)
+ {
+ }
+
+ [CLSCompliantAttribute(false)]
+ public void Emit(OpCode opcode, sbyte arg)
+ {
+ }
+
+ public virtual void Emit(OpCode opcode, float arg)
+ {
+ }
+
+ public virtual void Emit(OpCode opcode, string str)
+ {
+ }
+
+ public virtual void Emit(OpCode opcode, Type cls)
+ {
+ }
+
+ public virtual void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[] optionalParameterTypes)
+ {
+ }
+
+ public virtual void EmitCalli(OpCode opcode, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes)
+ {
+ }
+
+ public virtual void EmitCalli(OpCode opcode, CallingConvention unmanagedCallConv, Type returnType, Type[] parameterTypes)
+ {
+ }
+
+ public virtual void EmitWriteLine(LocalBuilder localBuilder)
+ {
+ }
+
+ public virtual void EmitWriteLine(FieldInfo fld)
+ {
+ }
+
+ public virtual void EmitWriteLine(string value)
+ {
+ }
+
+ public virtual void EndExceptionBlock()
+ {
+ }
+
+ public virtual void EndScope()
+ {
+ }
+
+ public virtual void MarkLabel(Label loc)
+ {
+ }
+
+ public virtual void ThrowException(Type excType)
+ {
+ }
+
+ public virtual void UsingNamespace(string usingNamespace)
+ {
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/LocalBuilder.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/LocalBuilder.cs
new file mode 100644
index 000000000..a0cbfbde0
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/LocalBuilder.cs
@@ -0,0 +1,38 @@
+// Licensed to the.NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Reflection.Emit
+{
+ public sealed class LocalBuilder : LocalVariableInfo
+ {
+ internal LocalBuilder()
+ {
+ // Prevent generating a default constructor
+ }
+
+ public override bool IsPinned
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override int LocalIndex
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type LocalType
+ {
+ get
+ {
+ return default;
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs
new file mode 100644
index 000000000..c1d528682
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs
@@ -0,0 +1,246 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Reflection.Emit
+{
+ public sealed class MethodBuilder : MethodInfo
+ {
+ internal MethodBuilder()
+ {
+ // Prevent generating a default constructor
+ }
+
+ public override MethodAttributes Attributes
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override CallingConventions CallingConvention
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool ContainsGenericParameters
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type DeclaringType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public bool InitLocals
+ {
+ get
+ {
+ return default;
+ }
+ set
+ {
+ }
+ }
+
+ public override bool IsGenericMethod
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsGenericMethodDefinition
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsConstructedGenericMethod
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override RuntimeMethodHandle MethodHandle
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Module Module
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override string Name
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type ReflectedType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override ParameterInfo ReturnParameter
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type ReturnType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override ICustomAttributeProvider ReturnTypeCustomAttributes
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public GenericTypeParameterBuilder[] DefineGenericParameters(params string[] names)
+ {
+ return default;
+ }
+
+ public ParameterBuilder DefineParameter(int position, ParameterAttributes attributes, string strParamName)
+ {
+ return default;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return default;
+ }
+
+ public override MethodInfo GetBaseDefinition()
+ {
+ return default;
+ }
+
+ public override object[] GetCustomAttributes(bool inherit)
+ {
+ return default;
+ }
+
+ public override object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ return default;
+ }
+
+ public override Type[] GetGenericArguments()
+ {
+ return default;
+ }
+
+ public override MethodInfo GetGenericMethodDefinition()
+ {
+ return default;
+ }
+
+ public override int GetHashCode()
+ {
+ return default;
+ }
+
+ public ILGenerator GetILGenerator()
+ {
+ return default;
+ }
+
+ public ILGenerator GetILGenerator(int size)
+ {
+ return default;
+ }
+
+ public override MethodImplAttributes GetMethodImplementationFlags()
+ {
+ return default;
+ }
+
+ public override ParameterInfo[] GetParameters()
+ {
+ return default;
+ }
+
+ public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, Globalization.CultureInfo culture)
+ {
+ return default;
+ }
+
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ return default;
+ }
+
+ public override MethodInfo MakeGenericMethod(params Type[] typeArguments)
+ {
+ return default;
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ }
+
+ public void SetImplementationFlags(MethodImplAttributes attributes)
+ {
+ }
+
+ public void SetParameters(params Type[] parameterTypes)
+ {
+ }
+
+ public void SetReturnType(Type returnType)
+ {
+ }
+
+ public void SetSignature(Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+ {
+ }
+
+ public override string ToString()
+ {
+ return default;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs
new file mode 100644
index 000000000..2e98335b3
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs
@@ -0,0 +1,142 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+
+namespace System.Reflection.Emit
+{
+ public class ModuleBuilder : Module
+ {
+ internal ModuleBuilder()
+ {
+ // Prevent generating a default constructor
+ }
+
+ public override Assembly Assembly
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override string FullyQualifiedName
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override string Name
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public void CreateGlobalFunctions()
+ {
+ }
+
+ public EnumBuilder DefineEnum(string name, TypeAttributes visibility, Type underlyingType)
+ {
+ return default;
+ }
+
+ public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
+ {
+ return default;
+ }
+
+ public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
+ {
+ return default;
+ }
+
+ public MethodBuilder DefineGlobalMethod(string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)
+ {
+ return default;
+ }
+
+ public FieldBuilder DefineInitializedData(string name, byte[] data, FieldAttributes attributes)
+ {
+ return default;
+ }
+
+ public MethodBuilder DefinePInvokeMethod(string name, string dllName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
+ {
+ return default;
+ }
+
+ public MethodBuilder DefinePInvokeMethod(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
+ {
+ return default;
+ }
+
+ public TypeBuilder DefineType(string name)
+ {
+ return default;
+ }
+
+ public TypeBuilder DefineType(string name, TypeAttributes attr)
+ {
+ return default;
+ }
+
+ public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent)
+ {
+ return default;
+ }
+
+ public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, int typesize)
+ {
+ return default;
+ }
+
+ public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packsize)
+ {
+ return default;
+ }
+
+ public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize)
+ {
+ return default;
+ }
+
+ public TypeBuilder DefineType(string name, TypeAttributes attr, Type parent, Type[] interfaces)
+ {
+ return default;
+ }
+
+ public FieldBuilder DefineUninitializedData(string name, int size, FieldAttributes attributes)
+ {
+ return default;
+ }
+
+ public override bool Equals(object obj)
+ {
+ return default;
+ }
+
+ public MethodInfo GetArrayMethod(Type arrayClass, string methodName, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
+ {
+ return default;
+ }
+
+ public override int GetHashCode()
+ {
+ return default;
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/ParameterBuilder.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/ParameterBuilder.cs
new file mode 100644
index 000000000..a633da26b
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/ParameterBuilder.cs
@@ -0,0 +1,74 @@
+// Licensed to the.NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Reflection.Emit
+{
+ public partial class ParameterBuilder
+ {
+ internal ParameterBuilder()
+ {
+ // Prevent generating a default constructor
+ }
+
+ public virtual int Attributes
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public bool IsIn
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public bool IsOptional
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public bool IsOut
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public virtual string Name
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public virtual int Position
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public virtual void SetConstant(object defaultValue)
+ {
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/PropertyBuilder.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/PropertyBuilder.cs
new file mode 100644
index 000000000..226225268
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/PropertyBuilder.cs
@@ -0,0 +1,155 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Reflection.Emit
+{
+ public sealed class PropertyBuilder : PropertyInfo
+ {
+ internal PropertyBuilder()
+ {
+ // Prevent generating a default constructor
+ }
+
+ public override PropertyAttributes Attributes
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool CanRead
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool CanWrite
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type DeclaringType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Module Module
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override string Name
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type PropertyType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type ReflectedType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public void AddOtherMethod(MethodBuilder mdBuilder)
+ {
+ }
+
+ public override MethodInfo[] GetAccessors(bool nonPublic)
+ {
+ return default;
+ }
+
+ public override object[] GetCustomAttributes(bool inherit)
+ {
+ return default;
+ }
+
+ public override object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ return default;
+ }
+
+ public override MethodInfo GetGetMethod(bool nonPublic)
+ {
+ return default;
+ }
+
+ public override ParameterInfo[] GetIndexParameters()
+ {
+ return default;
+ }
+
+ public override MethodInfo GetSetMethod(bool nonPublic)
+ {
+ return default;
+ }
+
+ public override object GetValue(object obj, object[] index)
+ {
+ return default;
+ }
+
+ public override object GetValue(object obj, BindingFlags invokeAttr, Binder binder, object[] index, Globalization.CultureInfo culture)
+ {
+ return default;
+ }
+
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ return default;
+ }
+
+ public void SetConstant(object defaultValue)
+ {
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ }
+
+ public void SetGetMethod(MethodBuilder mdBuilder)
+ {
+ }
+
+ public void SetSetMethod(MethodBuilder mdBuilder)
+ {
+ }
+
+ public override void SetValue(object obj, object value, object[] index)
+ {
+ }
+
+ public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, object[] index, Globalization.CultureInfo culture)
+ {
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/ReflectionEmitThrower.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/ReflectionEmitThrower.cs
new file mode 100644
index 000000000..6eb7c38cd
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/ReflectionEmitThrower.cs
@@ -0,0 +1,14 @@
+// Licensed to the.NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Reflection.Emit
+{
+ internal static class ReflectionEmitThrower
+ {
+ public static void ThrowPlatformNotSupportedException()
+ {
+ throw new PlatformNotSupportedException(SR.PlatformNotSupported_ReflectionEmit);
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/SignatureHelper.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/SignatureHelper.cs
new file mode 100644
index 000000000..c1da03ffb
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/SignatureHelper.cs
@@ -0,0 +1,108 @@
+// Licensed to the.NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Reflection.Emit
+{
+ public sealed class SignatureHelper
+ {
+ internal SignatureHelper()
+ {
+ // Prevent generating a default constructor
+ }
+
+ public void AddArgument(Type clsArgument)
+ {
+ }
+
+ public void AddArgument(Type argument, bool pinned)
+ {
+ }
+
+ public void AddArgument(Type argument, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ {
+ }
+
+ public void AddArguments(Type[] arguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
+ {
+ }
+
+ public void AddSentinel()
+ {
+ }
+
+ public override bool Equals(object obj)
+ {
+ return default;
+ }
+
+ public static SignatureHelper GetFieldSigHelper(Module mod)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ return default;
+ }
+
+ public override int GetHashCode()
+ {
+ return default;
+ }
+
+ public static SignatureHelper GetLocalVarSigHelper()
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ return default;
+ }
+
+ public static SignatureHelper GetLocalVarSigHelper(Module mod)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ return default;
+ }
+
+ public static SignatureHelper GetMethodSigHelper(CallingConventions callingConvention, Type returnType)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ return default;
+ }
+
+ public static SignatureHelper GetMethodSigHelper(Module mod, CallingConventions callingConvention, Type returnType)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ return default;
+ }
+
+ public static SignatureHelper GetMethodSigHelper(Module mod, Type returnType, Type[] parameterTypes)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ return default;
+ }
+
+ public static SignatureHelper GetPropertySigHelper(Module mod, CallingConventions callingConvention, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ return default;
+ }
+
+ public static SignatureHelper GetPropertySigHelper(Module mod, Type returnType, Type[] parameterTypes)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ return default;
+ }
+
+ public static SignatureHelper GetPropertySigHelper(Module mod, Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers, Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ return default;
+ }
+
+ public byte[] GetSignature()
+ {
+ return default;
+ }
+
+ public override string ToString()
+ {
+ return default;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs b/src/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs
new file mode 100644
index 000000000..d4f5c977d
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs
@@ -0,0 +1,642 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+
+namespace System.Reflection.Emit
+{
+ public sealed partial class TypeBuilder : TypeInfo
+ {
+ internal TypeBuilder()
+ {
+ // Prevent generating a default constructor
+ }
+
+ public const int UnspecifiedTypeSize = 0;
+
+ public override Assembly Assembly
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override string AssemblyQualifiedName
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type BaseType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override MethodBase DeclaringMethod
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type DeclaringType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override string FullName
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override GenericParameterAttributes GenericParameterAttributes
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override int GenericParameterPosition
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Guid GUID
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsByRefLike
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsConstructedGenericType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsGenericParameter
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsGenericType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsGenericTypeDefinition
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsSecurityCritical
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsSecuritySafeCritical
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsSecurityTransparent
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Module Module
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override string Name
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override string Namespace
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public PackingSize PackingSize
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type ReflectedType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public int Size
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override RuntimeTypeHandle TypeHandle
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type UnderlyingSystemType
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public void AddInterfaceImplementation(Type interfaceType) { }
+ public Type CreateType()
+ {
+ return default;
+ }
+
+ public TypeInfo CreateTypeInfo()
+ {
+ return default;
+ }
+
+ public ConstructorBuilder DefineConstructor(MethodAttributes attributes, CallingConventions callingConvention, Type[] parameterTypes)
+ {
+ return default;
+ }
+
+ public ConstructorBuilder DefineConstructor(MethodAttributes attributes, CallingConventions callingConvention, Type[] parameterTypes, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
+ {
+ return default;
+ }
+
+ public ConstructorBuilder DefineDefaultConstructor(MethodAttributes attributes)
+ {
+ return default;
+ }
+
+ public EventBuilder DefineEvent(string name, EventAttributes attributes, Type eventtype)
+ {
+ return default;
+ }
+
+ public FieldBuilder DefineField(string fieldName, Type type, FieldAttributes attributes)
+ {
+ return default;
+ }
+
+ public FieldBuilder DefineField(string fieldName, Type type, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes)
+ {
+ return default;
+ }
+
+ public GenericTypeParameterBuilder[] DefineGenericParameters(params string[] names)
+ {
+ return default;
+ }
+
+ public FieldBuilder DefineInitializedData(string name, byte[] data, FieldAttributes attributes)
+ {
+ return default;
+ }
+
+ public MethodBuilder DefineMethod(string name, MethodAttributes attributes)
+ {
+ return default;
+ }
+
+ public MethodBuilder DefineMethod(string name, MethodAttributes attributes, CallingConventions callingConvention)
+ {
+ return default;
+ }
+
+ public MethodBuilder DefineMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
+ {
+ return default;
+ }
+
+ public MethodBuilder DefineMethod(string name, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+ {
+ return default;
+ }
+
+ public MethodBuilder DefineMethod(string name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)
+ {
+ return default;
+ }
+
+ public void DefineMethodOverride(MethodInfo methodInfoBody, MethodInfo methodInfoDeclaration)
+ {
+ }
+
+ public TypeBuilder DefineNestedType(string name)
+ {
+ return default;
+ }
+
+ public TypeBuilder DefineNestedType(string name, TypeAttributes attr)
+ {
+ return default;
+ }
+
+ public TypeBuilder DefineNestedType(string name, TypeAttributes attr, Type parent)
+ {
+ return default;
+ }
+
+ public TypeBuilder DefineNestedType(string name, TypeAttributes attr, Type parent, int typeSize)
+ {
+ return default;
+ }
+
+ public TypeBuilder DefineNestedType(string name, TypeAttributes attr, Type parent, PackingSize packSize)
+ {
+ return default;
+ }
+
+ public TypeBuilder DefineNestedType(string name, TypeAttributes attr, Type parent, PackingSize packSize, int typeSize)
+ {
+ return default;
+ }
+
+ public TypeBuilder DefineNestedType(string name, TypeAttributes attr, Type parent, Type[] interfaces)
+ {
+ return default;
+ }
+
+ public MethodBuilder DefinePInvokeMethod(string name, string dllName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
+ {
+ return default;
+ }
+
+ public MethodBuilder DefinePInvokeMethod(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
+ {
+ return default;
+ }
+
+ public MethodBuilder DefinePInvokeMethod(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers, CallingConvention nativeCallConv, CharSet nativeCharSet)
+ {
+ return default;
+ }
+
+ public PropertyBuilder DefineProperty(string name, PropertyAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
+ {
+ return default;
+ }
+
+ public PropertyBuilder DefineProperty(string name, PropertyAttributes attributes, CallingConventions callingConvention, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+ {
+ return default;
+ }
+
+ public PropertyBuilder DefineProperty(string name, PropertyAttributes attributes, Type returnType, Type[] parameterTypes)
+ {
+ return default;
+ }
+
+ public PropertyBuilder DefineProperty(string name, PropertyAttributes attributes, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+ {
+ return default;
+ }
+
+ public ConstructorBuilder DefineTypeInitializer()
+ {
+ return default;
+ }
+
+ public FieldBuilder DefineUninitializedData(string name, int size, FieldAttributes attributes)
+ {
+ return default;
+ }
+
+ protected override TypeAttributes GetAttributeFlagsImpl()
+ {
+ return default;
+ }
+
+ public static ConstructorInfo GetConstructor(Type type, ConstructorInfo constructor)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ return default;
+ }
+
+ protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
+ {
+ return default;
+ }
+
+ public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override object[] GetCustomAttributes(bool inherit)
+ {
+ return default;
+ }
+
+ public override object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ return default;
+ }
+
+ public override Type GetElementType()
+ {
+ return default;
+ }
+
+ public override EventInfo GetEvent(string name, BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override EventInfo[] GetEvents()
+ {
+ return default;
+ }
+
+ public override EventInfo[] GetEvents(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override FieldInfo GetField(string name, BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public static FieldInfo GetField(Type type, FieldInfo field)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ return default;
+ }
+
+ public override FieldInfo[] GetFields(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override Type[] GetGenericArguments()
+ {
+ return default;
+ }
+
+ public override Type GetGenericTypeDefinition()
+ {
+ return default;
+ }
+
+ public override Type GetInterface(string name, bool ignoreCase)
+ {
+ return default;
+ }
+
+ public override InterfaceMapping GetInterfaceMap(Type interfaceType)
+ {
+ return default;
+ }
+
+ public override Type[] GetInterfaces()
+ {
+ return default;
+ }
+
+ public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public static MethodInfo GetMethod(Type type, MethodInfo method)
+ {
+ ReflectionEmitThrower.ThrowPlatformNotSupportedException();
+ return default;
+ }
+
+ protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
+ {
+ return default;
+ }
+
+ public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override Type GetNestedType(string name, BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override Type[] GetNestedTypes(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
+ {
+ return default;
+ }
+
+ protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
+ {
+ return default;
+ }
+
+ protected override bool HasElementTypeImpl()
+ {
+ return default;
+ }
+
+ public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, Globalization.CultureInfo culture, string[] namedParameters)
+ {
+ return default;
+ }
+
+ protected override bool IsArrayImpl()
+ {
+ return default;
+ }
+
+ public override bool IsAssignableFrom(TypeInfo typeInfo)
+ {
+ return default;
+ }
+
+ public override bool IsAssignableFrom(Type c)
+ {
+ return default;
+ }
+
+ protected override bool IsByRefImpl()
+ {
+ return default;
+ }
+
+ protected override bool IsCOMObjectImpl()
+ {
+ return default;
+ }
+
+ public bool IsCreated()
+ {
+ return default;
+ }
+
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ return default;
+ }
+
+ protected override bool IsPointerImpl()
+ {
+ return default;
+ }
+
+ protected override bool IsPrimitiveImpl()
+ {
+ return default;
+ }
+
+ public override bool IsSubclassOf(Type c)
+ {
+ return default;
+ }
+
+ public override bool IsTypeDefinition
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsSZArray
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override bool IsVariableBoundArray
+ {
+ get
+ {
+ return default;
+ }
+ }
+
+ public override Type MakeArrayType()
+ {
+ return default;
+ }
+
+ public override Type MakeArrayType(int rank)
+ {
+ return default;
+ }
+
+ public override Type MakeByRefType()
+ {
+ return default;
+ }
+
+ public override Type MakeGenericType(params Type[] typeArguments)
+ {
+ return default;
+ }
+
+ public override Type MakePointerType()
+ {
+ return default;
+ }
+
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ }
+
+ public void SetParent(Type parent)
+ {
+ }
+
+ public override string ToString()
+ {
+ return default;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Reflection/LocalVariableInfo.cs b/src/System.Private.CoreLib/src/System/Reflection/LocalVariableInfo.cs
deleted file mode 100644
index 31e58caeb..000000000
--- a/src/System.Private.CoreLib/src/System/Reflection/LocalVariableInfo.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-
-namespace System.Reflection
-{
- public class LocalVariableInfo
- {
- protected LocalVariableInfo()
- {
- }
-
- public virtual bool IsPinned
- {
- get
- {
- return false;
- }
- }
-
- public virtual int LocalIndex
- {
- get
- {
- return 0;
- }
- }
-
- public virtual Type LocalType
- {
- get
- {
- // Don't laugh - this is really how the desktop behaves if you don't override.
- Debug.Fail("type must be set!");
- return null;
- }
- }
-
- public override string ToString()
- {
- // Don't laugh - this is really how the desktop behaves if you don't override, including the NullReference when
- // it calls ToString() on LocalType's null return.
- string toString = LocalType.ToString() + " (" + LocalIndex + ")";
-
- if (IsPinned)
- toString += " (pinned)";
-
- return toString;
- }
- }
-}
-
diff --git a/src/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs b/src/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs
index 0e8d7a33f..4faa7e258 100644
--- a/src/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs
+++ b/src/System.Private.CoreLib/src/System/Reflection/RuntimeAssemblyName.cs
@@ -17,7 +17,7 @@ namespace System.Reflection
//
public sealed class RuntimeAssemblyName : IEquatable<RuntimeAssemblyName>
{
- public RuntimeAssemblyName(String name, Version version, String cultureName, AssemblyNameFlags flags, byte[] publicKeyOrToken)
+ public RuntimeAssemblyName(string name, Version version, string cultureName, AssemblyNameFlags flags, byte[] publicKeyOrToken)
{
Debug.Assert(name != null);
this.Name = name;
@@ -36,13 +36,13 @@ namespace System.Reflection
}
// Simple name.
- public String Name { get; }
+ public string Name { get; }
// Optional version.
public Version Version { get; }
// Optional culture name.
- public String CultureName { get; }
+ public string CultureName { get; }
// Optional flags (this is actually an OR of the classic flags and the ContentType.)
public AssemblyNameFlags Flags { get; }
@@ -69,7 +69,7 @@ namespace System.Reflection
if (!this.Version.Equals(other.Version))
return false;
}
- if (!String.Equals(this.CultureName, other.CultureName))
+ if (!string.Equals(this.CultureName, other.CultureName))
return false;
if (this.Flags != other.Flags)
return false;
@@ -101,7 +101,7 @@ namespace System.Reflection
return true;
}
- public sealed override bool Equals(Object obj)
+ public sealed override bool Equals(object obj)
{
RuntimeAssemblyName other = obj as RuntimeAssemblyName;
if (other == null)
@@ -157,7 +157,7 @@ namespace System.Reflection
return;
}
- public String FullName
+ public string FullName
{
get
{
diff --git a/src/System.Private.CoreLib/src/System/Resources/FileBasedResourceGroveler.cs b/src/System.Private.CoreLib/src/System/Resources/FileBasedResourceGroveler.cs
index 174a41975..92b6da397 100644
--- a/src/System.Private.CoreLib/src/System/Resources/FileBasedResourceGroveler.cs
+++ b/src/System.Private.CoreLib/src/System/Resources/FileBasedResourceGroveler.cs
@@ -34,16 +34,16 @@ namespace System.Resources
// Consider modifying IResourceGroveler interface (hence this method signature) when we figure out
// serialization compat story for moving ResourceManager members to either file-based or
// manifest-based classes. Want to continue tightening the design to get rid of unused params.
- public ResourceSet GrovelForResourceSet(CultureInfo culture, Dictionary<String, ResourceSet> localResourceSets, bool tryParents, bool createIfNotExists)
+ public ResourceSet GrovelForResourceSet(CultureInfo culture, Dictionary<string, ResourceSet> localResourceSets, bool tryParents, bool createIfNotExists)
{
Debug.Assert(culture != null, "culture shouldn't be null; check caller");
- String fileName = null;
+ string fileName = null;
ResourceSet rs = null;
// Don't use Assembly manifest, but grovel on disk for a file.
// Create new ResourceSet, if a file exists on disk for it.
- String tempFileName = _mediator.GetResourceFileName(culture);
+ string tempFileName = _mediator.GetResourceFileName(culture);
fileName = FindResourceFile(culture, tempFileName);
if (fileName == null)
{
@@ -73,7 +73,7 @@ namespace System.Resources
// diretory or the module dir wasn't provided, look in the current
// directory.
- private String FindResourceFile(CultureInfo culture, String fileName)
+ private string FindResourceFile(CultureInfo culture, string fileName)
{
Debug.Assert(culture != null, "culture shouldn't be null; check caller");
Debug.Assert(fileName != null, "fileName shouldn't be null; check caller");
@@ -82,7 +82,7 @@ namespace System.Resources
// qualified name, append path to that.
if (_mediator.ModuleDir != null)
{
- String path = Path.Combine(_mediator.ModuleDir, fileName);
+ string path = Path.Combine(_mediator.ModuleDir, fileName);
if (File.Exists(path))
{
return path;
@@ -92,27 +92,22 @@ namespace System.Resources
// look in .
if (File.Exists(fileName))
return fileName;
-
+
return null; // give up.
}
- // Constructs a new ResourceSet for a given file name. The logic in
- // here avoids a ReflectionPermission check for our RuntimeResourceSet
- // for perf and working set reasons.
- private ResourceSet CreateResourceSet(String file)
+ // Constructs a new ResourceSet for a given file name.
+ private ResourceSet CreateResourceSet(string file)
{
Debug.Assert(file != null, "file shouldn't be null; check caller");
if (_mediator.UserResourceSet == null)
{
- // Explicitly avoid CreateInstance if possible, because it
- // requires ReflectionPermission to call private & protected
- // constructors.
return new RuntimeResourceSet(file);
}
else
{
- Object[] args = new Object[1];
+ object[] args = new object[1];
args[0] = file;
try
{
diff --git a/src/System.Private.CoreLib/src/System/Resources/IResourceGroveler.cs b/src/System.Private.CoreLib/src/System/Resources/IResourceGroveler.cs
index 1b909a270..4dc5c5d87 100644
--- a/src/System.Private.CoreLib/src/System/Resources/IResourceGroveler.cs
+++ b/src/System.Private.CoreLib/src/System/Resources/IResourceGroveler.cs
@@ -2,10 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-
/*============================================================
**
**
@@ -17,11 +13,15 @@ using System.Globalization;
**
===========================================================*/
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+
namespace System.Resources
{
internal interface IResourceGroveler
{
- ResourceSet GrovelForResourceSet(CultureInfo culture, Dictionary<String, ResourceSet> localResourceSets, bool tryParents,
+ ResourceSet GrovelForResourceSet(CultureInfo culture, Dictionary<string, ResourceSet> localResourceSets, bool tryParents,
bool createIfNotExists);
}
} \ No newline at end of file
diff --git a/src/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs b/src/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs
index fc2241351..449fa4e5b 100644
--- a/src/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs
+++ b/src/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs
@@ -52,7 +52,7 @@ namespace System.Resources
_mediator = mediator;
}
- public ResourceSet GrovelForResourceSet(CultureInfo culture, Dictionary<String, ResourceSet> localResourceSets, bool tryParents, bool createIfNotExists)
+ public ResourceSet GrovelForResourceSet(CultureInfo culture, Dictionary<string, ResourceSet> localResourceSets, bool tryParents, bool createIfNotExists)
{
Debug.Assert(culture != null, "culture shouldn't be null; check caller");
Debug.Assert(localResourceSets != null, "localResourceSets shouldn't be null; check caller");
@@ -94,7 +94,7 @@ namespace System.Resources
// get resource file name we'll search for. Note, be careful if you're moving this statement
// around because lookForCulture may be modified from originally requested culture above.
- String fileName = _mediator.GetResourceFileName(lookForCulture);
+ string fileName = _mediator.GetResourceFileName(lookForCulture);
// 3. If we identified an assembly to search; look in manifest resource stream for resource file
if (satellite != null)
@@ -179,7 +179,7 @@ namespace System.Resources
// Note we could go into infinite loops if mscorlib's
// NeutralResourcesLanguageAttribute is mangled. If this assert
// fires, please fix the build process for the BCL directory.
- if (a == typeof(Object).GetTypeInfo().Assembly)
+ if (a == typeof(object).GetTypeInfo().Assembly)
{
Debug.Fail(a.GetName().Name + "'s NeutralResourcesLanguageAttribute is a malformed culture name! name: \"" + cultureName + "\" Exception: " + e);
return CultureInfo.InvariantCulture;
@@ -207,12 +207,12 @@ namespace System.Resources
// not disposing because we want to leave stream open
BinaryReader br = new BinaryReader(store);
- // Look for our magic number as a little endian Int32.
+ // Look for our magic number as a little endian int.
int bytes = br.ReadInt32();
if (bytes == ResourceManager.MagicNumber)
{
int resMgrHeaderVersion = br.ReadInt32();
- String readerTypeName = null, resSetTypeName = null;
+ string readerTypeName = null, resSetTypeName = null;
if (resMgrHeaderVersion == ResourceManager.HeaderVersionNumber)
{
br.ReadInt32(); // We don't want the number of bytes to skip.
@@ -256,11 +256,11 @@ namespace System.Resources
{
// we do not want to use partial binding here.
Type readerType = Type.GetType(readerTypeName, true);
- Object[] args = new Object[1];
+ object[] args = new object[1];
args[0] = store;
IResourceReader reader = (IResourceReader)Activator.CreateInstance(readerType, args);
- Object[] resourceSetArgs = new Object[1];
+ object[] resourceSetArgs = new object[1];
resourceSetArgs[0] = reader;
Type resSetType;
if (_mediator.UserResourceSet == null)
@@ -294,7 +294,7 @@ namespace System.Resources
}
else
{
- Object[] args = new Object[2];
+ object[] args = new object[2];
args[0] = store;
args[1] = assembly;
try
@@ -308,7 +308,7 @@ namespace System.Resources
}
catch (MissingMethodException) { }
- args = new Object[1];
+ args = new object[1];
args[0] = store;
rs = (ResourceSet)Activator.CreateInstance(_mediator.UserResourceSet, args);
return rs;
@@ -320,7 +320,7 @@ namespace System.Resources
}
}
- private Stream GetManifestResourceStream(Assembly satellite, String fileName)
+ private Stream GetManifestResourceStream(Assembly satellite, string fileName)
{
Debug.Assert(satellite != null, "satellite shouldn't be null; check caller");
Debug.Assert(fileName != null, "fileName shouldn't be null; check caller");
@@ -338,7 +338,7 @@ namespace System.Resources
// case-insensitive lookup rules. Yes, this is slow. The metadata
// dev lead refuses to make all assembly manifest resource lookups case-insensitive,
// even optionally case-insensitive.
- private Stream CaseInsensitiveManifestResourceStreamLookup(Assembly satellite, String name)
+ private Stream CaseInsensitiveManifestResourceStreamLookup(Assembly satellite, string name)
{
Debug.Assert(satellite != null, "satellite shouldn't be null; check caller");
Debug.Assert(name != null, "name shouldn't be null; check caller");
@@ -346,7 +346,7 @@ namespace System.Resources
StringBuilder sb = new StringBuilder();
if (_mediator.LocationInfo != null)
{
- String nameSpace = _mediator.LocationInfo.Namespace;
+ string nameSpace = _mediator.LocationInfo.Namespace;
if (nameSpace != null)
{
sb.Append(nameSpace);
@@ -356,11 +356,11 @@ namespace System.Resources
}
sb.Append(name);
- String givenName = sb.ToString();
- String canonicalName = null;
- foreach (String existingName in satellite.GetManifestResourceNames())
+ string givenName = sb.ToString();
+ string canonicalName = null;
+ foreach (string existingName in satellite.GetManifestResourceNames())
{
- if (String.Equals(existingName, givenName, StringComparison.InvariantCultureIgnoreCase))
+ if (string.Equals(existingName, givenName, StringComparison.InvariantCultureIgnoreCase))
{
if (canonicalName == null)
{
@@ -391,7 +391,7 @@ namespace System.Resources
}
Assembly satellite = null;
- String satAssemblyName = GetSatelliteAssemblyName();
+ string satAssemblyName = GetSatelliteAssemblyName();
// Look up the satellite assembly, but don't let problems
// like a partially signed satellite assembly stop us from
@@ -421,8 +421,11 @@ namespace System.Resources
// Perf optimization - Don't use Reflection for most cases with
// our .resources files. This makes our code run faster and we can avoid
- // creating a ResourceReader via Reflection.
- private bool CanUseDefaultResourceClasses(String readerTypeName, String resSetTypeName)
+ // creating a ResourceReader via Reflection. This would incur
+ // a security check (since the link-time check on the constructor that
+ // takes a String is turned into a full demand with a stack walk)
+ // and causes partially trusted localized apps to fail.
+ private bool CanUseDefaultResourceClasses(string readerTypeName, string resSetTypeName)
{
Debug.Assert(readerTypeName != null, "readerTypeName shouldn't be null; check caller");
Debug.Assert(resSetTypeName != null, "resSetTypeName shouldn't be null; check caller");
@@ -450,16 +453,16 @@ namespace System.Resources
return true;
}
- private String GetSatelliteAssemblyName()
+ private string GetSatelliteAssemblyName()
{
- String satAssemblyName = _mediator.MainAssembly.GetName().Name;
+ string satAssemblyName = _mediator.MainAssembly.GetName().Name;
satAssemblyName += ".resources";
return satAssemblyName;
}
private void HandleSatelliteMissing()
{
- String satAssemName = _mediator.MainAssembly.GetName().Name + ".resources.dll";
+ string satAssemName = _mediator.MainAssembly.GetName().Name + ".resources.dll";
if (_mediator.SatelliteContractVersion != null)
{
satAssemName += ", Version=" + _mediator.SatelliteContractVersion.ToString();
@@ -477,7 +480,7 @@ namespace System.Resources
}
satAssemName += ", PublicKeyToken=" + publicKeyTok;
- String missingCultureName = _mediator.NeutralResourcesCulture.Name;
+ string missingCultureName = _mediator.NeutralResourcesCulture.Name;
if (missingCultureName.Length == 0)
{
missingCultureName = "<invariant>";
@@ -485,10 +488,10 @@ namespace System.Resources
throw new MissingSatelliteAssemblyException(SR.Format(SR.MissingSatelliteAssembly_Culture_Name, _mediator.NeutralResourcesCulture, satAssemName), missingCultureName);
}
- private void HandleResourceStreamMissing(String fileName)
+ private void HandleResourceStreamMissing(string fileName)
{
// Keep people from bothering me about resources problems
- if (_mediator.MainAssembly == typeof(Object).GetTypeInfo().Assembly && _mediator.BaseName.Equals(System.CoreLib.Name))
+ if (_mediator.MainAssembly == typeof(object).GetTypeInfo().Assembly && _mediator.BaseName.Equals(System.CoreLib.Name))
{
// This would break CultureInfo & all our exceptions.
Debug.Fail("Couldn't get " + System.CoreLib.Name + ResourceManager.ResFileExtension + " from " + System.CoreLib.Name + "'s assembly" + Environment.NewLine + Environment.NewLine + "Are you building the runtime on your machine? Chances are the BCL directory didn't build correctly. Type 'build -c' in the BCL directory. If you get build errors, look at buildd.log. If you then can't figure out what's wrong (and you aren't changing the assembly-related metadata code), ask a BCL dev.\n\nIf you did NOT build the runtime, you shouldn't be seeing this and you've found a bug.");
@@ -499,7 +502,7 @@ namespace System.Resources
}
// We really don't think this should happen - we always
// expect the neutral locale's resources to be present.
- String resName = String.Empty;
+ string resName = string.Empty;
if (_mediator.LocationInfo != null && _mediator.LocationInfo.Namespace != null)
resName = _mediator.LocationInfo.Namespace + '.';
resName += fileName;
diff --git a/src/System.Private.CoreLib/src/System/Resources/ResourceManager.cs b/src/System.Private.CoreLib/src/System/Resources/ResourceManager.cs
index cabbff6a7..e219dc7d1 100644
--- a/src/System.Private.CoreLib/src/System/Resources/ResourceManager.cs
+++ b/src/System.Private.CoreLib/src/System/Resources/ResourceManager.cs
@@ -32,7 +32,7 @@ namespace System
public static string FixupCoreLibName(string strToFixup)
{
- if (!String.IsNullOrEmpty(strToFixup))
+ if (!string.IsNullOrEmpty(strToFixup))
{
strToFixup = strToFixup.Replace("mscorlib", System.CoreLib.Name);
}
@@ -45,7 +45,7 @@ namespace System.Resources
{
internal static class ExtensionMethods
{
- public static Assembly InternalGetSatelliteAssembly(this Assembly mainAssembly, String name,
+ public static Assembly InternalGetSatelliteAssembly(this Assembly mainAssembly, string name,
CultureInfo culture,
Version version,
bool throwOnFileNotFound)
@@ -83,7 +83,7 @@ namespace System.Resources
{
public virtual bool Initialize(string reswFilename, out PRIExceptionInfo exceptionInfo) { exceptionInfo = null; return false; }
- public virtual String GetString(String stringName, String startingCulture, String neutralResourcesCulture) { return null; }
+ public virtual string GetString(string stringName, string startingCulture, string neutralResourcesCulture) { return null; }
public virtual CultureInfo GlobalResourceContextBestFitCultureInfo
{
@@ -187,16 +187,16 @@ namespace System.Resources
{
internal class CultureNameResourceSetPair
{
- public String lastCultureName;
+ public string lastCultureName;
public ResourceSet lastResourceSet;
}
- protected String BaseNameField;
+ protected string BaseNameField;
// don't serialize the cache of ResourceSets
[NonSerialized]
- private Dictionary<String, ResourceSet> _resourceSets;
- private String moduleDir; // For assembly-ignorant directory location
+ private Dictionary<string, ResourceSet> _resourceSets;
+ private string moduleDir; // For assembly-ignorant directory location
protected Assembly MainAssembly; // Need the assembly manifest sometimes.
private Type _locationInfo; // For Assembly or type-based directory layout
private Type _userResourceSet; // Which ResourceSet instance to create
@@ -255,10 +255,10 @@ namespace System.Resources
// These Strings are used to avoid using Reflection in CreateResourceSet.
// The first set are used by ResourceWriter. The second are used by
// InternalResGen.
- internal static readonly String ResReaderTypeName = typeof(ResourceReader).FullName;
- internal static readonly String ResSetTypeName = typeof(RuntimeResourceSet).FullName;
- internal static readonly String MscorlibName = typeof(ResourceReader).GetTypeInfo().Assembly.FullName;
- internal const String ResFileExtension = ".resources";
+ internal static readonly string ResReaderTypeName = typeof(ResourceReader).FullName;
+ internal static readonly string ResSetTypeName = typeof(RuntimeResourceSet).FullName;
+ internal static readonly string MscorlibName = typeof(ResourceReader).GetTypeInfo().Assembly.FullName;
+ internal const string ResFileExtension = ".resources";
internal const int ResFileExtensionLength = 10;
// My private debugging aid. Set to 5 or 6 for verbose output. Set to 3
@@ -298,7 +298,7 @@ namespace System.Resources
//
// Note: System.Windows.Forms uses this method at design time.
//
- private ResourceManager(String baseName, String resourceDir, Type usingResourceSet)
+ private ResourceManager(string baseName, string resourceDir, Type usingResourceSet)
{
if (null == baseName)
throw new ArgumentNullException(nameof(baseName));
@@ -309,7 +309,7 @@ namespace System.Resources
moduleDir = resourceDir;
_userResourceSet = usingResourceSet;
- _resourceSets = new Dictionary<String, ResourceSet>();
+ _resourceSets = new Dictionary<string, ResourceSet>();
_lastUsedResourceCache = new CultureNameResourceSetPair();
UseManifest = false;
@@ -317,7 +317,7 @@ namespace System.Resources
resourceGroveler = new FileBasedResourceGroveler(mediator);
}
- public ResourceManager(String baseName, Assembly assembly)
+ public ResourceManager(string baseName, Assembly assembly)
{
if (null == baseName)
throw new ArgumentNullException(nameof(baseName));
@@ -333,7 +333,7 @@ namespace System.Resources
CommonAssemblyInit();
}
- public ResourceManager(String baseName, Assembly assembly, Type usingResourceSet)
+ public ResourceManager(string baseName, Assembly assembly, Type usingResourceSet)
{
if (null == baseName)
throw new ArgumentNullException(nameof(baseName));
@@ -377,7 +377,7 @@ namespace System.Resources
[OnDeserialized]
private void OnDeserialized(StreamingContext ctx)
{
- _resourceSets = new Dictionary<String, ResourceSet>();
+ _resourceSets = new Dictionary<string, ResourceSet>();
_lastUsedResourceCache = new CultureNameResourceSetPair();
// set up resource groveler, depending on whether this ResourceManager
// is looking for files or assemblies
@@ -411,7 +411,7 @@ namespace System.Resources
// Now we can use the managed resources even when using PRI's to support the APIs GetObject, GetStream...etc.
UseManifest = true;
- _resourceSets = new Dictionary<String, ResourceSet>();
+ _resourceSets = new Dictionary<string, ResourceSet>();
_lastUsedResourceCache = new CultureNameResourceSetPair();
_fallbackLoc = UltimateResourceFallbackLocation.MainAssembly;
@@ -423,7 +423,7 @@ namespace System.Resources
}
// Gets the base name for the ResourceManager.
- public virtual String BaseName
+ public virtual string BaseName
{
get
{
@@ -472,11 +472,11 @@ namespace System.Resources
// creating a new ResourceManager isn't quite the correct behavior.
public virtual void ReleaseAllResources()
{
- Dictionary<String, ResourceSet> localResourceSets = _resourceSets;
+ Dictionary<string, ResourceSet> localResourceSets = _resourceSets;
// If any calls to Close throw, at least leave ourselves in a
// consistent state.
- _resourceSets = new Dictionary<String, ResourceSet>();
+ _resourceSets = new Dictionary<string, ResourceSet>();
_lastUsedResourceCache = new CultureNameResourceSetPair();
lock (localResourceSets)
@@ -490,7 +490,7 @@ namespace System.Resources
}
}
- public static ResourceManager CreateFileBasedResourceManager(String baseName, String resourceDir, Type usingResourceSet)
+ public static ResourceManager CreateFileBasedResourceManager(string baseName, string resourceDir, Type usingResourceSet)
{
return new ResourceManager(baseName, resourceDir, usingResourceSet);
}
@@ -505,7 +505,7 @@ namespace System.Resources
//
// This method can be overriden to look for a different extension,
// such as ".ResX", or a completely different format for naming files.
- protected virtual String GetResourceFileName(CultureInfo culture)
+ protected virtual string GetResourceFileName(CultureInfo culture)
{
StringBuilder sb = new StringBuilder(255);
sb.Append(BaseNameField);
@@ -519,7 +519,7 @@ namespace System.Resources
char c = cultureName[i];
// TODO: NLS Arrowhead - This is broken, names can only be RFC4646 names (ie: a-zA-Z0-9).
// TODO: NLS Arrowhead - This allows any unicode letter/digit
- if (Char.IsLetterOrDigit(c) || c == '-' || c == '_')
+ if (char.IsLetterOrDigit(c) || c == '-' || c == '_')
{
continue;
}
@@ -554,7 +554,7 @@ namespace System.Resources
}
// Look in the ResourceSet table
- Dictionary<String, ResourceSet> localResourceSets = _resourceSets;
+ Dictionary<string, ResourceSet> localResourceSets = _resourceSets;
ResourceSet rs = null;
if (localResourceSets != null)
{
@@ -594,7 +594,7 @@ namespace System.Resources
if (null == culture)
throw new ArgumentNullException(nameof(culture));
- Dictionary<String, ResourceSet> localResourceSets = _resourceSets;
+ Dictionary<string, ResourceSet> localResourceSets = _resourceSets;
ResourceSet rs;
if (localResourceSets != null)
{
@@ -626,7 +626,7 @@ namespace System.Resources
// This will take a minimal number of locks.
protected virtual ResourceSet InternalGetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents)
{
- Dictionary<String, ResourceSet> localResourceSets = _resourceSets;
+ Dictionary<string, ResourceSet> localResourceSets = _resourceSets;
ResourceSet rs = null;
CultureInfo foundCulture = null;
lock (localResourceSets)
@@ -691,7 +691,7 @@ namespace System.Resources
}
// Simple helper to ease maintenance and improve readability.
- private static void AddResourceSet(Dictionary<String, ResourceSet> localResourceSets, String cultureName, ref ResourceSet rs)
+ private static void AddResourceSet(Dictionary<string, ResourceSet> localResourceSets, string cultureName, ref ResourceSet rs)
{
// InternalGetResourceSet is both recursive and reentrant -
// assembly load callbacks in particular are a way we can call
@@ -702,7 +702,7 @@ namespace System.Resources
ResourceSet lostRace;
if (localResourceSets.TryGetValue(cultureName, out lostRace))
{
- if (!Object.ReferenceEquals(lostRace, rs))
+ if (!object.ReferenceEquals(lostRace, rs))
{
// Note: In certain cases, we can be trying to add a ResourceSet for multiple
// cultures on one thread, while a second thread added another ResourceSet for one
@@ -728,7 +728,7 @@ namespace System.Resources
throw new ArgumentNullException(nameof(a), SR.ArgumentNull_Assembly);
}
- String v = null;
+ string v = null;
IEnumerable<SatelliteContractVersionAttribute> attrs = a.GetCustomAttributes<SatelliteContractVersionAttribute>();
foreach (SatelliteContractVersionAttribute attr in attrs)
@@ -753,7 +753,7 @@ namespace System.Resources
// SatelliteContractVersionAttribute contains bogus values.
// If this assert fires, please fix the build process for the
// BCL directory.
- if (a == typeof(Object).GetTypeInfo().Assembly)
+ if (a == typeof(object).GetTypeInfo().Assembly)
{
Debug.Fail(System.CoreLib.Name + "'s SatelliteContractVersionAttribute is a malformed version string!");
return null;
@@ -774,8 +774,8 @@ namespace System.Resources
}
// IGNORES VERSION
- internal static bool CompareNames(String asmTypeName1,
- String typeName2,
+ internal static bool CompareNames(string asmTypeName1,
+ string typeName2,
AssemblyName asmName2)
{
Debug.Assert(asmTypeName1 != null, "asmTypeName1 was unexpectedly null");
@@ -786,22 +786,22 @@ namespace System.Resources
return false;
// case sensitive
- if (String.Compare(asmTypeName1, 0, typeName2, 0, typeName2.Length, StringComparison.Ordinal) != 0)
+ if (string.Compare(asmTypeName1, 0, typeName2, 0, typeName2.Length, StringComparison.Ordinal) != 0)
return false;
if (comma == -1)
return true;
// Now, compare assembly display names (IGNORES VERSION AND PROCESSORARCHITECTURE)
// also, for mscorlib ignores everything, since that's what the binder is going to do
- while (Char.IsWhiteSpace(asmTypeName1[++comma])) ;
+ while (char.IsWhiteSpace(asmTypeName1[++comma])) ;
// case insensitive
AssemblyName an1 = new AssemblyName(asmTypeName1.Substring(comma));
- if (String.Compare(an1.Name, asmName2.Name, StringComparison.OrdinalIgnoreCase) != 0)
+ if (string.Compare(an1.Name, asmName2.Name, StringComparison.OrdinalIgnoreCase) != 0)
return false;
// to match IsMscorlib() in VM
- if (String.Compare(an1.Name, System.CoreLib.Name, StringComparison.OrdinalIgnoreCase) == 0)
+ if (string.Compare(an1.Name, System.CoreLib.Name, StringComparison.OrdinalIgnoreCase) == 0)
return true;
@@ -833,7 +833,7 @@ namespace System.Resources
#if FEATURE_APPX
// Throws WinRT hresults
- private string GetStringFromPRI(String stringName, String startingCulture, String neutralResourcesCulture) {
+ private string GetStringFromPRI(string stringName, string startingCulture, string neutralResourcesCulture) {
Debug.Assert(_bUsingModernResourceManagement);
Debug.Assert(_WinRTResourceManager != null);
Debug.Assert(_PRIonAppXInitialized);
@@ -847,8 +847,8 @@ namespace System.Resources
// exception types that the ResourceManager class is not documented to throw.
resourceString = _WinRTResourceManager.GetString(
stringName,
- String.IsNullOrEmpty(startingCulture) ? null : startingCulture,
- String.IsNullOrEmpty(neutralResourcesCulture) ? null : neutralResourcesCulture);
+ string.IsNullOrEmpty(startingCulture) ? null : startingCulture,
+ string.IsNullOrEmpty(neutralResourcesCulture) ? null : neutralResourcesCulture);
return resourceString;
}
@@ -920,7 +920,7 @@ namespace System.Resources
if (s_IsAppXModel)
{
// If we have the type information from the ResourceManager(Type) constructor, we use it. Otherwise, we use BaseNameField.
- String reswFilename = _locationInfo == null ? BaseNameField : _locationInfo.FullName;
+ string reswFilename = _locationInfo == null ? BaseNameField : _locationInfo.FullName;
// The only way this can happen is if a class inherited from ResourceManager and
// did not set the BaseNameField before calling the protected ResourceManager() constructor.
@@ -932,7 +932,7 @@ namespace System.Resources
// throw a MissingManifestResourceException when GetString is called indicating that a
// resW filename called "" could not be found.
if (reswFilename == null)
- reswFilename = String.Empty;
+ reswFilename = string.Empty;
// See AssemblyNative::IsFrameworkAssembly for details on which kinds of assemblies are considered Framework assemblies.
// The Modern Resource Manager is not used for such assemblies - they continue to use satellite assemblies (i.e. .resources.dll files).
@@ -1018,7 +1018,7 @@ namespace System.Resources
// current thread's CultureInfo, and if not found, all parent CultureInfos.
// Returns null if the resource wasn't found.
//
- public virtual String GetString(String name)
+ public virtual string GetString(string name)
{
return GetString(name, (CultureInfo)null);
}
@@ -1027,7 +1027,7 @@ namespace System.Resources
// specified CultureInfo, and if not found, all parent CultureInfos.
// Returns null if the resource wasn't found.
//
- public virtual String GetString(String name, CultureInfo culture)
+ public virtual string GetString(string name, CultureInfo culture)
{
if (null == name)
throw new ArgumentNullException(nameof(name));
@@ -1051,7 +1051,7 @@ namespace System.Resources
// match, since CultureInfo objects can't represent all the different languages the AppX resource model supports.
// For classic resources, this causes us to ignore the languages list and instead use the older Win32 behavior,
// which is the design choice we've made. (See the call a little later to GetCurrentUICultureNoAppX()).
- if (Object.ReferenceEquals(culture, CultureInfo.CurrentUICulture))
+ if (object.ReferenceEquals(culture, CultureInfo.CurrentUICulture))
{
culture = null;
}
@@ -1088,7 +1088,7 @@ namespace System.Resources
if (last != null)
{
- String value = last.GetString(name, _ignoreCase);
+ string value = last.GetString(name, _ignoreCase);
if (value != null)
return value;
}
@@ -1106,7 +1106,7 @@ namespace System.Resources
if (rs != last)
{
- String value = rs.GetString(name, _ignoreCase);
+ string value = rs.GetString(name, _ignoreCase);
if (value != null)
{
// update last used ResourceSet
@@ -1139,7 +1139,7 @@ namespace System.Resources
// current thread's CultureInfo, and if not found, all parent CultureInfos.
// Returns null if the resource wasn't found.
//
- public virtual Object GetObject(String name)
+ public virtual object GetObject(string name)
{
return GetObject(name, (CultureInfo)null, true);
}
@@ -1147,12 +1147,12 @@ namespace System.Resources
// Looks up a resource value for a particular name. Looks in the
// specified CultureInfo, and if not found, all parent CultureInfos.
// Returns null if the resource wasn't found.
- public virtual Object GetObject(String name, CultureInfo culture)
+ public virtual object GetObject(string name, CultureInfo culture)
{
return GetObject(name, culture, true);
}
- private Object GetObject(String name, CultureInfo culture, bool wrapUnmanagedMemStream)
+ private object GetObject(string name, CultureInfo culture, bool wrapUnmanagedMemStream)
{
if (null == name)
throw new ArgumentNullException(nameof(name));
@@ -1163,7 +1163,7 @@ namespace System.Resources
// If the caller explictily passed in a culture that was obtained by calling CultureInfo.CurrentUICulture,
// null it out, so that we re-compute it based on the Win32 value and not the AppX language list value.
// (See the call a little later to GetCurrentUICultureNoAppX()).
- if(Object.ReferenceEquals(culture, CultureInfo.CurrentUICulture))
+ if (object.ReferenceEquals(culture, CultureInfo.CurrentUICulture))
{
culture = null;
}
@@ -1180,7 +1180,7 @@ namespace System.Resources
ResourceSet last = GetFirstResourceSet(culture);
if (last != null)
{
- Object value = last.GetObject(name, _ignoreCase);
+ object value = last.GetObject(name, _ignoreCase);
if (value != null)
{
@@ -1205,7 +1205,7 @@ namespace System.Resources
if (rs != last)
{
- Object value = rs.GetObject(name, _ignoreCase);
+ object value = rs.GetObject(name, _ignoreCase);
if (value != null)
{
// update the last used ResourceSet
@@ -1232,14 +1232,14 @@ namespace System.Resources
return null;
}
- public UnmanagedMemoryStream GetStream(String name)
+ public UnmanagedMemoryStream GetStream(string name)
{
return GetStream(name, (CultureInfo)null);
}
- public UnmanagedMemoryStream GetStream(String name, CultureInfo culture)
+ public UnmanagedMemoryStream GetStream(string name, CultureInfo culture)
{
- Object obj = GetObject(name, culture, false);
+ object obj = GetObject(name, culture, false);
UnmanagedMemoryStream ums = obj as UnmanagedMemoryStream;
if (ums == null && obj != null)
throw new InvalidOperationException(SR.Format(SR.InvalidOperation_ResourceNotStream_Name, name));
@@ -1266,7 +1266,7 @@ namespace System.Resources
if (_installedSatelliteInfo == null)
return true;
- String[] installedSatellites = (String[])_installedSatelliteInfo[MainAssembly.FullName];
+ string[] installedSatellites = (string[])_installedSatelliteInfo[MainAssembly.FullName];
if (installedSatellites == null)
return true;
@@ -1297,7 +1297,7 @@ namespace System.Resources
}
// NEEDED ONLY BY FILE-BASED
- internal String ModuleDir
+ internal string ModuleDir
{
get { return _rm.moduleDir; }
}
@@ -1313,7 +1313,7 @@ namespace System.Resources
get { return _rm._userResourceSet; }
}
- internal String BaseNameField
+ internal string BaseNameField
{
get { return _rm.BaseNameField; }
}
@@ -1324,7 +1324,7 @@ namespace System.Resources
set { _rm._neutralResourcesCulture = value; }
}
- internal String GetResourceFileName(CultureInfo culture)
+ internal string GetResourceFileName(CultureInfo culture)
{
return _rm.GetResourceFileName(culture);
}
@@ -1360,7 +1360,7 @@ namespace System.Resources
// this is weird because we have BaseNameField accessor above, but we're sticking
// with it for compat.
- internal String BaseName
+ internal string BaseName
{
get { return _rm.BaseName; }
}
diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs
index 5601bae5a..3e038d998 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs
+++ b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs
@@ -949,7 +949,7 @@ namespace System.Runtime.CompilerServices
[DependencyReductionRoot]
internal static Action TryGetStateMachineForDebugger(Action action)
{
- Object target = action.Target;
+ object target = action.Target;
MoveNextRunner runner = target as MoveNextRunner;
if (runner != null)
return runner.m_stateMachine.MoveNext;
diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.NonPortable.cs b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.NonPortable.cs
index 4c309ca34..5374478e7 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.NonPortable.cs
+++ b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.NonPortable.cs
@@ -19,10 +19,9 @@ namespace System.Runtime.CompilerServices
{
//=========================================================================================================
// Intrinsic to call the cctor given a pointer to the code (this method's body is ignored and replaced
- // with a calli during compilation). The transform doesn't handle non-generic versions yet (i.e.
- // functions that are void).
+ // with a calli during compilation).
//=========================================================================================================
- private static T Call<T>(System.IntPtr pfn)
+ private static void Call(System.IntPtr pfn)
{
throw NotImplemented.ByDesign;
}
diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs
index 51abcf771..a82e434b8 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs
+++ b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ClassConstructorRunner.cs
@@ -50,7 +50,7 @@ namespace System.Runtime.CompilerServices
return nonGcStaticBase;
}
- private unsafe static object CheckStaticClassConstructionReturnThreadStaticBase(TypeManagerSlot* pModuleData, Int32 typeTlsIndex, StaticClassConstructionContext* context)
+ private unsafe static object CheckStaticClassConstructionReturnThreadStaticBase(TypeManagerSlot* pModuleData, int typeTlsIndex, StaticClassConstructionContext* context)
{
object threadStaticBase = ThreadStatics.GetThreadStaticBaseForType(pModuleData, typeTlsIndex);
EnsureClassConstructorRun(context);
@@ -94,7 +94,7 @@ namespace System.Runtime.CompilerServices
{
NoisyLog("Calling cctor, cctor={0}, thread={1}", pfnCctor, currentManagedThreadId);
- Call<int>(pfnCctor);
+ Call(pfnCctor);
// Insert a memory barrier here to order any writes executed as part of static class
// construction above with respect to the initialized flag update we're about to make
@@ -279,6 +279,19 @@ namespace System.Runtime.CompilerServices
#else
const int Grow = 10;
#endif
+
+ // WASMTODO: Remove this when the Initialize method gets called by the runtime startup
+#if WASM
+ if (s_cctorGlobalLock == null)
+ {
+ Interlocked.CompareExchange(ref s_cctorGlobalLock, new Lock(), null);
+ }
+ if (s_cctorArrays == null)
+ {
+ Interlocked.CompareExchange(ref s_cctorArrays, new Cctor[10][], null);
+ }
+#endif // WASM
+
using (LockHolder.Hold(s_cctorGlobalLock))
{
Cctor[] resultArray = null;
@@ -542,7 +555,7 @@ namespace System.Runtime.CompilerServices
string str;
fixed (char* p = &chars[i])
{
- str = new String(p, 0, numChars - i);
+ str = new string(p, 0, numChars - i);
}
return str;
}
diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs
index 562c195db..5d9b51bcc 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs
+++ b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs
@@ -7,7 +7,6 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
-
using Internal.Runtime.CompilerServices;
namespace System.Runtime.CompilerServices
@@ -17,6 +16,13 @@ namespace System.Runtime.CompilerServices
where TKey : class
where TValue : class
{
+ #region Fields
+ private const int InitialCapacity = 8; // Initial length of the table. Must be a power of two.
+ private readonly Lock _lock; // This lock protects all mutation of data in the table. Readers do not take this lock.
+ private volatile Container _container; // The actual storage for the table; swapped out as the table grows.
+ private int _activeEnumeratorRefCount; // The number of outstanding enumerators on the table
+ #endregion
+
#region Constructors
public ConditionalWeakTable()
{
@@ -165,8 +171,8 @@ namespace System.Runtime.CompilerServices
// invokes createValueCallback() passing it the key. The returned value is bound to the key in the table
// and returned as the result of GetValue().
//
- // If multiple threads race to initialize the same key, the table may invoke createValueCallback
- // multiple times with the same key. Exactly one of these calls will "win the race" and the returned
+ // If multiple threads try to initialize the same key, the table may invoke createValueCallback
+ // multiple times with the same key. Exactly one of these calls will succeed and the returned
// value of that call will be the one added to the table and returned by all the racing GetValue() calls.
//
// This rule permits the table to invoke createValueCallback outside the internal table lock
@@ -174,12 +180,7 @@ namespace System.Runtime.CompilerServices
//--------------------------------------------------------------------------------------------
public TValue GetValue(TKey key, CreateValueCallback createValueCallback)
{
- // Our call to TryGetValue() validates key so no need for us to.
- //
- // if (key == null)
- // {
- // ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
- // }
+ // key is validated by TryGetValue
if (createValueCallback == null)
{
@@ -187,12 +188,9 @@ namespace System.Runtime.CompilerServices
}
TValue existingValue;
- if (TryGetValue(key, out existingValue))
- {
- return existingValue;
- }
-
- return GetValueLocked(key, createValueCallback);
+ return TryGetValue(key, out existingValue) ?
+ existingValue :
+ GetValueLocked(key, createValueCallback);
}
private TValue GetValueLocked(TKey key, CreateValueCallback createValueCallback)
@@ -226,10 +224,7 @@ namespace System.Runtime.CompilerServices
// throw.
//--------------------------------------------------------------------------------------------
- public TValue GetOrCreateValue(TKey key)
- {
- return GetValue(key, k => Activator.CreateInstance<TValue>());
- }
+ public TValue GetOrCreateValue(TKey key) => GetValue(key, _ => Activator.CreateInstance<TValue>());
public delegate TValue CreateValueCallback(TKey key);
@@ -305,7 +300,7 @@ namespace System.Runtime.CompilerServices
if (table != null)
{
// Ensure we don't keep the last current alive unnecessarily
- _current = default(KeyValuePair<TKey, TValue>);
+ _current = default;
// Decrement the ref count that was incremented when constructed
using (LockHolder.Hold(table._lock))
@@ -399,10 +394,7 @@ namespace System.Runtime.CompilerServices
c.CreateEntryNoResize(key, value);
}
- private static bool IsPowerOfTwo(int value)
- {
- return (value > 0) && ((value & (value - 1)) == 0);
- }
+ private static bool IsPowerOfTwo(int value) => (value > 0) && ((value & (value - 1)) == 0);
#endregion
@@ -417,7 +409,7 @@ namespace System.Runtime.CompilerServices
//
// - Used with live key (linked into a bucket list where _buckets[hashCode & (_buckets.Length - 1)] points to first entry)
// depHnd.IsAllocated == true, depHnd.GetPrimary() != null
- // hashCode == RuntimeHelpers.GetHashCode(depHnd.GetPrimary()) & Int32.MaxValue
+ // hashCode == RuntimeHelpers.GetHashCode(depHnd.GetPrimary()) & int.MaxValue
// next links to next Entry in bucket.
//
// - Used with dead key (linked into a bucket list where _buckets[hashCode & (_buckets.Length - 1)] points to first entry)
@@ -453,10 +445,19 @@ namespace System.Runtime.CompilerServices
//
private sealed class Container
{
+ private readonly ConditionalWeakTable<TKey, TValue> _parent; // the ConditionalWeakTable with which this container is associated
+ private int[] _buckets; // _buckets[hashcode & (_buckets.Length - 1)] contains index of the first entry in bucket (-1 if empty)
+ private Entry[] _entries; // the table entries containing the stored dependency handles
+ private int _firstFreeEntry; // _firstFreeEntry < _entries.Length => table has capacity, entries grow from the bottom of the table.
+ private bool _invalid; // flag detects if OOM or other background exception threw us out of the lock.
+ private bool _finalized; // set to true when initially finalized
+ private volatile object _oldKeepAlive; // used to ensure the next allocated container isn't finalized until this one is GC'd
+
internal Container(ConditionalWeakTable<TKey, TValue> parent)
{
Debug.Assert(parent != null);
Debug.Assert(IsPowerOfTwo(InitialCapacity));
+
int size = InitialCapacity;
_buckets = new int[size];
for (int i = 0; i < _buckets.Length; i++)
@@ -481,13 +482,7 @@ namespace System.Runtime.CompilerServices
_firstFreeEntry = firstFreeEntry;
}
- internal bool HasCapacity
- {
- get
- {
- return _firstFreeEntry < _entries.Length;
- }
- }
+ internal bool HasCapacity => _firstFreeEntry < _entries.Length;
internal int FirstFreeEntry => _firstFreeEntry;
@@ -503,7 +498,7 @@ namespace System.Runtime.CompilerServices
VerifyIntegrity();
_invalid = true;
- int hashCode = RuntimeHelpers.GetHashCode(key) & Int32.MaxValue;
+ int hashCode = RuntimeHelpers.GetHashCode(key) & int.MaxValue;
int newEntry = _firstFreeEntry++;
_entries[newEntry].hashCode = hashCode;
@@ -530,7 +525,7 @@ namespace System.Runtime.CompilerServices
object secondary;
int entryIndex = FindEntry(key, out secondary);
value = Unsafe.As<TValue>(secondary);
- return (entryIndex != -1);
+ return entryIndex != -1;
}
//----------------------------------------------------------------------------------------
@@ -542,17 +537,17 @@ namespace System.Runtime.CompilerServices
//----------------------------------------------------------------------------------------
internal int FindEntry(TKey key, out object value)
{
- int hashCode = RuntimeHelpers.GetHashCode(key) & Int32.MaxValue;
+ int hashCode = RuntimeHelpers.GetHashCode(key) & int.MaxValue;
int bucket = hashCode & (_buckets.Length - 1);
for (int entriesIndex = Volatile.Read(ref _buckets[bucket]); entriesIndex != -1; entriesIndex = _entries[entriesIndex].next)
{
if (_entries[entriesIndex].hashCode == hashCode && _entries[entriesIndex].depHnd.GetPrimaryAndSecondary(out value) == key)
{
GC.KeepAlive(this); // ensure we don't get finalized while accessing DependentHandles.
-
return entriesIndex;
}
}
+
GC.KeepAlive(this); // ensure we don't get finalized while accessing DependentHandles.
value = null;
return -1;
@@ -565,8 +560,8 @@ namespace System.Runtime.CompilerServices
{
if (index < _entries.Length)
{
- object oValue;
- object oKey = _entries[index].depHnd.GetPrimaryAndSecondary(out oValue);
+ object oKey, oValue;
+ oKey = _entries[index].depHnd.GetPrimaryAndSecondary(out oValue);
GC.KeepAlive(this); // ensure we don't get finalized while accessing DependentHandles.
if (oKey != null)
@@ -577,8 +572,8 @@ namespace System.Runtime.CompilerServices
}
}
- key = default(TKey);
- value = default(TValue);
+ key = default;
+ value = default;
return false;
}
@@ -617,11 +612,9 @@ namespace System.Runtime.CompilerServices
ref Entry entry = ref _entries[entryIndex];
- //
// We do not free the handle here, as we may be racing with readers who already saw the hash code.
// Instead, we simply overwrite the entry's hash code, so subsequent reads will ignore it.
// The handle will be free'd in Container's finalizer, after the table is resized or discarded.
- //
Volatile.Write(ref entry.hashCode, -1);
// Also, clear the key to allow GC to collect objects pointed to by the entry
@@ -797,18 +790,10 @@ namespace System.Runtime.CompilerServices
~Container()
{
// We're just freeing per-appdomain unmanaged handles here. If we're already shutting down the AD,
- // don't bother.
- //
- // (Despite its name, Environment.HasShutdownStart also returns true if the current AD is finalizing.)
-
- if (Environment.HasShutdownStarted)
- {
- return;
- }
-
- //We also skip doing anything if the container is invalid, including if someone
+ // don't bother. (Despite its name, Environment.HasShutdownStart also returns true if the current
+ // AD is finalizing.) We also skip doing anything if the container is invalid, including if someone
// the container object was allocated but its associated table never set.
- if (_invalid || _parent == null)
+ if (Environment.HasShutdownStarted || _invalid || _parent == null)
{
return;
}
@@ -855,21 +840,7 @@ namespace System.Runtime.CompilerServices
}
}
}
-
- private readonly ConditionalWeakTable<TKey, TValue> _parent; // the ConditionalWeakTable with which this container is associated
- private int[] _buckets; // _buckets[hashcode & (_buckets.Length - 1)] contains index of the first entry in bucket (-1 if empty)
- private Entry[] _entries; // the table entries containing the stored dependency handles
- private int _firstFreeEntry; // _firstFreeEntry < _entries.Length => table has capacity, entries grow from the bottom of the table.
- private bool _invalid; // flag detects if OOM or other background exception threw us out of the lock.
- private bool _finalized; // set to true when initially finalized
- private volatile object _oldKeepAlive; // used to ensure the next allocated container isn't finalized until this one is GC'd
}
-
- private volatile Container _container;
- private readonly Lock _lock; // This lock protects all mutation of data in the table. Readers do not take this lock.
- private int _activeEnumeratorRefCount; // The number of outstanding enumerators on the table
-
- private const int InitialCapacity = 8; // Must be a power of two
#endregion
}
#endregion
@@ -902,25 +873,19 @@ namespace System.Runtime.CompilerServices
internal struct DependentHandle
{
#region Constructors
- public DependentHandle(Object primary, Object secondary)
+ public DependentHandle(object primary, object secondary)
{
_handle = RuntimeImports.RhHandleAllocDependent(primary, secondary);
}
#endregion
#region Public Members
- public bool IsAllocated
- {
- get
- {
- return _handle != (IntPtr)0;
- }
- }
+ public bool IsAllocated => _handle != IntPtr.Zero;
// Getting the secondary object is more expensive than getting the first so
// we provide a separate primary-only accessor for those times we only want the
// primary.
- public Object GetPrimary()
+ public object GetPrimary()
{
return RuntimeImports.RhHandleGet(_handle);
}
diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/FeatureRemovedException.cs b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/FeatureRemovedException.cs
new file mode 100644
index 000000000..fce17a87f
--- /dev/null
+++ b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/FeatureRemovedException.cs
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ // Exception to be thrown when a feature was removed during publishing.
+ internal sealed class FeatureRemovedException : Exception
+ {
+ public string FeatureName { get; }
+
+ public FeatureRemovedException(string featureName)
+ {
+ FeatureName = featureName;
+ }
+
+ public override string Message
+ {
+ get
+ {
+ return SR.Format(SR.FeatureRemoved_Message, FeatureName);
+ }
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs
index f126f4f81..15412878b 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs
+++ b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs
@@ -53,7 +53,7 @@ namespace System.Runtime.CompilerServices
ReflectionAugments.ReflectionCoreCallbacks.RunModuleConstructor(module.AssociatedModule);
}
- public static Object GetObjectValue(Object obj)
+ public static object GetObjectValue(object obj)
{
if (obj == null)
return null;
@@ -65,7 +65,7 @@ namespace System.Runtime.CompilerServices
return RuntimeImports.RhMemberwiseClone(obj);
}
- public new static bool Equals(Object o1, Object o2)
+ public new static bool Equals(object o1, object o2)
{
if (o1 == o2)
return true;
@@ -102,7 +102,7 @@ namespace System.Runtime.CompilerServices
return t_hashSeed;
}
- public static unsafe int GetHashCode(Object o)
+ public static unsafe int GetHashCode(object o)
{
#if FEATURE_SYNCTABLE
return ObjectHeader.GetHashCode(o);
@@ -162,7 +162,7 @@ namespace System.Runtime.CompilerServices
// Number of bytes from the address pointed to by a reference to
// a String to the first 16-bit character in the String.
// This property allows C#'s fixed statement to work on Strings.
- return String.FIRST_CHAR_OFFSET;
+ return string.FIRST_CHAR_OFFSET;
}
}
@@ -239,7 +239,7 @@ namespace System.Runtime.CompilerServices
throw new ArgumentNullException(nameof(d));
}
- public static void ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
+ public static void ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, object userData)
{
if (code == null)
throw new ArgumentNullException(nameof(code));
@@ -263,8 +263,8 @@ namespace System.Runtime.CompilerServices
}
}
- public delegate void TryCode(Object userData);
- public delegate void CleanupCode(Object userData, bool exceptionThrown);
+ public delegate void TryCode(object userData);
+ public delegate void CleanupCode(object userData, bool exceptionThrown);
public static object GetUninitializedObject(Type type)
{
diff --git a/src/System.Private.CoreLib/src/System/Runtime/InitializeFinalizerThread.cs b/src/System.Private.CoreLib/src/System/Runtime/InitializeFinalizerThread.cs
index 2b0e67bc8..cc52fda24 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/InitializeFinalizerThread.cs
+++ b/src/System.Private.CoreLib/src/System/Runtime/InitializeFinalizerThread.cs
@@ -13,9 +13,9 @@ namespace System.Runtime
[RuntimeExport("InitializeFinalizerThread")]
public static void DoInitialize()
{
- // Make sure that the finalizer thread is RoInitialized before any objects are finalized. If this
+ // Make sure that the finalizer thread is CoInitialized before any objects are finalized. If this
// fails, it will throw an exception and that will go unhandled, triggering a FailFast.
- RuntimeThread.RoInitialize();
+ RuntimeThread.InitializeCom();
}
}
}
diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CriticalHandle.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CriticalHandle.cs
index 61f5b8bfb..ed2f7513b 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CriticalHandle.cs
+++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/CriticalHandle.cs
@@ -2,10 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-//
-
-//
-
/*============================================================
**
**
@@ -50,18 +46,19 @@
===========================================================*/
using System;
+using System.IO;
+using System.Reflection;
using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
using System.Runtime.Versioning;
-using System.Reflection;
using System.Threading;
-using System.Runtime.ConstrainedExecution;
/*
Problems addressed by the CriticalHandle class:
1) Critical finalization - ensure we never leak OS resources in SQL. Done
without running truly arbitrary & unbounded amounts of managed code.
2) Reduced graph promotion - during finalization, keep object graph small
- 3) GC.KeepAlive behavior - P/Invoke vs. finalizer thread race (HandleRef)
+ 3) GC.KeepAlive behavior - P/Invoke vs. finalizer thread race condition (HandleRef)
4) Enforcement of the above via the type system - Don't use IntPtr anymore.
Subclasses of CriticalHandle will implement the ReleaseHandle
@@ -240,7 +237,7 @@ namespace System.Runtime.InteropServices
// that no jit allocations etc. will occur, but don't allocate memory unless
// you can deal with the failure and still free the handle).
// The boolean returned should be true for success and false if a
- // catastrophic error occured and you wish to trigger a diagnostic for
+ // catastrophic error occurred and you wish to trigger a diagnostic for
// debugging purposes (the SafeHandleCriticalFailure MDA).
protected abstract bool ReleaseHandle();
}
diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs
index 5bae816fb..53a51ae19 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs
+++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.cs
@@ -31,7 +31,7 @@ namespace System.Runtime.InteropServices
private const GCHandleType MaxHandleType = GCHandleType.Pinned;
// Allocate a handle storing the object and the type.
- internal GCHandle(Object value, GCHandleType type)
+ internal GCHandle(object value, GCHandleType type)
{
// Make sure the type parameter is within the valid range for the enum.
if ((uint)type > (uint)MaxHandleType)
@@ -61,12 +61,12 @@ namespace System.Runtime.InteropServices
// type - The type of GC handle to create.
//
// returns a new GC handle that protects the object.
- public static GCHandle Alloc(Object value)
+ public static GCHandle Alloc(object value)
{
return new GCHandle(value, GCHandleType.Normal);
}
- public static GCHandle Alloc(Object value, GCHandleType type)
+ public static GCHandle Alloc(object value, GCHandleType type)
{
return new GCHandle(value, type);
}
@@ -95,7 +95,7 @@ namespace System.Runtime.InteropServices
}
// Target property - allows getting / updating of the handle's referent.
- public Object Target
+ public object Target
{
get
{
@@ -145,12 +145,12 @@ namespace System.Runtime.InteropServices
// Get the address of the pinned object.
// The layout of String and Array is different from Object
- Object target = this.Target;
+ object target = this.Target;
if (target == null)
return default(IntPtr);
- if (target is String targetAsString)
+ if (target is string targetAsString)
{
return (IntPtr)Unsafe.AsPointer(ref targetAsString.GetRawStringData());
}
@@ -206,7 +206,7 @@ namespace System.Runtime.InteropServices
return _handle.GetHashCode();
}
- public override bool Equals(Object o)
+ public override bool Equals(object o)
{
GCHandle hnd;
@@ -256,7 +256,7 @@ namespace System.Runtime.InteropServices
#endif
}
- private static void GCHandleValidatePinnedObject(Object obj)
+ private static void GCHandleValidatePinnedObject(object obj)
{
if (obj != null && !obj.IsBlittable())
throw new ArgumentException(SR.Argument_NotIsomorphic);
diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/InteropExtensions.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/InteropExtensions.cs
index b296c66fd..10092bcf7 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/InteropExtensions.cs
+++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/InteropExtensions.cs
@@ -43,7 +43,7 @@ namespace System.Runtime.InteropServices
}
// Used for methods in System.Private.Interop.dll that need to work from offsets on boxed structs
- public static unsafe void PinObjectAndCall(Object obj, Action<IntPtr> del)
+ public static unsafe void PinObjectAndCall(object obj, Action<IntPtr> del)
{
fixed (IntPtr* pEEType = &obj.m_pEEType)
{
@@ -70,7 +70,7 @@ namespace System.Runtime.InteropServices
return handle.ToEETypePtr().MightBeBlittable();
}
- public static bool IsBlittable(this Object obj)
+ public static bool IsBlittable(this object obj)
{
return obj.EETypePtr.MightBeBlittable();
}
@@ -130,7 +130,7 @@ namespace System.Runtime.InteropServices
/// <summary>
/// Comparing RuntimeTypeHandle with an object's RuntimeTypeHandle, avoiding going through expensive Object.GetType().TypeHandle path
/// </summary>
- public static bool IsOfType(this Object obj, RuntimeTypeHandle handle)
+ public static bool IsOfType(this object obj, RuntimeTypeHandle handle)
{
RuntimeTypeHandle objType = new RuntimeTypeHandle(obj.EETypePtr);
@@ -228,12 +228,12 @@ namespace System.Runtime.InteropServices
/// weak handle if the callback returns false, which is perfect for controlling lifetime of a CCW
/// </summary>
internal const int RefCountedHandleType = 5;
- public static IntPtr RuntimeHandleAllocRefCounted(Object value)
+ public static IntPtr RuntimeHandleAllocRefCounted(object value)
{
return RuntimeImports.RhHandleAlloc(value, (GCHandleType)RefCountedHandleType);
}
- public static void RuntimeHandleSet(IntPtr handle, Object value)
+ public static void RuntimeHandleSet(IntPtr handle, object value)
{
RuntimeImports.RhHandleSet(handle, value);
}
@@ -253,7 +253,7 @@ namespace System.Runtime.InteropServices
return RuntimeImports.RhIsPromoted(obj);
}
- public static void RuntimeHandleSetDependentSecondary(IntPtr handle, Object secondary)
+ public static void RuntimeHandleSetDependentSecondary(IntPtr handle, object secondary)
{
RuntimeImports.RhHandleSetDependentSecondary(handle, secondary);
}
@@ -338,7 +338,7 @@ namespace System.Runtime.InteropServices
return stringBuilder.GetBuffer(out len);
}
- public static IntPtr RuntimeHandleAllocVariable(Object value, uint type)
+ public static IntPtr RuntimeHandleAllocVariable(object value, uint type)
{
return RuntimeImports.RhHandleAllocVariable(value, type);
}
@@ -357,12 +357,12 @@ namespace System.Runtime.InteropServices
{
return RuntimeImports.RhHandleCompareExchangeVariableType(handle, oldType, newType);
}
-
+
public static void SetExceptionErrorCode(Exception exception, int hr)
{
- exception.SetErrorCode(hr);
+ exception.HResult = hr;
}
-
+
public static void SetExceptionMessage(Exception exception, string message)
{
exception.SetMessage(message);
@@ -373,7 +373,7 @@ namespace System.Runtime.InteropServices
return new DataMisalignedException(message);
}
- public static Delegate CreateDelegate(RuntimeTypeHandle typeHandleForDelegate, IntPtr ldftnResult, Object thisObject, bool isStatic, bool isVirtual, bool isOpen)
+ public static Delegate CreateDelegate(RuntimeTypeHandle typeHandleForDelegate, IntPtr ldftnResult, object thisObject, bool isStatic, bool isVirtual, bool isOpen)
{
return Delegate.CreateDelegate(typeHandleForDelegate.ToEETypePtr(), ldftnResult, thisObject, isStatic, isOpen);
}
@@ -401,6 +401,11 @@ namespace System.Runtime.InteropServices
return ex.TryGetRestrictedErrorDetails(out restrictedError, out restrictedErrorReference, out restrictedCapabilitySid);
}
+ public static IntPtr[] ExceptionGetStackIPs(Exception ex)
+ {
+ return ex.GetStackIPs();
+ }
+
public static TypeInitializationException CreateTypeInitializationException(string message)
{
return new TypeInitializationException(message);
@@ -419,7 +424,7 @@ namespace System.Runtime.InteropServices
return RuntimeImports.RhpETWShouldWalkCom();
}
- public static void RhpETWLogLiveCom(int eventType, IntPtr CCWHandle, IntPtr objectID, IntPtr typeRawValue, IntPtr IUnknown, IntPtr VTable, Int32 comRefCount, Int32 jupiterRefCount, Int32 flags)
+ public static void RhpETWLogLiveCom(int eventType, IntPtr CCWHandle, IntPtr objectID, IntPtr typeRawValue, IntPtr IUnknown, IntPtr VTable, int comRefCount, int jupiterRefCount, int flags)
{
RuntimeImports.RhpETWLogLiveCom(eventType, CCWHandle, objectID, typeRawValue, IUnknown, VTable, comRefCount, jupiterRefCount, flags);
}
diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs
index 5af9ce674..00b7449da 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs
+++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs
@@ -12,12 +12,12 @@ namespace System.Runtime.InteropServices
/// </summary>
internal class Marshal
{
- public static unsafe String PtrToStringUni(IntPtr ptr, int len)
+ public static unsafe string PtrToStringUni(IntPtr ptr, int len)
{
return PInvokeMarshal.PtrToStringUni(ptr, len);
}
- public static unsafe String PtrToStringUni(IntPtr ptr)
+ public static unsafe string PtrToStringUni(IntPtr ptr)
{
return PInvokeMarshal.PtrToStringUni(ptr);
}
diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.cs
index bca69bce3..cf4079084 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.cs
+++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.cs
@@ -443,17 +443,17 @@ namespace System.Runtime.InteropServices
#endregion
#region String marshalling
- public static unsafe String PtrToStringUni(IntPtr ptr, int len)
+ public static unsafe string PtrToStringUni(IntPtr ptr, int len)
{
if (ptr == IntPtr.Zero)
throw new ArgumentNullException(nameof(ptr));
if (len < 0)
throw new ArgumentException(nameof(len));
- return new String((char*)ptr, 0, len);
+ return new string((char*)ptr, 0, len);
}
- public static unsafe String PtrToStringUni(IntPtr ptr)
+ public static unsafe string PtrToStringUni(IntPtr ptr)
{
if (IntPtr.Zero == ptr)
{
@@ -465,7 +465,7 @@ namespace System.Runtime.InteropServices
}
else
{
- return new String((char*)ptr);
+ return new string((char*)ptr);
}
}
@@ -553,7 +553,7 @@ namespace System.Runtime.InteropServices
int lenUnicode;
CalculateStringLength(pchBuffer, out lenAnsi, out lenUnicode);
- string result = String.Empty;
+ string result = string.Empty;
if (lenUnicode > 0)
{
@@ -768,7 +768,7 @@ namespace System.Runtime.InteropServices
int lenAnsi = GetAnsiStringLen(pchBuffer);
int lenUnicode = charCount;
- string result = String.Empty;
+ string result = string.Empty;
if (lenUnicode > 0)
{
diff --git a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/UnsafeGCHandle.cs b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/UnsafeGCHandle.cs
index d7fbf7597..4a0b1d2ce 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/InteropServices/UnsafeGCHandle.cs
+++ b/src/System.Private.CoreLib/src/System/Runtime/InteropServices/UnsafeGCHandle.cs
@@ -36,19 +36,19 @@ namespace System.Runtime.InteropServices
private IntPtr _handle;
// Allocate a handle storing the object and the type.
- private UnsafeGCHandle(Object value, GCHandleType type)
+ private UnsafeGCHandle(object value, GCHandleType type)
{
Debug.Assert((uint)type <= (uint)MaxHandleType, "Unexpected handle type");
_handle = RuntimeImports.RhHandleAlloc(value, type);
}
- public static UnsafeGCHandle Alloc(Object value, GCHandleType type)
+ public static UnsafeGCHandle Alloc(object value, GCHandleType type)
{
return new UnsafeGCHandle(value, type);
}
// Target property - allows getting / updating of the handle's referent.
- public Object Target
+ public object Target
{
get
{
diff --git a/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs
index 6ad477ead..161de82ae 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs
+++ b/src/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs
@@ -34,6 +34,9 @@ namespace System.Runtime.Loader
{
throw new PlatformNotSupportedException();
}
+
+ public void SetProfileOptimizationRoot(string directoryPath) { }
+ public void StartProfileOptimization(string profile) { }
}
/// <summary>
diff --git a/src/System.Private.CoreLib/src/System/Runtime/MemoryFailPoint.cs b/src/System.Private.CoreLib/src/System/Runtime/MemoryFailPoint.cs
index 4c68823e5..da5c8452c 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/MemoryFailPoint.cs
+++ b/src/System.Private.CoreLib/src/System/Runtime/MemoryFailPoint.cs
@@ -212,6 +212,20 @@ namespace System.Runtime
}
bool needContiguousVASpace = (ulong)LastKnownFreeAddressSpace < segmentSize;
+#if false
+ Console.WriteLine($"MemoryFailPoint:" +
+ $"Checking for {(segmentSize >> 20)} MB, " +
+ $"for allocation size of {sizeInMegabytes} MB, " +
+ $"stage {stage}. " +
+ $"Need page file? {needPageFile} " +
+ $"Need Address Space? {needAddressSpace} " +
+ $"Need Contiguous address space? {needContiguousVASpace} " +
+ $"Avail page file: {(availPageFile >> 20)} MB " +
+ $"Total free VA space: {totalAddressSpaceFree >> 20} MB " +
+ $"Contiguous free address space (found): {LastKnownFreeAddressSpace >> 20} MB " +
+ $"Space reserved via process's MemoryFailPoints: {reserved} MB");
+#endif
+
if (!needPageFile && !needAddressSpace && !needContiguousVASpace)
break;
@@ -231,29 +245,20 @@ namespace System.Runtime
if (!needPageFile)
continue;
- // Attempt to grow the OS's page file. Note that we ignore
- // any allocation routines from the host intentionally.
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- }
- finally
+ // This shouldn't overflow due to the if clauses above.
+ UIntPtr numBytes = new UIntPtr(segmentSize);
+ unsafe
{
- // This shouldn't overflow due to the if clauses above.
- UIntPtr numBytes = new UIntPtr(segmentSize);
- unsafe
- {
#if ENABLE_WINRT
- void* pMemory = Interop.mincore.VirtualAllocFromApp(null, numBytes, Interop.Kernel32.MEM_COMMIT, Interop.Kernel32.PAGE_READWRITE);
+ void* pMemory = Interop.mincore.VirtualAllocFromApp(null, numBytes, Interop.Kernel32.MEM_COMMIT, Interop.Kernel32.PAGE_READWRITE);
#else
- void* pMemory = Interop.Kernel32.VirtualAlloc(null, numBytes, Interop.Kernel32.MEM_COMMIT, Interop.Kernel32.PAGE_READWRITE);
+ void* pMemory = Interop.Kernel32.VirtualAlloc(null, numBytes, Interop.Kernel32.MEM_COMMIT, Interop.Kernel32.PAGE_READWRITE);
#endif
- if (pMemory != null)
- {
- bool r = Interop.Kernel32.VirtualFree(pMemory, UIntPtr.Zero, Interop.Kernel32.MEM_RELEASE);
- if (!r)
- throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
- }
+ if (pMemory != null)
+ {
+ bool r = Interop.Kernel32.VirtualFree(pMemory, UIntPtr.Zero, Interop.Kernel32.MEM_RELEASE);
+ if (!r)
+ throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
}
}
continue;
@@ -300,15 +305,8 @@ namespace System.Runtime
if (LastKnownFreeAddressSpace < 0)
CheckForFreeAddressSpace(segmentSize, true);
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- }
- finally
- {
- AddMemoryFailPointReservation((long)size);
- _mustSubtractReservation = true;
- }
+ AddMemoryFailPointReservation((long)size);
+ _mustSubtractReservation = true;
}
private static void CheckForAvailableMemory(out ulong availPageFile, out ulong totalAddressSpaceFree)
@@ -320,6 +318,7 @@ namespace System.Runtime
throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
availPageFile = memory.availPageFile;
totalAddressSpaceFree = memory.availVirtual;
+ // Console.WriteLine($"Memory gate: Mem load: {memory.memoryLoad}% Available memory (physical + page file): {(memory.availPageFile >> 20)} MB Total free address space: {memory.availVirtual >> 20} MB GC Heap: {(GC.GetTotalMemory(true) >> 20)} MB");
}
// Based on the shouldThrow parameter, this will throw an exception, or
@@ -334,6 +333,8 @@ namespace System.Runtime
// know whether VirtualAlloc could succeed.
ulong freeSpaceAfterGCHeap = MemFreeAfterAddress(null, size);
+ // Console.WriteLine($"MemoryFailPoint: Checked for free VA space. Found enough? {(freeSpaceAfterGCHeap >= size)} Asked for: {size} Found: {freeSpaceAfterGCHeap}");
+
// We may set these without taking a lock - I don't believe
// this will hurt, as long as we never increment this number in
// the Dispose method. If we do an extra bit of checking every
@@ -406,15 +407,8 @@ namespace System.Runtime
// within the GC heap.
if (_mustSubtractReservation)
{
- RuntimeHelpers.PrepareConstrainedRegions();
- try
- {
- }
- finally
- {
- AddMemoryFailPointReservation(-((long)_reservedMemory));
- _mustSubtractReservation = false;
- }
+ AddMemoryFailPointReservation(-((long)_reservedMemory));
+ _mustSubtractReservation = false;
}
/*
@@ -463,7 +457,7 @@ namespace System.Runtime
private ulong _totalFreeAddressSpace;
private long _lastKnownFreeAddressSpace;
private ulong _reservedMem;
- private String _stackTrace; // Where did we fail, for additional debugging.
+ private string _stackTrace; // Where did we fail, for additional debugging.
internal MemoryFailPointState(int allocationSizeInMB, ulong segmentSize, bool needPageFile, bool needAddressSpace, bool needContiguousVASpace, ulong availPageFile, ulong totalFreeAddressSpace, long lastKnownFreeAddressSpace, ulong reservedMem)
{
@@ -490,9 +484,9 @@ namespace System.Runtime
}
}
- public override String ToString()
+ public override string ToString()
{
- return String.Format(System.Globalization.CultureInfo.InvariantCulture, "MemoryFailPoint detected insufficient memory to guarantee an operation could complete. Checked for {0} MB, for allocation size of {1} MB. Need page file? {2} Need Address Space? {3} Need Contiguous address space? {4} Avail page file: {5} MB Total free VA space: {6} MB Contiguous free address space (found): {7} MB Space reserved by process's MemoryFailPoints: {8} MB",
+ return string.Format(System.Globalization.CultureInfo.InvariantCulture, "MemoryFailPoint detected insufficient memory to guarantee an operation could complete. Checked for {0} MB, for allocation size of {1} MB. Need page file? {2} Need Address Space? {3} Need Contiguous address space? {4} Avail page file: {5} MB Total free VA space: {6} MB Contiguous free address space (found): {7} MB Space reserved by process's MemoryFailPoints: {8} MB",
_segmentSize >> 20, _allocationSizeInMB, _needPageFile,
_needAddressSpace, _needContiguousVASpace,
_availPageFile >> 20, _totalFreeAddressSpace >> 20,
diff --git a/src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs
index f8ebc13ee..add147252 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs
+++ b/src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs
@@ -71,9 +71,9 @@ namespace System.Runtime
// Mark an object instance as already finalized.
[MethodImpl(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhSuppressFinalize")]
- internal static extern void RhSuppressFinalize(Object obj);
+ internal static extern void RhSuppressFinalize(object obj);
- internal static void RhReRegisterForFinalize(Object obj)
+ internal static void RhReRegisterForFinalize(object obj)
{
if (!_RhReRegisterForFinalize(obj))
throw new OutOfMemoryException();
@@ -81,7 +81,7 @@ namespace System.Runtime
[MethodImpl(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhReRegisterForFinalize")]
- private static extern bool _RhReRegisterForFinalize(Object obj);
+ private static extern bool _RhReRegisterForFinalize(object obj);
// Wait for all pending finalizers. This must be a p/invoke to avoid starving the GC.
[DllImport(RuntimeLibrary, ExactSpelling = true)]
@@ -109,7 +109,7 @@ namespace System.Runtime
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhGetGeneration")]
- internal static extern int RhGetGeneration(Object obj);
+ internal static extern int RhGetGeneration(object obj);
[MethodImpl(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhGetGcLatencyMode")]
@@ -207,9 +207,9 @@ namespace System.Runtime
// Allocate handle.
[MethodImpl(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhpHandleAlloc")]
- private static extern IntPtr RhpHandleAlloc(Object value, GCHandleType type);
+ private static extern IntPtr RhpHandleAlloc(object value, GCHandleType type);
- internal static IntPtr RhHandleAlloc(Object value, GCHandleType type)
+ internal static IntPtr RhHandleAlloc(object value, GCHandleType type)
{
IntPtr h = RhpHandleAlloc(value, type);
if (h == IntPtr.Zero)
@@ -220,9 +220,9 @@ namespace System.Runtime
// Allocate handle for dependent handle case where a secondary can be set at the same time.
[MethodImpl(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhpHandleAllocDependent")]
- private static extern IntPtr RhpHandleAllocDependent(Object primary, Object secondary);
+ private static extern IntPtr RhpHandleAllocDependent(object primary, object secondary);
- internal static IntPtr RhHandleAllocDependent(Object primary, Object secondary)
+ internal static IntPtr RhHandleAllocDependent(object primary, object secondary)
{
IntPtr h = RhpHandleAllocDependent(primary, secondary);
if (h == IntPtr.Zero)
@@ -233,9 +233,9 @@ namespace System.Runtime
// Allocate variable handle with its initial type.
[MethodImpl(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhpHandleAllocVariable")]
- private static extern IntPtr RhpHandleAllocVariable(Object value, uint type);
+ private static extern IntPtr RhpHandleAllocVariable(object value, uint type);
- internal static IntPtr RhHandleAllocVariable(Object value, uint type)
+ internal static IntPtr RhHandleAllocVariable(object value, uint type)
{
IntPtr h = RhpHandleAllocVariable(value, type);
if (h == IntPtr.Zero)
@@ -251,9 +251,9 @@ namespace System.Runtime
// Get object reference from handle.
[MethodImpl(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhHandleGet")]
- private static extern Object _RhHandleGet(IntPtr handle);
+ private static extern object _RhHandleGet(IntPtr handle);
- internal static unsafe Object RhHandleGet(IntPtr handle)
+ internal static unsafe object RhHandleGet(IntPtr handle)
{
#if DEBUG
// The runtime performs additional checks in debug builds
@@ -266,17 +266,17 @@ namespace System.Runtime
// Get primary and secondary object references from dependent handle.
[MethodImpl(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhHandleGetDependent")]
- internal static extern Object RhHandleGetDependent(IntPtr handle, out Object secondary);
+ internal static extern object RhHandleGetDependent(IntPtr handle, out object secondary);
// Set object reference into handle.
[MethodImpl(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhHandleSet")]
- internal static extern void RhHandleSet(IntPtr handle, Object value);
+ internal static extern void RhHandleSet(IntPtr handle, object value);
// Set the secondary object reference into a dependent handle.
[MethodImpl(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhHandleSetDependentSecondary")]
- internal static extern void RhHandleSetDependentSecondary(IntPtr handle, Object secondary);
+ internal static extern void RhHandleSetDependentSecondary(IntPtr handle, object secondary);
// Get the handle type associated with a variable handle.
[MethodImpl(MethodImplOptions.InternalCall)]
@@ -308,7 +308,7 @@ namespace System.Runtime
[MethodImpl(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhTypeCast_CheckArrayStore")]
- internal static extern void RhCheckArrayStore(Object array, Object obj);
+ internal static extern void RhCheckArrayStore(object array, object obj);
[MethodImpl(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhTypeCast_IsInstanceOf")]
@@ -346,7 +346,7 @@ namespace System.Runtime
[MethodImpl(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhNewString")]
- internal static extern String RhNewString(EETypePtr pEEType, int length);
+ internal static extern string RhNewString(EETypePtr pEEType, int length);
[MethodImpl(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhBox")]
@@ -381,6 +381,7 @@ namespace System.Runtime
[DllImport(RuntimeLibrary, EntryPoint = "RhFlushProcessWriteBuffers", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)]
internal static extern void RhFlushProcessWriteBuffers();
+#if !PLATFORM_UNIX
// Wait for any object to be signalled, in a way that's compatible with the CLR's behavior in an STA.
// ExactSpelling = 'true' to force MCG to resolve it to default
[DllImport(RuntimeLibrary, ExactSpelling = true)]
@@ -395,6 +396,7 @@ namespace System.Runtime
{
return RhCompatibleReentrantWaitAny(alertable ? 1 : 0, timeout, count, handles);
}
+#endif
//
// EEType interrogation methods.
@@ -559,11 +561,11 @@ namespace System.Runtime
#if !PROJECTN
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhGetThreadStaticStorageForModule")]
- internal static unsafe extern Array RhGetThreadStaticStorageForModule(Int32 moduleIndex);
+ internal static unsafe extern object[] RhGetThreadStaticStorageForModule(int moduleIndex);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhSetThreadStaticStorageForModule")]
- internal static unsafe extern bool RhSetThreadStaticStorageForModule(Array storage, Int32 moduleIndex);
+ internal static unsafe extern bool RhSetThreadStaticStorageForModule(object[] storage, int moduleIndex);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhCurrentNativeThreadId")]
@@ -571,6 +573,10 @@ namespace System.Runtime
#endif
[MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [RuntimeImport(RuntimeLibrary, "RhCurrentOSThreadId")]
+ internal static unsafe extern ulong RhCurrentOSThreadId();
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport("*", "RhGetCurrentThunkContext")]
internal static extern IntPtr GetCurrentInteropThunkContext();
@@ -715,7 +721,7 @@ namespace System.Runtime
//
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhpETWLogLiveCom")]
- internal extern static void RhpETWLogLiveCom(int eventType, IntPtr CCWHandle, IntPtr objectID, IntPtr typeRawValue, IntPtr IUnknown, IntPtr VTable, Int32 comRefCount, Int32 jupiterRefCount, Int32 flags);
+ internal extern static void RhpETWLogLiveCom(int eventType, IntPtr CCWHandle, IntPtr objectID, IntPtr typeRawValue, IntPtr IUnknown, IntPtr VTable, int comRefCount, int jupiterRefCount, int flags);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhpETWShouldWalkCom")]
diff --git a/src/System.Private.CoreLib/src/System/Runtime/TypeLoaderExports.cs b/src/System.Private.CoreLib/src/System/Runtime/TypeLoaderExports.cs
index fe283e992..8e08a76da 100644
--- a/src/System.Private.CoreLib/src/System/Runtime/TypeLoaderExports.cs
+++ b/src/System.Private.CoreLib/src/System/Runtime/TypeLoaderExports.cs
@@ -109,7 +109,7 @@ namespace System.Runtime
#if PROJECTN
[RuntimeExport("GenericLookupAndCallCtor")]
#endif
- public static void GenericLookupAndCallCtor(Object arg, IntPtr context, IntPtr signature)
+ public static void GenericLookupAndCallCtor(object arg, IntPtr context, IntPtr signature)
{
Entry entry = LookupInCache(s_cache, context, signature);
if (entry == null)
@@ -122,27 +122,27 @@ namespace System.Runtime
#if PROJECTN
[RuntimeExport("GenericLookupAndAllocObject")]
#endif
- public static Object GenericLookupAndAllocObject(IntPtr context, IntPtr signature)
+ public static object GenericLookupAndAllocObject(IntPtr context, IntPtr signature)
{
Entry entry = LookupInCache(s_cache, context, signature);
if (entry == null)
{
entry = CacheMiss(context, signature);
}
- return RawCalliHelper.Call<Object>(entry.Result, entry.AuxResult);
+ return RawCalliHelper.Call<object>(entry.Result, entry.AuxResult);
}
#if PROJECTN
[RuntimeExport("GenericLookupAndAllocArray")]
#endif
- public static Object GenericLookupAndAllocArray(IntPtr context, IntPtr arg, IntPtr signature)
+ public static object GenericLookupAndAllocArray(IntPtr context, IntPtr arg, IntPtr signature)
{
Entry entry = LookupInCache(s_cache, context, signature);
if (entry == null)
{
entry = CacheMiss(context, signature);
}
- return RawCalliHelper.Call<Object>(entry.Result, entry.AuxResult, arg);
+ return RawCalliHelper.Call<object>(entry.Result, entry.AuxResult, arg);
}
#if PROJECTN
@@ -161,14 +161,14 @@ namespace System.Runtime
#if PROJECTN
[RuntimeExport("GenericLookupAndCast")]
#endif
- public static Object GenericLookupAndCast(Object arg, IntPtr context, IntPtr signature)
+ public static object GenericLookupAndCast(object arg, IntPtr context, IntPtr signature)
{
Entry entry = LookupInCache(s_cache, context, signature);
if (entry == null)
{
entry = CacheMiss(context, signature);
}
- return RawCalliHelper.Call<Object>(entry.Result, arg, entry.AuxResult);
+ return RawCalliHelper.Call<object>(entry.Result, arg, entry.AuxResult);
}
#if PROJECTN
@@ -433,7 +433,7 @@ namespace System.Runtime
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static void Call(System.IntPtr pfn, Object arg)
+ public static void Call(System.IntPtr pfn, object arg)
{
}
@@ -451,12 +451,12 @@ namespace System.Runtime
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static void Call(System.IntPtr pfn, IntPtr arg1, Object arg2)
+ public static void Call(System.IntPtr pfn, IntPtr arg1, object arg2)
{
}
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
- public static T Call<T>(System.IntPtr pfn, Object arg1, IntPtr arg2)
+ public static T Call<T>(System.IntPtr pfn, object arg1, IntPtr arg2)
{
return default(T);
}
diff --git a/src/System.Private.CoreLib/src/System/RuntimeExceptionHelpers.cs b/src/System.Private.CoreLib/src/System/RuntimeExceptionHelpers.cs
index ec40c126d..35d954368 100644
--- a/src/System.Private.CoreLib/src/System/RuntimeExceptionHelpers.cs
+++ b/src/System.Private.CoreLib/src/System/RuntimeExceptionHelpers.cs
@@ -129,7 +129,7 @@ namespace System
}
- public static void FailFast(String message)
+ public static void FailFast(string message)
{
FailFast(message, null, RhFailFastReason.Unknown, IntPtr.Zero, IntPtr.Zero);
}
@@ -184,7 +184,7 @@ namespace System
Debug.WriteLine("Unhandled Exception: " + exception.ToString());
}
- failFastMessage = String.Format("Runtime-generated FailFast: ({0}): {1}{2}",
+ failFastMessage = string.Format("Runtime-generated FailFast: ({0}): {1}{2}",
reason.ToString(), // Explicit call to ToString() to avoid MissingMetadataException inside String.Format()
GetStringForFailFastReason(reason),
exception != null ? " [exception object available]" : "");
@@ -208,7 +208,7 @@ namespace System
if (!minimalFailFast)
{
- String output = (exception != null) ?
+ string output = (exception != null) ?
"Unhandled Exception: " + exception.ToString()
: message;
DeveloperExperience.Default.WriteLine(output);
@@ -309,10 +309,10 @@ namespace System
public struct ExceptionMetadataStruct
{
- public UInt32 ExceptionId { get; set; } // Id assigned to the exception. May not be contiguous or start at 0.
- public UInt32 InnerExceptionId { get; set; } // ID of the inner exception or 0xFFFFFFFF for 'no inner exception'
- public UInt32 ThreadId { get; set; } // Managed thread ID the eception was thrown on
- public Int32 NestingLevel { get; set; } // If multiple exceptions are currently active on a thread, this gives the ordering for them.
+ public uint ExceptionId { get; set; } // Id assigned to the exception. May not be contiguous or start at 0.
+ public uint InnerExceptionId { get; set; } // ID of the inner exception or 0xFFFFFFFF for 'no inner exception'
+ public uint ThreadId { get; set; } // Managed thread ID the eception was thrown on
+ public int NestingLevel { get; set; } // If multiple exceptions are currently active on a thread, this gives the ordering for them.
// The highest number is the most recent exception. -1 means the exception is not currently in flight
// (but it may still be an InnerException).
public IntPtr ExceptionCCWPtr { get; set; } // If the exception was thrown in an interop scenario, this contains the CCW pointer, otherwise, IntPtr.Zero
@@ -390,7 +390,7 @@ namespace System
private static void SerializeExceptionsForDump(Exception currentException, IntPtr exceptionCCWPtr, LowLevelList<byte[]> serializedExceptions)
{
- const UInt32 NoInnerExceptionValue = 0xFFFFFFFF;
+ const uint NoInnerExceptionValue = 0xFFFFFFFF;
// Approximate upper size limit for the serialized exceptions (but we'll always serialize currentException)
// If we hit the limit, because we serialize in arbitrary order, there may be missing InnerExceptions or nested exceptions.
@@ -442,10 +442,10 @@ namespace System
{
ExceptionData exceptionData = s_exceptionDataTable.GetOrCreateValue(exceptions[i]);
- exceptionData.ExceptionMetadata.ExceptionId = (UInt32)System.Threading.Interlocked.Increment(ref s_currentExceptionId);
+ exceptionData.ExceptionMetadata.ExceptionId = (uint)System.Threading.Interlocked.Increment(ref s_currentExceptionId);
if (exceptionData.ExceptionMetadata.ExceptionId == NoInnerExceptionValue)
{
- exceptionData.ExceptionMetadata.ExceptionId = (UInt32)System.Threading.Interlocked.Increment(ref s_currentExceptionId);
+ exceptionData.ExceptionMetadata.ExceptionId = (uint)System.Threading.Interlocked.Increment(ref s_currentExceptionId);
}
exceptionData.ExceptionMetadata.ThreadId = currentThreadId;
@@ -462,7 +462,7 @@ namespace System
}
// Only match the CCW pointer up to the current exception
- if (Object.ReferenceEquals(exceptions[i], currentException))
+ if (object.ReferenceEquals(exceptions[i], currentException))
{
exceptionData.ExceptionMetadata.ExceptionCCWPtr = exceptionCCWPtr;
}
diff --git a/src/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs b/src/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs
index dac2f2958..3e9b5a5e2 100644
--- a/src/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs
+++ b/src/System.Private.CoreLib/src/System/RuntimeFieldHandle.cs
@@ -18,7 +18,7 @@ namespace System
public IntPtr Value => _value;
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
if (!(obj is RuntimeFieldHandle))
return false;
diff --git a/src/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs b/src/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs
index c079f4756..02d1b8da0 100644
--- a/src/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs
+++ b/src/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs
@@ -20,7 +20,7 @@ namespace System
public unsafe IntPtr Value => _value;
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
if (!(obj is RuntimeMethodHandle))
return false;
diff --git a/src/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs b/src/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs
index c713560e6..778b011a6 100644
--- a/src/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs
+++ b/src/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs
@@ -26,7 +26,7 @@ namespace System
_value = pEEType.RawValue;
}
- public override bool Equals(Object obj)
+ public override bool Equals(object obj)
{
if (obj is RuntimeTypeHandle)
{
@@ -105,6 +105,7 @@ namespace System
throw new PlatformNotSupportedException();
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
internal EETypePtr ToEETypePtr()
{
return new EETypePtr(_value);
@@ -119,11 +120,11 @@ namespace System
}
// Last resort string for Type.ToString() when no metadata around.
- internal String LastResortToString
+ internal string LastResortToString
{
get
{
- String s;
+ string s;
EETypePtr eeType = this.ToEETypePtr();
IntPtr rawEEType = eeType.RawValue;
IntPtr moduleBase = RuntimeImports.RhGetOSModuleFromEEType(rawEEType);
@@ -140,7 +141,7 @@ namespace System
ReflectionExecutionDomainCallbacks callbacks = RuntimeAugments.CallbacksIfAvailable;
if (callbacks != null)
{
- String penultimateLastResortString = callbacks.GetBetterDiagnosticInfoIfAvailable(this);
+ string penultimateLastResortString = callbacks.GetBetterDiagnosticInfoIfAvailable(this);
if (penultimateLastResortString != null)
s += "(" + penultimateLastResortString + ")";
}
diff --git a/src/System.Private.CoreLib/src/System/Security/AccessControl/RegistryRights.cs b/src/System.Private.CoreLib/src/System/Security/AccessControl/RegistryRights.cs
deleted file mode 100644
index 6359122ef..000000000
--- a/src/System.Private.CoreLib/src/System/Security/AccessControl/RegistryRights.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Microsoft.Win32;
-
-namespace System.Security.AccessControl
-{
- // We derived this enum from the definitions of KEY_READ and such from
- // winnt.h and from MSDN, plus some experimental validation with regedit.
- // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/base/registry_key_security_and_access_rights.asp
- [Flags]
-#if REGISTRY_ASSEMBLY
- public
-#else
- internal
-#endif
- enum RegistryRights
- {
- // No None field - An ACE with the value 0 cannot grant nor deny.
- QueryValues = Interop.mincore.RegistryOperations.KEY_QUERY_VALUE, // 0x0001 query the values of a registry key
- SetValue = Interop.mincore.RegistryOperations.KEY_SET_VALUE, // 0x0002 create, delete, or set a registry value
- CreateSubKey = Interop.mincore.RegistryOperations.KEY_CREATE_SUB_KEY, // 0x0004 required to create a subkey of a specific key
- EnumerateSubKeys = Interop.mincore.RegistryOperations.KEY_ENUMERATE_SUB_KEYS, // 0x0008 required to enumerate sub keys of a key
- Notify = Interop.mincore.RegistryOperations.KEY_NOTIFY, // 0x0010 needed to request change notifications
- CreateLink = Interop.mincore.RegistryOperations.KEY_CREATE_LINK, // 0x0020 reserved for system use
- ///
- /// The Windows Kernel team agrees that it was a bad design to expose the WOW64_n options as permissions.
- /// in the .NET Framework these options are exposed via the RegistryView enum
- ///
- /// Reg64 = Interop.mincore.RegistryOptions.KEY_WOW64_64KEY, // 0x0100 operate on the 64-bit registry view
- /// Reg32 = Interop.mincore.RegistryOptions.KEY_WOW64_32KEY, // 0x0200 operate on the 32-bit registry view
- ExecuteKey = ReadKey,
- ReadKey = Interop.mincore.RegistryOperations.STANDARD_RIGHTS_READ | QueryValues | EnumerateSubKeys | Notify,
- WriteKey = Interop.mincore.RegistryOperations.STANDARD_RIGHTS_WRITE | SetValue | CreateSubKey,
- Delete = 0x10000,
- ReadPermissions = 0x20000,
- ChangePermissions = 0x40000,
- TakeOwnership = 0x80000,
- FullControl = 0xF003F | Interop.mincore.RegistryOperations.STANDARD_RIGHTS_READ | Interop.mincore.RegistryOperations.STANDARD_RIGHTS_WRITE
- }
-}
diff --git a/src/System.Private.CoreLib/src/System/String.CoreRT.cs b/src/System.Private.CoreLib/src/System/String.CoreRT.cs
index a892006d9..3aedf2c50 100644
--- a/src/System.Private.CoreLib/src/System/String.CoreRT.cs
+++ b/src/System.Private.CoreLib/src/System/String.CoreRT.cs
@@ -16,9 +16,52 @@ using Internal.Runtime.CompilerServices;
namespace System
{
+ // STRING LAYOUT
+ // -------------
+ // Strings are null-terminated for easy interop with native, but the value returned by String.Length
+ // does NOT include this null character in its count. As a result, there's some trickiness here in the
+ // layout and allocation of strings that needs explanation...
+ //
+ // String is allocated like any other array, using the RhNewArray API. It is essentially a very special
+ // char[] object. In order to be an array, the String EEType must have an 'array element size' of 2,
+ // which is setup by a special case in the binder. Strings must also have a typical array instance
+ // layout, which means that the first field after the m_pEEType field is the 'number of array elements'
+ // field. However, here, it is called _stringLength because it contains the number of characters in the
+ // string (NOT including the terminating null element) and, thus, directly represents both the array
+ // length and String.Length.
+ //
+ // As with all arrays, the GC calculates the size of an object using the following formula:
+ //
+ // obj_size = align(base_size + (num_elements * element_size), sizeof(void*))
+ //
+ // The values 'base_size' and 'element_size' are both stored in the EEType for String and 'num_elements'
+ // is _stringLength.
+ //
+ // Our base_size is the size of the fixed portion of the string defined below. It, therefore, contains
+ // the size of the _firstChar field in it. This means that, since our string data actually starts
+ // inside the fixed 'base_size' area, and our num_elements is equal to String.Length, we end up with one
+ // extra character at the end. This is how we get our extra null terminator which allows us to pass a
+ // pinned string out to native code as a null-terminated string. This is also why we don't increment the
+ // requested string length by one before passing it to RhNewArray. There is no need to allocate an extra
+ // array element, it is already allocated here in the fixed layout of the String.
+ //
+ // Typically, the base_size of an array type is aligned up to the nearest pointer size multiple (so that
+ // array elements start out aligned in case they need alignment themselves), but we don't want to do that
+ // with String because we are allocating String.Length components with RhNewArray and the overall object
+ // size will then need another alignment, resulting in wasted space. So the binder specially shrinks the
+ // base_size of String, leaving it unaligned in order to allow the use of that otherwise wasted space.
+ //
+ // One more note on base_size -- on 64-bit, the base_size ends up being 22 bytes, which is less than the
+ // min_obj_size of (3 * sizeof(void*)). This is OK because our array allocator will still align up the
+ // overall object size, so a 0-length string will end up with an object size of 24 bytes, which meets the
+ // min_obj_size requirement.
+ //
+ // NOTE: This class is marked EagerStaticClassConstruction because McgCurrentModule class being eagerly
+ // constructed itself depends on this class also being eagerly constructed. Plus, it's nice to have this
+ // eagerly constructed to avoid the cost of defered ctors. I can't imagine any app that doesn't use string
+ //
[StructLayout(LayoutKind.Sequential)]
[System.Runtime.CompilerServices.EagerStaticClassConstructionAttribute]
- [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public partial class String
{
#if BIT64
@@ -47,11 +90,8 @@ namespace System
#pragma warning restore
- public static readonly String Empty = "";
+ public static readonly string Empty = "";
- // Gets the character at a specified position.
- //
- // Spec#: Apply the precondition here using a contract assembly. Potential perf issue.
[System.Runtime.CompilerServices.IndexerName("Chars")]
public unsafe char this[int index]
{
@@ -72,7 +112,12 @@ namespace System
#endif
}
- internal static String FastAllocateString(int length)
+ public int Length
+ {
+ get { return _stringLength; }
+ }
+
+ internal static string FastAllocateString(int length)
{
// We allocate one extra char as an interop convenience so that our strings are null-
// terminated, however, we don't pass the extra +1 to the string allocation because the base
diff --git a/src/System.Private.CoreLib/src/System/Text/EncodingData.cs b/src/System.Private.CoreLib/src/System/Text/EncodingData.cs
index bff11e744..852f578dc 100644
--- a/src/System.Private.CoreLib/src/System/Text/EncodingData.cs
+++ b/src/System.Private.CoreLib/src/System/Text/EncodingData.cs
@@ -121,7 +121,7 @@ namespace System.Text
// The index of the entry in s_encodingNamesIndices will be the index of codepage in
// s_codePagesByName.
//
- private static readonly UInt16[] s_codePagesByName = new UInt16[]
+ private static readonly ushort[] s_codePagesByName = new ushort[]
{
20127, // ansi_x3.4-1968
20127, // ansi_x3.4-1986
@@ -177,7 +177,7 @@ namespace System.Text
// s_englishNames. In addition, this arrays indices correspond to the indices
// into s_uiFamilyCodePages and s_flags.
//
- private static readonly UInt16[] s_mappedCodePages = new UInt16[]
+ private static readonly ushort[] s_mappedCodePages = new ushort[]
{
1200, // utf-16
1201, // utf-16be
diff --git a/src/System.Private.CoreLib/src/System/Text/StringBuilder.CoreRT.cs b/src/System.Private.CoreLib/src/System/Text/StringBuilder.CoreRT.cs
index aab4e5d31..9a9516e4f 100644
--- a/src/System.Private.CoreLib/src/System/Text/StringBuilder.CoreRT.cs
+++ b/src/System.Private.CoreLib/src/System/Text/StringBuilder.CoreRT.cs
@@ -32,7 +32,7 @@ namespace System.Text
/// </summary>
internal unsafe void ReplaceBuffer(char* newBuffer)
{
- int len = String.wcslen(newBuffer);
+ int len = string.wcslen(newBuffer);
// the '+1' is for back-compat with desktop CLR in terms of length calculation because desktop
// CLR had '\0'
diff --git a/src/System.Private.CoreLib/src/System/Text/StringBuilderCache.cs b/src/System.Private.CoreLib/src/System/Text/StringBuilderCache.cs
deleted file mode 100644
index a1b1f50e3..000000000
--- a/src/System.Private.CoreLib/src/System/Text/StringBuilderCache.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-/*============================================================
-**
-**
-** Purpose: provide a cached reusable instance of stringbuilder
-** per thread it's an optimisation that reduces the
-** number of instances constructed and collected.
-**
-** Acquire - is used to get a string builder to use of a
-** particular size. It can be called any number of
-** times, if a stringbuilder is in the cache then
-** it will be returned and the cache emptied.
-** subsequent calls will return a new stringbuilder.
-**
-** A StringBuilder instance is cached in
-** Thread Local Storage and so there is one per thread
-**
-** Release - Place the specified builder in the cache if it is
-** not too big.
-** The stringbuilder should not be used after it has
-** been released.
-** Unbalanced Releases are perfectly acceptable. It
-** will merely cause the runtime to create a new
-** stringbuilder next time Acquire is called.
-**
-** GetStringAndRelease
-** - ToString() the stringbuilder, Release it to the
-** cache and return the resulting string
-**
-===========================================================*/
-
-using System.Threading;
-
-namespace System.Text
-{
- internal static class StringBuilderCache
- {
- private const int MAX_BUILDER_SIZE = 260;
-
- // WARNING: We allow diagnostic tools to directly inspect this member (t_cachedInstance).
- // See https://github.com/dotnet/corert/blob/master/Documentation/design-docs/diagnostics/diagnostics-tools-contract.md for more details.
- // Please do not change the type, the name, or the semantic usage of this member without understanding the implication for tools.
- // Get in touch with the diagnostics team if you have questions.
- [ThreadStatic]
- private static StringBuilder t_cachedInstance;
-
- public static StringBuilder Acquire(int capacity = StringBuilder.DefaultCapacity)
- {
- if (capacity <= MAX_BUILDER_SIZE)
- {
- StringBuilder sb = StringBuilderCache.t_cachedInstance;
- if (sb != null)
- {
- // Avoid stringbuilder block fragmentation by getting a new StringBuilder
- // when the requested size is larger than the current capacity
- if (capacity <= sb.Capacity)
- {
- StringBuilderCache.t_cachedInstance = null;
- sb.Clear();
- return sb;
- }
- }
- }
- return new StringBuilder(capacity);
- }
-
- public static void Release(StringBuilder sb)
- {
- if (sb.Capacity <= MAX_BUILDER_SIZE)
- {
- StringBuilderCache.t_cachedInstance = sb;
- }
- }
-
- public static string GetStringAndRelease(StringBuilder sb)
- {
- string result = sb.ToString();
- Release(sb);
- return result;
- }
- }
-}
diff --git a/src/System.Private.CoreLib/src/System/Threading/CancellationTokenRegistration.cs b/src/System.Private.CoreLib/src/System/Threading/CancellationTokenRegistration.cs
index d7180b16d..1125b26ef 100644
--- a/src/System.Private.CoreLib/src/System/Threading/CancellationTokenRegistration.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/CancellationTokenRegistration.cs
@@ -37,12 +37,13 @@ namespace System.Threading
public CancellationToken Token => m_callbackInfo?.CancellationTokenSource.Token ?? default(CancellationToken);
/// <summary>
- /// Attempts to deregister the item. If it's already being run, this may fail.
+ /// Attempts to unregister the item. If it's already being run, this may fail.
/// Entails a full memory fence.
/// </summary>
- /// <returns>True if the callback was found and deregistered, false otherwise.</returns>
+ /// <returns>True if the callback was found and unregistered, false otherwise.</returns>
+ // Called from System.Runtime.WindowsRuntime. Also see the proposal at https://github.com/dotnet/corefx/issues/14903.
//[FriendAccessAllowed]
- internal bool TryDeregister()
+ public bool Unregister()
{
if (m_registrationInfo.Source == null) //can be null for dummy registrations.
return false;
@@ -61,14 +62,14 @@ namespace System.Threading
/// <summary>
/// Disposes of the registration and unregisters the target callback from the associated
/// <see cref="T:System.Threading.CancellationToken">CancellationToken</see>.
- /// If the target callback is currently executing this method will wait until it completes, except
- /// in the degenerate cases where a callback method deregisters itself.
+ /// If the target callback is currently executing, this method will wait until it completes, except
+ /// in the degenerate cases where a callback method unregisters itself.
/// </summary>
public void Dispose()
{
// Remove the entry from the array.
// This call includes a full memory fence which prevents potential reorderings of the reads below
- bool deregisterOccured = TryDeregister();
+ bool unregisterOccured = Unregister();
// We guarantee that we will not return if the callback is being executed (assuming we are not currently called by the callback itself)
// We achieve this by the following rules:
@@ -76,8 +77,8 @@ namespace System.Threading
// - if the currently executing callback is this CTR, then waiting would deadlock. (We choose to return rather than deadlock)
// - if not, then this CTR cannot be the one executing, hence no need to wait
//
- // 2. if deregistration failed, and we are on a different thread, then the callback may be running under control of cts.Cancel()
- // => poll until cts.ExecutingCallback is not the one we are trying to deregister.
+ // 2. if unregistration failed, and we are on a different thread, then the callback may be running under control of cts.Cancel()
+ // => poll until cts.ExecutingCallback is not the one we are trying to unregister.
var callbackInfo = m_callbackInfo;
if (callbackInfo != null)
@@ -85,7 +86,7 @@ namespace System.Threading
var tokenSource = callbackInfo.CancellationTokenSource;
if (tokenSource.IsCancellationRequested && //running callbacks has commenced.
!tokenSource.IsCancellationCompleted && //running callbacks hasn't finished
- !deregisterOccured && //deregistration failed (ie the callback is missing from the list)
+ !unregisterOccured && //unregistration failed (ie the callback is missing from the list)
tokenSource.ThreadIDExecutingCallbacks != Environment.CurrentManagedThreadId) //the executingThreadID is not this threadID.
{
// Callback execution is in progress, the executing thread is different to us and has taken the callback for execution
diff --git a/src/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs b/src/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs
index 30302b936..9dbc0db08 100644
--- a/src/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs
@@ -1,15 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#pragma warning disable 0420
-
-//
-
-////////////////////////////////////////////////////////////////////////////////
using System.Collections.Generic;
using System.Diagnostics;
-using System.Runtime.InteropServices;
namespace System.Threading
{
@@ -33,46 +27,44 @@ namespace System.Threading
/// </remarks>
public class CancellationTokenSource : IDisposable
{
- //static sources that can be used as the backing source for 'fixed' CancellationTokens that never change state.
- private static readonly CancellationTokenSource _staticSource_Set = new CancellationTokenSource(true);
- private static readonly CancellationTokenSource _staticSource_NotCancelable = new CancellationTokenSource(false);
+ // static sources that can be used as the backing source for 'fixed' CancellationTokens that never change state.
+ internal static readonly CancellationTokenSource s_canceledSource = new CancellationTokenSource() { _state = NotifyingCompleteState };
+ internal static readonly CancellationTokenSource s_neverCanceledSource = new CancellationTokenSource() { _state = CannotBeCanceled };
- //Note: the callback lists array is only created on first registration.
- // the actual callback lists are only created on demand.
- // Storing a registered callback costs around >60bytes, hence some overhead for the lists array is OK
+ // Note: the callback lists array is only created on first registration.
+ // the actual callback lists are only created on demand.
+ // Storing a registered callback costs around >60bytes, hence some overhead for the lists array is OK
// At most 24 lists seems reasonable, and caps the cost of the listsArray to 96bytes(32-bit,24-way) or 192bytes(64-bit,24-way).
private static readonly int s_nLists = (PlatformHelper.ProcessorCount > 24) ? 24 : PlatformHelper.ProcessorCount;
- private volatile ManualResetEvent m_kernelEvent; //lazily initialized if required.
+ private volatile ManualResetEvent _kernelEvent; //lazily initialized if required.
- private volatile SparselyPopulatedArray<CancellationCallbackInfo>[] m_registeredCallbacksLists;
+ private volatile SparselyPopulatedArray<CancellationCallbackInfo>[] _registeredCallbacksLists;
- // legal values for m_state
- private const int CANNOT_BE_CANCELED = 0;
- private const int NOT_CANCELED = 1;
- private const int NOTIFYING = 2;
- private const int NOTIFYINGCOMPLETE = 3;
+ // legal values for _state
+ private const int CannotBeCanceled = 0;
+ private const int NotCanceledState = 1;
+ private const int NotifyingState = 2;
+ private const int NotifyingCompleteState = 3;
- //m_state uses the pattern "volatile int32 reads, with cmpxch writes" which is safe for updates and cannot suffer torn reads.
- private volatile int m_state;
+ //_state uses the pattern "volatile int32 reads, with cmpxch writes" which is safe for updates and cannot suffer torn reads.
+ private volatile int _state;
+ /// <summary>The ID of the thread currently executing the main body of CTS.Cancel()</summary>
+ /// <remarks>
+ /// This helps us to know if a call to ctr.Dispose() is running 'within' a cancellation callback.
+ /// This is updated as we move between the main thread calling cts.Cancel() and any syncContexts
+ /// that are used to actually run the callbacks.
+ /// </remarks>
+ private volatile int _threadIDExecutingCallbacks = -1;
- /// The ID of the thread currently executing the main body of CTS.Cancel()
- /// this helps us to know if a call to ctr.Dispose() is running 'within' a cancellation callback.
- /// This is updated as we move between the main thread calling cts.Cancel() and any syncContexts that are used to
- /// actually run the callbacks.
- private volatile int m_threadIDExecutingCallbacks = -1;
-
- private bool m_disposed;
+ private bool _disposed;
// we track the running callback to assist ctr.Dispose() to wait for the target callback to complete.
- private volatile CancellationCallbackInfo m_executingCallback;
+ private volatile CancellationCallbackInfo _executingCallback;
// provided for CancelAfter and timer-related constructors
- private volatile Timer m_timer;
-
- // ----------------------
- // ** public properties
+ private volatile Timer _timer;
/// <summary>
/// Gets whether cancellation has been requested for this <see
@@ -94,34 +86,25 @@ namespace System.Threading
/// canceled concurrently.
/// </para>
/// </remarks>
- public bool IsCancellationRequested
- {
- get { return m_state >= NOTIFYING; }
- }
+ public bool IsCancellationRequested => _state >= NotifyingState;
/// <summary>
/// A simple helper to determine whether cancellation has finished.
/// </summary>
- internal bool IsCancellationCompleted
- {
- get { return m_state == NOTIFYINGCOMPLETE; }
- }
+ internal bool IsCancellationCompleted => _state == NotifyingCompleteState;
/// <summary>
/// A simple helper to determine whether disposal has occurred.
/// </summary>
- internal bool IsDisposed
- {
- get { return m_disposed; }
- }
+ internal bool IsDisposed => _disposed;
/// <summary>
/// The ID of the thread that is running callbacks.
/// </summary>
internal int ThreadIDExecutingCallbacks
{
- set { m_threadIDExecutingCallbacks = value; }
- get { return m_threadIDExecutingCallbacks; }
+ get => _threadIDExecutingCallbacks;
+ set => _threadIDExecutingCallbacks = value;
}
/// <summary>
@@ -140,36 +123,25 @@ namespace System.Threading
return new CancellationToken(this);
}
}
-
- // ----------------------
- // ** internal and private properties.
-
- /// <summary>
- ///
- /// </summary>
internal bool CanBeCanceled
{
- get { return m_state != CANNOT_BE_CANCELED; }
+ get { return _state != CannotBeCanceled; }
}
-
- /// <summary>
- ///
- /// </summary>
internal WaitHandle WaitHandle
{
get
{
ThrowIfDisposed();
- // fast path if already allocated.
- if (m_kernelEvent != null)
- return m_kernelEvent;
+ // Return the handle if it was already allocated.
+ if (_kernelEvent != null)
+ return _kernelEvent;
- // lazy-init the mre.
+ // Lazily-initialize the handle.
ManualResetEvent mre = new ManualResetEvent(false);
- if (Interlocked.CompareExchange(ref m_kernelEvent, mre, null) != null)
+ if (Interlocked.CompareExchange(ref _kernelEvent, mre, null) != null)
{
- ((IDisposable)mre).Dispose();
+ mre.Dispose();
}
// There is a race condition between checking IsCancellationRequested and setting the event.
@@ -177,9 +149,9 @@ namespace System.Threading
// 1. if IsCancellationRequested = true, then we will call Set()
// 2. if IsCancellationRequested = false, then NotifyCancellation will see that the event exists, and will call Set().
if (IsCancellationRequested)
- m_kernelEvent.Set();
+ _kernelEvent.Set();
- return m_kernelEvent;
+ return _kernelEvent;
}
}
@@ -187,10 +159,7 @@ namespace System.Threading
/// <summary>
/// The currently executing callback
/// </summary>
- internal CancellationCallbackInfo ExecutingCallback
- {
- get { return m_executingCallback; }
- }
+ internal CancellationCallbackInfo ExecutingCallback => _executingCallback;
#if DEBUG
/// <summary>
@@ -202,7 +171,7 @@ namespace System.Threading
{
get
{
- SparselyPopulatedArray<CancellationCallbackInfo>[] callbackLists = m_registeredCallbacksLists;
+ SparselyPopulatedArray<CancellationCallbackInfo>[] callbackLists = _registeredCallbacksLists;
if (callbackLists == null)
return 0;
@@ -227,23 +196,10 @@ namespace System.Threading
}
#endif
- // ** Public Constructors
-
/// <summary>
/// Initializes the <see cref="T:System.Threading.CancellationTokenSource"/>.
/// </summary>
- public CancellationTokenSource()
- {
- m_state = NOT_CANCELED;
- }
-
- // ** Private constructors for static sources.
- // set=false ==> cannot be canceled.
- // set=true ==> is canceled.
- private CancellationTokenSource(bool set)
- {
- m_state = set ? NOTIFYINGCOMPLETE : CANNOT_BE_CANCELED;
- }
+ public CancellationTokenSource() => _state = NotCanceledState;
/// <summary>
/// Constructs a <see cref="T:System.Threading.CancellationTokenSource"/> that will be canceled after a specified time span.
@@ -267,7 +223,7 @@ namespace System.Threading
public CancellationTokenSource(TimeSpan delay)
{
long totalMilliseconds = (long)delay.TotalMilliseconds;
- if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
{
throw new ArgumentOutOfRangeException(nameof(delay));
}
@@ -294,7 +250,7 @@ namespace System.Threading
/// canceled already.
/// </para>
/// </remarks>
- public CancellationTokenSource(Int32 millisecondsDelay)
+ public CancellationTokenSource(int millisecondsDelay)
{
if (millisecondsDelay < -1)
{
@@ -305,14 +261,12 @@ namespace System.Threading
}
// Common initialization logic when constructing a CTS with a delay parameter
- private void InitializeWithTimer(Int32 millisecondsDelay)
+ private void InitializeWithTimer(int millisecondsDelay)
{
- m_state = NOT_CANCELED;
- m_timer = new Timer(s_timerCallback, this, millisecondsDelay, -1);
+ _state = NotCanceledState;
+ _timer = new Timer(s_timerCallback, this, millisecondsDelay, -1);
}
- // ** Public Methods
-
/// <summary>
/// Communicates a request for cancellation.
/// </summary>
@@ -334,10 +288,7 @@ namespace System.Threading
/// by the registered callbacks on the associated <see cref="T:System.Threading.CancellationToken"/>.</exception>
/// <exception cref="T:System.ObjectDisposedException">This <see
/// cref="T:System.Threading.CancellationTokenSource"/> has been disposed.</exception>
- public void Cancel()
- {
- Cancel(false);
- }
+ public void Cancel() => Cancel(false);
/// <summary>
/// Communicates a request for cancellation.
@@ -391,14 +342,13 @@ namespace System.Threading
/// </para>
/// <para>
/// Subsequent calls to CancelAfter will reset the delay for this
- /// <see cref="T:System.Threading.CancellationTokenSource"/>, if it has not been
- /// canceled already.
+ /// <see cref="T:System.Threading.CancellationTokenSource"/>, if it has not been canceled already.
/// </para>
/// </remarks>
public void CancelAfter(TimeSpan delay)
{
long totalMilliseconds = (long)delay.TotalMilliseconds;
- if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
{
throw new ArgumentOutOfRangeException(nameof(delay));
}
@@ -430,7 +380,7 @@ namespace System.Threading
/// canceled already.
/// </para>
/// </remarks>
- public void CancelAfter(Int32 millisecondsDelay)
+ public void CancelAfter(int millisecondsDelay)
{
ThrowIfDisposed();
@@ -439,7 +389,10 @@ namespace System.Threading
throw new ArgumentOutOfRangeException(nameof(millisecondsDelay));
}
- if (IsCancellationRequested) return;
+ if (IsCancellationRequested)
+ {
+ return;
+ }
// There is a race condition here as a Cancel could occur between the check of
// IsCancellationRequested and the creation of the timer. This is benign; in the
@@ -450,26 +403,25 @@ namespace System.Threading
// expired and Disposed itself). But this would be considered bad behavior, as
// Dispose() is not thread-safe and should not be called concurrently with CancelAfter().
- if (m_timer == null)
+ if (_timer == null)
{
// Lazily initialize the timer in a thread-safe fashion.
// Initially set to "never go off" because we don't want to take a
// chance on a timer "losing" the initialization and then
// cancelling the token before it (the timer) can be disposed.
Timer newTimer = new Timer(s_timerCallback, this, -1, -1);
- if (Interlocked.CompareExchange(ref m_timer, newTimer, null) != null)
+ if (Interlocked.CompareExchange(ref _timer, newTimer, null) != null)
{
// We did not initialize the timer. Dispose the new timer.
newTimer.Dispose();
}
}
-
- // It is possible that m_timer has already been disposed, so we must do
+ // It is possible that _timer has already been disposed, so we must do
// the following in a try/catch block.
try
{
- m_timer.Change(millisecondsDelay, -1);
+ _timer.Change(millisecondsDelay, -1);
}
catch (ObjectDisposedException)
{
@@ -495,7 +447,7 @@ namespace System.Threading
// against this race condition.
try
{
- cts.Cancel(); // will take care of disposing of m_timer
+ cts.Cancel(); // will take care of disposing of _timer
}
catch (ObjectDisposedException)
{
@@ -523,11 +475,9 @@ namespace System.Threading
/// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
- // There is nothing to do if disposing=false because the CancellationTokenSource holds no unmanaged resources.
-
- if (disposing && !m_disposed)
+ if (disposing && !_disposed)
{
- //NOTE: We specifically tolerate that a callback can be deregistered
+ //NOTE: We specifically tolerate that a callback can be unregistered
// after the CTS has been disposed and/or concurrently with cts.Dispose().
// This is safe without locks because the reg.Dispose() only
// mutates a sparseArrayFragment and then reads from properties of the CTS that are not
@@ -535,8 +485,8 @@ namespace System.Threading
//
// We also tolerate that a callback can be registered after the CTS has been
// disposed. This is safe without locks because InternalRegister is tolerant
- // of m_registeredCallbacksLists becoming null during its execution. However,
- // we run the acceptable risk of m_registeredCallbacksLists getting reinitialized
+ // of _registeredCallbacksLists becoming null during its execution. However,
+ // we run the acceptable risk of _registeredCallbacksLists getting reinitialized
// to non-null if there is a race between Dispose and Register, in which case this
// instance may unnecessarily hold onto a registered callback. But that's no worse
// than if Dispose wasn't safe to use concurrently, as Dispose would never be called,
@@ -549,57 +499,43 @@ namespace System.Threading
// internal source of cancellation, then Disposes of that linked source, which could
// happen at the same time the external entity is requesting cancellation).
- m_timer?.Dispose(); // Timer.Dispose is thread-safe
+ _timer?.Dispose(); // Timer.Dispose is thread-safe
// registered callbacks are now either complete or will never run, due to guarantees made by ctr.Dispose()
// so we can now perform main disposal work without risk of linking callbacks trying to use this CTS.
- m_registeredCallbacksLists = null; // free for GC; Cancel correctly handles a null field
+ _registeredCallbacksLists = null; // free for GC; Cancel correctly handles a null field
// If a kernel event was created via WaitHandle, we'd like to Dispose of it. However,
// we only want to do so if it's not being used by Cancel concurrently. First, we
// interlocked exchange it to be null, and then we check whether cancellation is currently
// in progress. NotifyCancellation will only try to set the event if it exists after it's
- // transitioned to and while it's in the NOTIFYING state.
- if (m_kernelEvent != null)
+ // transitioned to and while it's in the NotifyingState.
+ if (_kernelEvent != null)
{
- ManualResetEvent mre = Interlocked.Exchange(ref m_kernelEvent, null);
- if (mre != null && m_state != NOTIFYING)
+ ManualResetEvent mre = Interlocked.Exchange(ref _kernelEvent, null);
+ if (mre != null && _state != NotifyingState)
{
mre.Dispose();
}
}
- m_disposed = true;
+ _disposed = true;
}
}
- // -- Internal methods.
-
/// <summary>
/// Throws an exception if the source has been disposed.
/// </summary>
internal void ThrowIfDisposed()
{
- if (m_disposed)
+ if (_disposed)
ThrowObjectDisposedException();
}
- // separation enables inlining of ThrowIfDisposed
- private static void ThrowObjectDisposedException()
- {
+ /// <summary>Throws an <see cref="ObjectDisposedException"/>. Separated out from ThrowIfDisposed to help with inlining.</summary>
+ private static void ThrowObjectDisposedException() =>
throw new ObjectDisposedException(null, SR.CancellationTokenSource_Disposed);
- }
-
- /// <summary>
- /// InternalGetStaticSource()
- /// </summary>
- /// <param name="set">Whether the source should be set.</param>
- /// <returns>A static source to be shared among multiple tokens.</returns>
- internal static CancellationTokenSource InternalGetStaticSource(bool set)
- {
- return set ? _staticSource_Set : _staticSource_NotCancelable;
- }
/// <summary>
/// Registers a callback object. If cancellation has already occurred, the
@@ -625,11 +561,11 @@ namespace System.Threading
// while at the same time not paying any non-negligible overhead. The simple compromise
// is to check whether we're disposed (not volatile), and if we see we are, to return an empty
// registration, just as if CanBeCanceled was false for the check made in CancellationToken.Register.
- // If there's a race and m_disposed is false even though it's been disposed, or if the disposal request
- // comes in after this line, we simply run the minor risk of having m_registeredCallbacksLists reinitialized
+ // If there's a race and _disposed is false even though it's been disposed, or if the disposal request
+ // comes in after this line, we simply run the minor risk of having _registeredCallbacksLists reinitialized
// (after it was cleared to null during Dispose).
- if (m_disposed)
+ if (_disposed)
return new CancellationTokenRegistration();
int myIndex = Environment.CurrentManagedThreadId % s_nLists;
@@ -639,11 +575,11 @@ namespace System.Threading
new CancellationCallbackInfo(callback, stateForCallback, executionContext, this);
//allocate the callback list array
- var registeredCallbacksLists = m_registeredCallbacksLists;
+ var registeredCallbacksLists = _registeredCallbacksLists;
if (registeredCallbacksLists == null)
{
SparselyPopulatedArray<CancellationCallbackInfo>[] list = new SparselyPopulatedArray<CancellationCallbackInfo>[s_nLists];
- registeredCallbacksLists = Interlocked.CompareExchange(ref m_registeredCallbacksLists, list, null);
+ registeredCallbacksLists = Interlocked.CompareExchange(ref _registeredCallbacksLists, list, null);
if (registeredCallbacksLists == null) registeredCallbacksLists = list;
}
@@ -665,9 +601,9 @@ namespace System.Threading
// If a cancellation has since come in, we will try to undo the registration and run the callback ourselves.
// (this avoids leaving the callback orphaned)
- bool deregisterOccurred = registration.TryDeregister();
+ bool unregisterOccurred = registration.Unregister();
- if (!deregisterOccurred)
+ if (!unregisterOccurred)
{
// The thread that is running Cancel() snagged our callback for execution.
// So we don't need to run it, but we do return the registration so that
@@ -681,29 +617,22 @@ namespace System.Threading
return new CancellationTokenRegistration();
}
- /// <summary>
- ///
- /// </summary>
private void NotifyCancellation(bool throwOnFirstException)
{
- // fast-path test to check if Notify has been called previously
- if (IsCancellationRequested)
- return;
-
// If we're the first to signal cancellation, do the main extra work.
- if (Interlocked.CompareExchange(ref m_state, NOTIFYING, NOT_CANCELED) == NOT_CANCELED)
+ if (!IsCancellationRequested && Interlocked.CompareExchange(ref _state, NotifyingState, NotCanceledState) == NotCanceledState)
{
// Dispose of the timer, if any. Dispose may be running concurrently here, but Timer.Dispose is thread-safe.
- m_timer?.Dispose();
+ _timer?.Dispose();
// Record the threadID being used for running the callbacks.
ThreadIDExecutingCallbacks = Environment.CurrentManagedThreadId;
// Set the event if it's been lazily initialized and hasn't yet been disposed of. Dispose may
- // be running concurrently, in which case either it'll have set m_kernelEvent back to null and
+ // be running concurrently, in which case either it'll have set _kernelEvent back to null and
// we won't see it here, or it'll see that we've transitioned to NOTIFYING and will skip disposing it,
// leaving cleanup to finalization.
- m_kernelEvent?.Set(); // update the MRE value.
+ _kernelEvent?.Set(); // update the MRE value.
// - late enlisters to the Canceled event will have their callbacks called immediately in the Register() methods.
// - Callbacks are not called inside a lock.
@@ -728,13 +657,13 @@ namespace System.Threading
// Design decision: call the delegates in LIFO order so that callbacks fire 'deepest first'.
// This is intended to help with nesting scenarios so that child enlisters cancel before their parents.
LowLevelListWithIList<Exception> exceptionList = null;
- SparselyPopulatedArray<CancellationCallbackInfo>[] callbackLists = m_registeredCallbacksLists;
+ SparselyPopulatedArray<CancellationCallbackInfo>[] callbackLists = _registeredCallbacksLists;
// If there are no callbacks to run, we can safely exit. Any race conditions to lazy initialize it
// will see IsCancellationRequested and will then run the callback themselves.
if (callbackLists == null)
{
- Interlocked.Exchange(ref m_state, NOTIFYINGCOMPLETE);
+ Interlocked.Exchange(ref _state, NotifyingCompleteState);
return;
}
@@ -758,8 +687,8 @@ namespace System.Threading
// 3. execute the callback
// re:#2 we do the remove on the syncCtx so that we can be sure we have control of the syncCtx before
// grabbing the callback. This prevents a deadlock if ctr.Dispose() might run on the syncCtx too.
- m_executingCallback = currArrayFragment[i];
- if (m_executingCallback != null)
+ _executingCallback = currArrayFragment[i];
+ if (_executingCallback != null)
{
//Transition to the target sync context (if necessary), and continue our work there.
CancellationCallbackCoreWorkArguments args = new CancellationCallbackCoreWorkArguments(currArrayFragment, i);
@@ -768,7 +697,7 @@ namespace System.Threading
// We assume that syncCtx.Send() has forwarded on user exceptions when appropriate.
try
{
- var wsc = m_executingCallback as CancellationCallbackInfo.WithSyncContext;
+ var wsc = _executingCallback as CancellationCallbackInfo.WithSyncContext;
if (wsc != null)
{
Debug.Assert(wsc.TargetSyncContext != null, "Should only have derived CCI if non-null SyncCtx");
@@ -801,14 +730,14 @@ namespace System.Threading
}
finally
{
- m_state = NOTIFYINGCOMPLETE;
- m_executingCallback = null;
+ _state = NotifyingCompleteState;
+ _executingCallback = null;
Interlocked.MemoryBarrier(); // for safety, prevent reorderings crossing this point and seeing inconsistent state.
}
if (exceptionList != null)
{
- Debug.Assert(exceptionList.Count > 0, "Expected exception count > 0");
+ Debug.Assert(exceptionList.Count > 0, $"Expected {exceptionList.Count} > 0");
throw new AggregateException(exceptionList);
}
}
@@ -823,15 +752,14 @@ namespace System.Threading
{
// remove the intended callback..and ensure that it worked.
// otherwise the callback has disappeared in the interim and we can immediately return.
- CancellationCallbackInfo callback = args.m_currArrayFragment.SafeAtomicRemove(args.m_currArrayIndex, m_executingCallback);
- if (callback == m_executingCallback)
+ CancellationCallbackInfo callback = args._currArrayFragment.SafeAtomicRemove(args._currArrayIndex, _executingCallback);
+ if (callback == _executingCallback)
{
callback.CancellationTokenSource.ThreadIDExecutingCallbacks = Environment.CurrentManagedThreadId;
callback.ExecuteCallback();
}
}
-
/// <summary>
/// Creates a <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> that will be in the canceled state
/// when any of the source tokens are in the canceled state.
@@ -906,7 +834,7 @@ namespace System.Threading
protected override void Dispose(bool disposing)
{
- if (!disposing || m_disposed) return;
+ if (!disposing || _disposed) return;
_reg1.Dispose();
base.Dispose(disposing);
}
@@ -925,7 +853,7 @@ namespace System.Threading
protected override void Dispose(bool disposing)
{
- if (!disposing || m_disposed) return;
+ if (!disposing || _disposed) return;
_reg1.Dispose();
_reg2.Dispose();
base.Dispose(disposing);
@@ -936,17 +864,17 @@ namespace System.Threading
{
internal static readonly Action<object> s_linkedTokenCancelDelegate =
s => ((CancellationTokenSource)s).NotifyCancellation(throwOnFirstException: false); // skip ThrowIfDisposed() check in Cancel()
- private CancellationTokenRegistration[] m_linkingRegistrations;
+ private CancellationTokenRegistration[] _linkingRegistrations;
internal LinkedNCancellationTokenSource(params CancellationToken[] tokens)
{
- m_linkingRegistrations = new CancellationTokenRegistration[tokens.Length];
+ _linkingRegistrations = new CancellationTokenRegistration[tokens.Length];
for (int i = 0; i < tokens.Length; i++)
{
if (tokens[i].CanBeCanceled)
{
- m_linkingRegistrations[i] = tokens[i].InternalRegisterWithoutEC(s_linkedTokenCancelDelegate, this);
+ _linkingRegistrations[i] = tokens[i].InternalRegisterWithoutEC(s_linkedTokenCancelDelegate, this);
}
// Empty slots in the array will be default(CancellationTokenRegistration), which are nops to Dispose.
// Based on usage patterns, such occurrences should also be rare, such that it's not worth resizing
@@ -956,13 +884,13 @@ namespace System.Threading
protected override void Dispose(bool disposing)
{
- if (!disposing || m_disposed)
+ if (!disposing || _disposed)
return;
- CancellationTokenRegistration[] linkingRegistrations = m_linkingRegistrations;
+ CancellationTokenRegistration[] linkingRegistrations = _linkingRegistrations;
if (linkingRegistrations != null)
{
- m_linkingRegistrations = null; // release for GC once we're done enumerating
+ _linkingRegistrations = null; // release for GC once we're done enumerating
for (int i = 0; i < linkingRegistrations.Length; i++)
{
linkingRegistrations[i].Dispose();
@@ -980,13 +908,13 @@ namespace System.Threading
// Helper struct for passing data to the target sync context
internal struct CancellationCallbackCoreWorkArguments
{
- internal SparselyPopulatedArrayFragment<CancellationCallbackInfo> m_currArrayFragment;
- internal int m_currArrayIndex;
+ internal SparselyPopulatedArrayFragment<CancellationCallbackInfo> _currArrayFragment;
+ internal int _currArrayIndex;
public CancellationCallbackCoreWorkArguments(SparselyPopulatedArrayFragment<CancellationCallbackInfo> currArrayFragment, int currArrayIndex)
{
- m_currArrayFragment = currArrayFragment;
- m_currArrayIndex = currArrayIndex;
+ _currArrayFragment = currArrayFragment;
+ _currArrayIndex = currArrayIndex;
}
}
@@ -1078,8 +1006,8 @@ namespace System.Threading
/// <typeparam name="T">The kind of elements contained within.</typeparam>
internal class SparselyPopulatedArray<T> where T : class
{
- private readonly SparselyPopulatedArrayFragment<T> m_head;
- private volatile SparselyPopulatedArrayFragment<T> m_tail;
+ private readonly SparselyPopulatedArrayFragment<T> _head;
+ private volatile SparselyPopulatedArrayFragment<T> _tail;
/// <summary>
/// Allocates a new array with the given initial size.
@@ -1087,7 +1015,7 @@ namespace System.Threading
/// <param name="initialSize">How many array slots to pre-allocate.</param>
internal SparselyPopulatedArray(int initialSize)
{
- m_head = m_tail = new SparselyPopulatedArrayFragment<T>(initialSize);
+ _head = _tail = new SparselyPopulatedArrayFragment<T>(initialSize);
}
#if DEBUG
@@ -1097,7 +1025,7 @@ namespace System.Threading
/// </summary>
internal SparselyPopulatedArrayFragment<T> Head
{
- get { return m_head; }
+ get { return _head; }
}
#endif
@@ -1106,7 +1034,7 @@ namespace System.Threading
/// </summary>
internal SparselyPopulatedArrayFragment<T> Tail
{
- get { return m_tail; }
+ get { return _tail; }
}
/// <summary>
@@ -1114,36 +1042,36 @@ namespace System.Threading
/// If no slots are available, the array is grown. The method doesn't return until successful.
/// </summary>
/// <param name="element">The element to add.</param>
- /// <returns>Information about where the add happened, to enable O(1) deregistration.</returns>
+ /// <returns>Information about where the add happened, to enable O(1) unregistration.</returns>
internal SparselyPopulatedArrayAddInfo<T> Add(T element)
{
while (true)
{
// Get the tail, and ensure it's up to date.
- SparselyPopulatedArrayFragment<T> tail = m_tail;
- while (tail.m_next != null)
- m_tail = (tail = tail.m_next);
+ SparselyPopulatedArrayFragment<T> tail = _tail;
+ while (tail._next != null)
+ _tail = (tail = tail._next);
// Search for a free index, starting from the tail.
SparselyPopulatedArrayFragment<T> curr = tail;
while (curr != null)
{
const int RE_SEARCH_THRESHOLD = -10; // Every 10 skips, force a search.
- if (curr.m_freeCount < 1)
- --curr.m_freeCount;
+ if (curr._freeCount < 1)
+ --curr._freeCount;
- if (curr.m_freeCount > 0 || curr.m_freeCount < RE_SEARCH_THRESHOLD)
+ if (curr._freeCount > 0 || curr._freeCount < RE_SEARCH_THRESHOLD)
{
int c = curr.Length;
// We'll compute a start offset based on how many free slots we think there
- // are. This optimizes for ordinary the LIFO deregistration pattern, and is
+ // are. This optimizes for ordinary the LIFO unregistration pattern, and is
// far from perfect due to the non-threadsafe ++ and -- of the free counter.
- int start = ((c - curr.m_freeCount) % c);
+ int start = ((c - curr._freeCount) % c);
if (start < 0)
{
start = 0;
- curr.m_freeCount--; // Too many free elements; fix up.
+ curr._freeCount--; // Too many free elements; fix up.
}
Debug.Assert(start >= 0 && start < c, "start is outside of bounds");
@@ -1152,29 +1080,29 @@ namespace System.Threading
{
// If the slot is null, try to CAS our element into it.
int tryIndex = (start + i) % c;
- Debug.Assert(tryIndex >= 0 && tryIndex < curr.m_elements.Length, "tryIndex is outside of bounds");
+ Debug.Assert(tryIndex >= 0 && tryIndex < curr._elements.Length, "tryIndex is outside of bounds");
- if (curr.m_elements[tryIndex] == null && Interlocked.CompareExchange(ref curr.m_elements[tryIndex], element, null) == null)
+ if (curr._elements[tryIndex] == null && Interlocked.CompareExchange(ref curr._elements[tryIndex], element, null) == null)
{
// We adjust the free count by --. Note: if this drops to 0, we will skip
// the fragment on the next search iteration. Searching threads will -- the
// count and force a search every so often, just in case fragmentation occurs.
- int newFreeCount = curr.m_freeCount - 1;
- curr.m_freeCount = newFreeCount > 0 ? newFreeCount : 0;
+ int newFreeCount = curr._freeCount - 1;
+ curr._freeCount = newFreeCount > 0 ? newFreeCount : 0;
return new SparselyPopulatedArrayAddInfo<T>(curr, tryIndex);
}
}
}
- curr = curr.m_prev;
+ curr = curr._prev;
}
// If we got here, we need to add a new chunk to the tail and try again.
SparselyPopulatedArrayFragment<T> newTail = new SparselyPopulatedArrayFragment<T>(
- tail.m_elements.Length == 4096 ? 4096 : tail.m_elements.Length * 2, tail);
- if (Interlocked.CompareExchange(ref tail.m_next, newTail, null) == null)
+ tail._elements.Length == 4096 ? 4096 : tail._elements.Length * 2, tail);
+ if (Interlocked.CompareExchange(ref tail._next, newTail, null) == null)
{
- m_tail = newTail;
+ _tail = newTail;
}
}
}
@@ -1186,25 +1114,25 @@ namespace System.Threading
/// </summary>
internal struct SparselyPopulatedArrayAddInfo<T> where T : class
{
- private SparselyPopulatedArrayFragment<T> m_source;
- private int m_index;
+ private SparselyPopulatedArrayFragment<T> _source;
+ private int _index;
internal SparselyPopulatedArrayAddInfo(SparselyPopulatedArrayFragment<T> source, int index)
{
Debug.Assert(source != null);
Debug.Assert(index >= 0 && index < source.Length);
- m_source = source;
- m_index = index;
+ _source = source;
+ _index = index;
}
internal SparselyPopulatedArrayFragment<T> Source
{
- get { return m_source; }
+ get { return _source; }
}
internal int Index
{
- get { return m_index; }
+ get { return _index; }
}
}
@@ -1214,10 +1142,10 @@ namespace System.Threading
/// <typeparam name="T">The kind of elements contained within.</typeparam>
internal class SparselyPopulatedArrayFragment<T> where T : class
{
- internal readonly T[] m_elements; // The contents, sparsely populated (with nulls).
- internal volatile int m_freeCount; // A hint of the number of free elements.
- internal volatile SparselyPopulatedArrayFragment<T> m_next; // The next fragment in the chain.
- internal volatile SparselyPopulatedArrayFragment<T> m_prev; // The previous fragment in the chain.
+ internal readonly T[] _elements; // The contents, sparsely populated (with nulls).
+ internal volatile int _freeCount; // A hint of the number of free elements.
+ internal volatile SparselyPopulatedArrayFragment<T> _next; // The next fragment in the chain.
+ internal volatile SparselyPopulatedArrayFragment<T> _prev; // The previous fragment in the chain.
internal SparselyPopulatedArrayFragment(int size) : this(size, null)
{
@@ -1225,31 +1153,31 @@ namespace System.Threading
internal SparselyPopulatedArrayFragment(int size, SparselyPopulatedArrayFragment<T> prev)
{
- m_elements = new T[size];
- m_freeCount = size;
- m_prev = prev;
+ _elements = new T[size];
+ _freeCount = size;
+ _prev = prev;
}
internal T this[int index]
{
- get { return Volatile.Read<T>(ref m_elements[index]); }
+ get { return Volatile.Read<T>(ref _elements[index]); }
}
internal int Length
{
- get { return m_elements.Length; }
+ get { return _elements.Length; }
}
#if DEBUG
// Used in DEBUG mode by CancellationTokenSource.CallbackCount
internal SparselyPopulatedArrayFragment<T> Next
{
- get { return m_next; }
+ get { return _next; }
}
#endif
internal SparselyPopulatedArrayFragment<T> Prev
{
- get { return m_prev; }
+ get { return _prev; }
}
// only removes the item at the specified index if it is still the expected one.
@@ -1258,9 +1186,9 @@ namespace System.Threading
// otherwise the remove did not occur.
internal T SafeAtomicRemove(int index, T expectedElement)
{
- T prevailingValue = Interlocked.CompareExchange(ref m_elements[index], null, expectedElement);
+ T prevailingValue = Interlocked.CompareExchange(ref _elements[index], null, expectedElement);
if (prevailingValue != null)
- ++m_freeCount;
+ ++_freeCount;
return prevailingValue;
}
}
diff --git a/src/System.Private.CoreLib/src/System/Threading/ClrThreadPool.CpuUtilizationReader.Windows.cs b/src/System.Private.CoreLib/src/System/Threading/ClrThreadPool.CpuUtilizationReader.Windows.cs
index b7d7f8ae4..915f11106 100644
--- a/src/System.Private.CoreLib/src/System/Threading/ClrThreadPool.CpuUtilizationReader.Windows.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/ClrThreadPool.CpuUtilizationReader.Windows.cs
@@ -28,7 +28,7 @@ namespace System.Threading
{
int error = Marshal.GetLastWin32Error();
var exception = new OutOfMemoryException();
- exception.SetErrorCode(error);
+ exception.HResult = error;
throw exception;
}
diff --git a/src/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Unix.cs b/src/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Unix.cs
index 04e124cc0..5f1aeb3e4 100644
--- a/src/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Unix.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Unix.cs
@@ -2,23 +2,19 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using Microsoft.Win32.SafeHandles;
using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
namespace System.Threading
{
public partial class EventWaitHandle
{
- private static void VerifyNameForCreate(string name)
+ private void CreateEventCore(bool initialState, EventResetMode mode, string name, out bool createdNew)
{
if (name != null)
- {
throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
- }
- }
-
- private void CreateEventCore(bool initialState, EventResetMode mode, string name, out bool createdNew)
- {
- Debug.Assert(name == null);
SafeWaitHandle = WaitSubsystem.NewEvent(initialState, mode);
createdNew = true;
@@ -29,16 +25,46 @@ namespace System.Threading
throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
}
- private static bool ResetCore(IntPtr handle)
+ public bool Reset()
{
- WaitSubsystem.ResetEvent(handle);
- return true;
+ SafeWaitHandle waitHandle = ValidateHandle();
+ try
+ {
+ WaitSubsystem.ResetEvent(waitHandle.DangerousGetHandle());
+ return true;
+ }
+ finally
+ {
+ waitHandle.DangerousRelease();
+ }
}
- private static bool SetCore(IntPtr handle)
+ public bool Set()
{
- WaitSubsystem.SetEvent(handle);
- return true;
+ SafeWaitHandle waitHandle = ValidateHandle();
+ try
+ {
+ WaitSubsystem.SetEvent(waitHandle.DangerousGetHandle());
+ return true;
+ }
+ finally
+ {
+ waitHandle.DangerousRelease();
+ }
+ }
+
+ private SafeWaitHandle ValidateHandle()
+ {
+ // The field value is modifiable via the public <see cref="WaitHandle.SafeWaitHandle"/> property, save it locally
+ // to ensure that one instance is used in all places in this method
+ SafeWaitHandle waitHandle = _waitHandle;
+ if (waitHandle == null)
+ {
+ ThrowInvalidHandleException();
+ }
+
+ waitHandle.DangerousAddRef();
+ return waitHandle;
}
}
}
diff --git a/src/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs b/src/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs
deleted file mode 100644
index 2800fc951..000000000
--- a/src/System.Private.CoreLib/src/System/Threading/EventWaitHandle.Windows.cs
+++ /dev/null
@@ -1,116 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-using Microsoft.Win32.SafeHandles;
-
-namespace System.Threading
-{
- public partial class EventWaitHandle
- {
- private const uint AccessRights = (uint)(Interop.Constants.MaximumAllowed | Interop.Constants.Synchronize | Interop.Constants.EventModifyState);
-
- private EventWaitHandle(SafeWaitHandle handle)
- {
- SafeWaitHandle = handle;
- }
-
- private static void VerifyNameForCreate(string name)
- {
- if (null != name && Interop.Kernel32.MAX_PATH < name.Length)
- {
- throw new ArgumentException(SR.Format(SR.Argument_WaitHandleNameTooLong, Interop.Kernel32.MAX_PATH), nameof(name));
- }
- }
-
- private void CreateEventCore(bool initialState, EventResetMode mode, string name, out bool createdNew)
- {
- Debug.Assert((mode == EventResetMode.AutoReset) || (mode == EventResetMode.ManualReset));
- Debug.Assert(name == null || name.Length <= Interop.Kernel32.MAX_PATH);
-
- uint eventFlags = initialState ? (uint)Interop.Constants.CreateEventInitialSet : 0;
- if (mode == EventResetMode.ManualReset)
- {
- eventFlags |= (uint)Interop.Constants.CreateEventManualReset;
- }
-
- SafeWaitHandle _handle = Interop.mincore.CreateEventEx(IntPtr.Zero, name, eventFlags, AccessRights);
-
- if (_handle.IsInvalid)
- {
- int errorCode = Marshal.GetLastWin32Error();
- _handle.SetHandleAsInvalid();
- if (null != name && 0 != name.Length && Interop.Errors.ERROR_INVALID_HANDLE == errorCode)
- throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
- throw ExceptionFromCreationError(errorCode, name);
- }
- else if (name != null)
- {
- int errorCode = Marshal.GetLastWin32Error();
- createdNew = errorCode != Interop.Errors.ERROR_ALREADY_EXISTS;
- }
- else
- {
- createdNew = true;
- }
-
- SafeWaitHandle = _handle;
- }
-
- private static OpenExistingResult OpenExistingWorker(string name, out EventWaitHandle result)
- {
- if (name == null)
- {
- throw new ArgumentNullException(nameof(name), SR.ArgumentNull_WithParamName);
- }
-
- if (name.Length == 0)
- {
- throw new ArgumentException(SR.Argument_EmptyName, nameof(name));
- }
-
- if (null != name && Interop.Kernel32.MAX_PATH < name.Length)
- {
- throw new ArgumentException(SR.Format(SR.Argument_WaitHandleNameTooLong, Interop.Kernel32.MAX_PATH), nameof(name));
- }
-
- result = null;
-
- SafeWaitHandle myHandle = Interop.mincore.OpenEvent(AccessRights, false, name);
-
- if (myHandle.IsInvalid)
- {
- int errorCode = Marshal.GetLastWin32Error();
-
- if (Interop.Errors.ERROR_FILE_NOT_FOUND == errorCode || Interop.Errors.ERROR_INVALID_NAME == errorCode)
- return OpenExistingResult.NameNotFound;
- if (Interop.Errors.ERROR_PATH_NOT_FOUND == errorCode)
- return OpenExistingResult.PathNotFound;
- if (null != name && 0 != name.Length && Interop.Errors.ERROR_INVALID_HANDLE == errorCode)
- return OpenExistingResult.NameInvalid;
-
- throw ExceptionFromCreationError(errorCode, name);
- }
- result = new EventWaitHandle(myHandle);
- return OpenExistingResult.Success;
- }
-
- private static bool ResetCore(IntPtr handle)
- {
- bool res = Interop.mincore.ResetEvent(handle);
- if (!res)
- ThrowSignalOrUnsignalException();
- return res;
- }
-
- private static bool SetCore(IntPtr handle)
- {
- bool res = Interop.mincore.SetEvent(handle);
- if (!res)
- ThrowSignalOrUnsignalException();
- return res;
- }
- }
-}
diff --git a/src/System.Private.CoreLib/src/System/Threading/EventWaitHandle.cs b/src/System.Private.CoreLib/src/System/Threading/EventWaitHandle.cs
deleted file mode 100644
index 04026d587..000000000
--- a/src/System.Private.CoreLib/src/System/Threading/EventWaitHandle.cs
+++ /dev/null
@@ -1,130 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-//
-
-/*=============================================================================
-**
-**
-**
-** Purpose: Base class for representing Events
-**
-**
-=============================================================================*/
-
-using System;
-using System.Runtime.InteropServices;
-using Microsoft.Win32.SafeHandles;
-using System.IO;
-using System.Diagnostics;
-
-namespace System.Threading
-{
- public partial class EventWaitHandle : WaitHandle
- {
- public EventWaitHandle(bool initialState, EventResetMode mode)
- {
- VerifyMode(mode);
-
- bool createdNew;
- CreateEventCore(initialState, mode, null, out createdNew);
- }
-
- public EventWaitHandle(bool initialState, EventResetMode mode, string name)
- {
- VerifyNameForCreate(name);
- VerifyMode(mode);
-
- bool createdNew;
- CreateEventCore(initialState, mode, name, out createdNew);
- }
-
- public EventWaitHandle(bool initialState, EventResetMode mode, string name, out bool createdNew)
- {
- VerifyNameForCreate(name);
- VerifyMode(mode);
-
- CreateEventCore(initialState, mode, name, out createdNew);
- }
-
- private static void VerifyMode(EventResetMode mode)
- {
- if (mode != EventResetMode.AutoReset && mode != EventResetMode.ManualReset)
- {
- throw new ArgumentException(SR.Argument_InvalidFlag, nameof(mode));
- }
- }
-
- public static EventWaitHandle OpenExisting(string name)
- {
- EventWaitHandle result;
- switch (OpenExistingWorker(name, out result))
- {
- case OpenExistingResult.NameNotFound:
- throw new WaitHandleCannotBeOpenedException();
-
- case OpenExistingResult.NameInvalid:
- throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
-
- case OpenExistingResult.PathNotFound:
- throw new IOException(SR.Format(SR.IO_PathNotFound_Path, name));
-
- default:
- return result;
- }
- }
-
- public static bool TryOpenExisting(string name, out EventWaitHandle result)
- {
- return OpenExistingWorker(name, out result) == OpenExistingResult.Success;
- }
-
- public bool Reset()
- {
- // The field value is modifiable via <see cref="SafeWaitHandle"/>, save it locally to ensure that ref modification
- // is done on the same instance
- SafeWaitHandle waitHandle = _waitHandle;
- if (waitHandle == null)
- {
- ThrowInvalidHandleException();
- }
-
- waitHandle.DangerousAddRef();
- try
- {
- return ResetCore(_waitHandle.DangerousGetHandle());
- }
- finally
- {
- waitHandle.DangerousRelease();
- }
- }
-
- public bool Set()
- {
- // The field value is modifiable via the public <see cref="WaitHandle.SafeWaitHandle"/> property, save it locally
- // to ensure that one instance is used in all places in this method
- SafeWaitHandle waitHandle = _waitHandle;
- if (waitHandle == null)
- {
- ThrowInvalidHandleException();
- }
-
- waitHandle.DangerousAddRef();
- try
- {
- return SetCore(waitHandle.DangerousGetHandle());
- }
- finally
- {
- waitHandle.DangerousRelease();
- }
- }
-
- internal static bool Set(IntPtr handle)
- {
- return SetCore(handle);
- }
- }
-}
diff --git a/src/System.Private.CoreLib/src/System/Threading/Interlocked.cs b/src/System.Private.CoreLib/src/System/Threading/Interlocked.cs
index e07fbf97b..c3917e873 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Interlocked.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Interlocked.cs
@@ -322,7 +322,7 @@ namespace System.Threading
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T CompareExchange<T>(ref T location1, T value, T comparand) where T : class
{
- return Unsafe.As<T>(RuntimeImports.InterlockedCompareExchange(ref Unsafe.As<T, Object>(ref location1), value, comparand));
+ return Unsafe.As<T>(RuntimeImports.InterlockedCompareExchange(ref Unsafe.As<T, object>(ref location1), value, comparand));
}
[Intrinsic]
@@ -394,7 +394,7 @@ namespace System.Threading
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T Exchange<T>(ref T location1, T value) where T : class
{
- return Unsafe.As<T>(RuntimeImports.InterlockedExchange(ref Unsafe.As<T, Object>(ref location1), value));
+ return Unsafe.As<T>(RuntimeImports.InterlockedExchange(ref Unsafe.As<T, object>(ref location1), value));
}
[Intrinsic]
diff --git a/src/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.Windows.cs b/src/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.Windows.cs
index 88ca53420..38ed1d554 100644
--- a/src/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.Windows.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.Windows.cs
@@ -27,7 +27,7 @@ namespace System.Threading
{
var error = Marshal.GetLastWin32Error();
var exception = new OutOfMemoryException();
- exception.SetErrorCode(error);
+ exception.HResult = error;
throw exception;
}
Release(initialSignalCount);
@@ -48,7 +48,7 @@ namespace System.Threading
{
var lastError = Marshal.GetLastWin32Error();
var exception = new OutOfMemoryException();
- exception.SetErrorCode(lastError);
+ exception.HResult = lastError;
throw exception;
}
}
diff --git a/src/System.Private.CoreLib/src/System/Threading/LowLevelMonitor.Windows.cs b/src/System.Private.CoreLib/src/System/Threading/LowLevelMonitor.Windows.cs
index 602908d6d..a492e3acb 100644
--- a/src/System.Private.CoreLib/src/System/Threading/LowLevelMonitor.Windows.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/LowLevelMonitor.Windows.cs
@@ -51,7 +51,7 @@ namespace System.Threading
if (lastError != Interop.Errors.ERROR_TIMEOUT)
{
var exception = new OutOfMemoryException();
- exception.SetErrorCode(lastError);
+ exception.HResult = lastError;
throw exception;
}
}
diff --git a/src/System.Private.CoreLib/src/System/Threading/ManagedThreadId.cs b/src/System.Private.CoreLib/src/System/Threading/ManagedThreadId.cs
index 370aeca09..8bbb8ba25 100644
--- a/src/System.Private.CoreLib/src/System/Threading/ManagedThreadId.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/ManagedThreadId.cs
@@ -103,7 +103,7 @@ namespace System.Threading
var right = _right;
// Any free bits in current node?
- if (bitmap != UInt32.MaxValue)
+ if (bitmap != uint.MaxValue)
{
int bit = 0;
while ((bitmap & (uint)(1 << bit)) != 0)
@@ -218,7 +218,7 @@ namespace System.Threading
{
var updatedIdDispenser = priorIdDispenser.AllocateId(out id);
var interlockedResult = Interlocked.CompareExchange(ref s_idDispenser, updatedIdDispenser, priorIdDispenser);
- if (Object.ReferenceEquals(priorIdDispenser, interlockedResult))
+ if (object.ReferenceEquals(priorIdDispenser, interlockedResult))
break;
priorIdDispenser = interlockedResult; // we already have a volatile read that we can reuse for the next loop
}
@@ -240,7 +240,7 @@ namespace System.Threading
{
var updatedIdDispenser = s_idDispenser.RecycleId(id);
var interlockedResult = Interlocked.CompareExchange(ref s_idDispenser, updatedIdDispenser, priorIdDispenser);
- if (Object.ReferenceEquals(priorIdDispenser, interlockedResult))
+ if (object.ReferenceEquals(priorIdDispenser, interlockedResult))
break;
priorIdDispenser = interlockedResult; // we already have a volatile read that we can reuse for the next loop
}
diff --git a/src/System.Private.CoreLib/src/System/Threading/ManualResetEventSlim.cs b/src/System.Private.CoreLib/src/System/Threading/ManualResetEventSlim.cs
index a674901ea..faa5f2482 100644
--- a/src/System.Private.CoreLib/src/System/Threading/ManualResetEventSlim.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/ManualResetEventSlim.cs
@@ -57,7 +57,7 @@ namespace System.Threading
// -- State -- //
//For a packed word a uint would seem better, but Interlocked.* doesn't support them as uint isn't CLS-compliant.
- private volatile int m_combinedState; //ie a UInt32. Used for the state items listed below.
+ private volatile int m_combinedState; //ie a uint. Used for the state items listed below.
//1-bit for signalled state
private const int SignalledState_BitMask = unchecked((int)0x80000000);//1000 0000 0000 0000 0000 0000 0000 0000
@@ -163,7 +163,7 @@ namespace System.Threading
// it is possible for the max number of waiters to be exceeded via user-code, hence we use a real exception here.
if (value >= NumWaitersState_MaxValue)
- throw new InvalidOperationException(String.Format(SR.ManualResetEventSlim_ctor_TooManyWaiters, NumWaitersState_MaxValue));
+ throw new InvalidOperationException(string.Format(SR.ManualResetEventSlim_ctor_TooManyWaiters, NumWaitersState_MaxValue));
UpdateStateAtomically(value << NumWaitersState_ShiftCount, NumWaitersState_BitMask);
}
@@ -185,7 +185,7 @@ namespace System.Threading
/// <summary>
/// Initializes a new instance of the <see cref="ManualResetEventSlim"/>
- /// class with a Boolen value indicating whether to set the intial state to signaled.
+ /// class with a Boolean value indicating whether to set the intial state to signaled.
/// </summary>
/// <param name="initialState">true to set the initial state signaled; false to set the initial state
/// to nonsignaled.</param>
@@ -218,7 +218,7 @@ namespace System.Threading
{
throw new ArgumentOutOfRangeException(
nameof(spinCount),
- String.Format(SR.ManualResetEventSlim_ctor_SpinCountOutOfRange, SpinCountState_MaxValue));
+ string.Format(SR.ManualResetEventSlim_ctor_SpinCountOutOfRange, SpinCountState_MaxValue));
}
// We will suppress default spin because the user specified a count.
@@ -611,7 +611,7 @@ namespace System.Threading
// Now enter the lock and wait.
EnsureLockObjectCreated();
- // We must register and deregister the token outside of the lock, to avoid deadlocks.
+ // We must register and unregister the token outside of the lock, to avoid deadlocks.
using (cancellationToken.InternalRegisterWithoutEC(s_cancellationTokenCallback, this))
{
using (LockHolder.Hold(m_lock))
@@ -665,7 +665,7 @@ namespace System.Threading
}
}
}
- } // automatically disposes (and deregisters) the callback
+ } // automatically disposes (and unregisters) the callback
return true; //done. The wait was satisfied.
}
@@ -690,7 +690,7 @@ namespace System.Threading
/// <param name="disposing">true to release both managed and unmanaged resources;
/// false to release only unmanaged resources.</param>
/// <remarks>
- /// Unlike most of the members of <see cref="ManualResetEventSlim"/>, <see cref="Dispose(Boolean)"/> is not
+ /// Unlike most of the members of <see cref="ManualResetEventSlim"/>, <see cref="Dispose(bool)"/> is not
/// thread-safe and may not be used concurrently with other members of this instance.
/// </remarks>
protected virtual void Dispose(bool disposing)
diff --git a/src/System.Private.CoreLib/src/System/Threading/Monitor.cs b/src/System.Private.CoreLib/src/System/Threading/Monitor.cs
index e825d625b..b9839321a 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Monitor.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Monitor.cs
@@ -32,7 +32,7 @@ namespace System.Threading
private static ConditionalWeakTable<object, Condition> s_conditionTable = new ConditionalWeakTable<object, Condition>();
private static ConditionalWeakTable<object, Condition>.CreateValueCallback s_createCondition = (o) => new Condition(GetLock(o));
- internal static Lock GetLock(Object obj)
+ internal static Lock GetLock(object obj)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
@@ -47,7 +47,7 @@ namespace System.Threading
#endif
}
- private static Condition GetCondition(Object obj)
+ private static Condition GetCondition(object obj)
{
Debug.Assert(
!(obj is Condition || obj is Lock),
@@ -58,7 +58,7 @@ namespace System.Threading
#region Public Enter/Exit methods
- public static void Enter(Object obj)
+ public static void Enter(object obj)
{
Lock lck = GetLock(obj);
if (lck.TryAcquire(0))
@@ -66,7 +66,7 @@ namespace System.Threading
TryAcquireContended(lck, obj, Timeout.Infinite);
}
- public static void Enter(Object obj, ref bool lockTaken)
+ public static void Enter(object obj, ref bool lockTaken)
{
if (lockTaken)
throw new ArgumentException(SR.Argument_MustBeFalse, nameof(lockTaken));
@@ -81,12 +81,12 @@ namespace System.Threading
lockTaken = true;
}
- public static bool TryEnter(Object obj)
+ public static bool TryEnter(object obj)
{
return GetLock(obj).TryAcquire(0);
}
- public static void TryEnter(Object obj, ref bool lockTaken)
+ public static void TryEnter(object obj, ref bool lockTaken)
{
if (lockTaken)
throw new ArgumentException(SR.Argument_MustBeFalse, nameof(lockTaken));
@@ -94,7 +94,7 @@ namespace System.Threading
lockTaken = GetLock(obj).TryAcquire(0);
}
- public static bool TryEnter(Object obj, int millisecondsTimeout)
+ public static bool TryEnter(object obj, int millisecondsTimeout)
{
if (millisecondsTimeout < -1)
throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), SR.ArgumentOutOfRange_NeedNonNegOrNegative1);
@@ -105,7 +105,7 @@ namespace System.Threading
return TryAcquireContended(lck, obj, millisecondsTimeout);
}
- public static void TryEnter(Object obj, int millisecondsTimeout, ref bool lockTaken)
+ public static void TryEnter(object obj, int millisecondsTimeout, ref bool lockTaken)
{
if (lockTaken)
throw new ArgumentException(SR.Argument_MustBeFalse, nameof(lockTaken));
@@ -121,18 +121,18 @@ namespace System.Threading
lockTaken = TryAcquireContended(lck, obj, millisecondsTimeout);
}
- public static bool TryEnter(Object obj, TimeSpan timeout) =>
+ public static bool TryEnter(object obj, TimeSpan timeout) =>
TryEnter(obj, WaitHandle.ToTimeoutMilliseconds(timeout));
- public static void TryEnter(Object obj, TimeSpan timeout, ref bool lockTaken) =>
+ public static void TryEnter(object obj, TimeSpan timeout, ref bool lockTaken) =>
TryEnter(obj, WaitHandle.ToTimeoutMilliseconds(timeout), ref lockTaken);
- public static void Exit(Object obj)
+ public static void Exit(object obj)
{
GetLock(obj).Release();
}
- public static bool IsEntered(Object obj)
+ public static bool IsEntered(object obj)
{
return GetLock(obj).IsAcquired;
}
@@ -142,14 +142,14 @@ namespace System.Threading
#region Public Wait/Pulse methods
// Remoting is not supported, ignore exitContext
- public static bool Wait(Object obj, int millisecondsTimeout, bool exitContext) =>
+ public static bool Wait(object obj, int millisecondsTimeout, bool exitContext) =>
Wait(obj, millisecondsTimeout);
// Remoting is not supported, ignore exitContext
- public static bool Wait(Object obj, TimeSpan timeout, bool exitContext) =>
+ public static bool Wait(object obj, TimeSpan timeout, bool exitContext) =>
Wait(obj, WaitHandle.ToTimeoutMilliseconds(timeout));
- public static bool Wait(Object obj, int millisecondsTimeout)
+ public static bool Wait(object obj, int millisecondsTimeout)
{
Condition condition = GetCondition(obj);
DebugBlockingItem blockingItem;
@@ -160,9 +160,9 @@ namespace System.Threading
}
}
- public static bool Wait(Object obj, TimeSpan timeout) => Wait(obj, WaitHandle.ToTimeoutMilliseconds(timeout));
+ public static bool Wait(object obj, TimeSpan timeout) => Wait(obj, WaitHandle.ToTimeoutMilliseconds(timeout));
- public static bool Wait(Object obj) => Wait(obj, Timeout.Infinite);
+ public static bool Wait(object obj) => Wait(obj, Timeout.Infinite);
public static void Pulse(object obj)
{
@@ -178,7 +178,7 @@ namespace System.Threading
#region Slow path for Entry/TryEnter methods.
- internal static bool TryAcquireContended(Lock lck, Object obj, int millisecondsTimeout)
+ internal static bool TryAcquireContended(Lock lck, object obj, int millisecondsTimeout)
{
DebugBlockingItem blockingItem;
diff --git a/src/System.Private.CoreLib/src/System/Threading/Mutex.Unix.cs b/src/System.Private.CoreLib/src/System/Threading/Mutex.Unix.cs
index 46a996348..004e95287 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Mutex.Unix.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Mutex.Unix.cs
@@ -2,24 +2,21 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using Microsoft.Win32.SafeHandles;
using System.Diagnostics;
using System.IO;
+using System.Runtime.InteropServices;
namespace System.Threading
{
public sealed partial class Mutex
{
- private static void VerifyNameForCreate(string name)
+ private void CreateMutexCore(bool initiallyOwned, string name, out bool createdNew)
{
if (name != null)
{
throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
}
- }
-
- private void CreateMutexCore(bool initiallyOwned, string name, out bool createdNew)
- {
- Debug.Assert(name == null);
SafeWaitHandle = WaitSubsystem.NewMutex(initiallyOwned);
createdNew = true;
@@ -30,9 +27,25 @@ namespace System.Threading
throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
}
- private static void ReleaseMutexCore(IntPtr handle)
+ public void ReleaseMutex()
{
- WaitSubsystem.ReleaseMutex(handle);
+ // The field value is modifiable via the public <see cref="WaitHandle.SafeWaitHandle"/> property, save it locally
+ // to ensure that one instance is used in all places in this method
+ SafeWaitHandle waitHandle = _waitHandle;
+ if (waitHandle == null)
+ {
+ ThrowInvalidHandleException();
+ }
+
+ waitHandle.DangerousAddRef();
+ try
+ {
+ WaitSubsystem.ReleaseMutex(waitHandle.DangerousGetHandle());
+ }
+ finally
+ {
+ waitHandle.DangerousRelease();
+ }
}
}
}
diff --git a/src/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs b/src/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs
deleted file mode 100644
index ba5e86304..000000000
--- a/src/System.Private.CoreLib/src/System/Threading/Mutex.Windows.cs
+++ /dev/null
@@ -1,91 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-using Microsoft.Win32.SafeHandles;
-
-namespace System.Threading
-{
- public sealed partial class Mutex
- {
- private const uint AccessRights = (uint)(Interop.Constants.MaximumAllowed | Interop.Constants.Synchronize | Interop.Constants.MutexModifyState);
-
- private static void VerifyNameForCreate(string name)
- {
- if (null != name && Interop.Kernel32.MAX_PATH < name.Length)
- {
- throw new ArgumentException(SR.Format(SR.Argument_WaitHandleNameTooLong, Interop.Kernel32.MAX_PATH), nameof(name));
- }
- }
-
- private void CreateMutexCore(bool initiallyOwned, string name, out bool createdNew)
- {
- Debug.Assert(name == null || name.Length <= Interop.Kernel32.MAX_PATH);
-
- uint mutexFlags = initiallyOwned ? (uint)Interop.Constants.CreateMutexInitialOwner : 0;
-
- SafeWaitHandle mutexHandle = Interop.mincore.CreateMutexEx(IntPtr.Zero, name, mutexFlags, AccessRights);
- int errorCode = Marshal.GetLastWin32Error();
-
- if (mutexHandle.IsInvalid)
- {
- mutexHandle.SetHandleAsInvalid();
- if (null != name && 0 != name.Length && Interop.Errors.ERROR_INVALID_HANDLE == errorCode)
- throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
- throw ExceptionFromCreationError(errorCode, name);
- }
-
- createdNew = errorCode != Interop.Errors.ERROR_ALREADY_EXISTS;
- SafeWaitHandle = mutexHandle;
- }
-
- private static OpenExistingResult OpenExistingWorker(string name, out Mutex result)
- {
- if (name == null)
- {
- throw new ArgumentNullException(nameof(name), SR.ArgumentNull_WithParamName);
- }
-
- if (name.Length == 0)
- {
- throw new ArgumentException(SR.Argument_EmptyName, nameof(name));
- }
- if (Interop.Kernel32.MAX_PATH < (uint)name.Length)
- {
- throw new ArgumentException(SR.Format(SR.Argument_WaitHandleNameTooLong, Interop.Kernel32.MAX_PATH), nameof(name));
- }
-
- result = null;
-
- SafeWaitHandle myHandle = Interop.mincore.OpenMutex(AccessRights, false, name);
-
- int errorCode = 0;
- if (myHandle.IsInvalid)
- {
- errorCode = Marshal.GetLastWin32Error();
-
- if (Interop.Errors.ERROR_FILE_NOT_FOUND == errorCode || Interop.Errors.ERROR_INVALID_NAME == errorCode)
- return OpenExistingResult.NameNotFound;
- if (Interop.Errors.ERROR_PATH_NOT_FOUND == errorCode)
- return OpenExistingResult.PathNotFound;
- if (null != name && 0 != name.Length && Interop.Errors.ERROR_INVALID_HANDLE == errorCode)
- return OpenExistingResult.NameInvalid;
-
- throw ExceptionFromCreationError(errorCode, name);
- }
-
- result = new Mutex(myHandle);
- return OpenExistingResult.Success;
- }
-
- private static void ReleaseMutexCore(IntPtr handle)
- {
- if (!Interop.mincore.ReleaseMutex(handle))
- {
- ThrowSignalOrUnsignalException();
- }
- }
- }
-}
diff --git a/src/System.Private.CoreLib/src/System/Threading/Mutex.cs b/src/System.Private.CoreLib/src/System/Threading/Mutex.cs
deleted file mode 100644
index 6db36cb59..000000000
--- a/src/System.Private.CoreLib/src/System/Threading/Mutex.cs
+++ /dev/null
@@ -1,103 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-/*=============================================================================
-**
-**
-**
-** Purpose: synchronization primitive that can also be used for interprocess synchronization
-**
-**
-=============================================================================*/
-
-using System;
-using System.Threading;
-using System.Runtime.CompilerServices;
-using System.IO;
-using Microsoft.Win32;
-using Microsoft.Win32.SafeHandles;
-using System.Runtime.InteropServices;
-using System.Runtime.Versioning;
-using System.Security;
-
-namespace System.Threading
-{
- public sealed partial class Mutex : WaitHandle
- {
- public Mutex(bool initiallyOwned, string name, out bool createdNew)
- {
- VerifyNameForCreate(name);
-
- CreateMutexCore(initiallyOwned, name, out createdNew);
- }
-
- public Mutex(bool initiallyOwned, string name)
- {
- VerifyNameForCreate(name);
-
- bool createdNew;
- CreateMutexCore(initiallyOwned, name, out createdNew);
- }
-
- public Mutex(bool initiallyOwned)
- {
- bool createdNew;
- CreateMutexCore(initiallyOwned, null, out createdNew);
- }
-
- public Mutex()
- {
- bool createdNew;
- CreateMutexCore(false, null, out createdNew);
- }
-
- private Mutex(SafeWaitHandle handle)
- {
- SafeWaitHandle = handle;
- }
-
- public static Mutex OpenExisting(string name)
- {
- Mutex result;
- switch (OpenExistingWorker(name, out result))
- {
- case OpenExistingResult.NameNotFound:
- throw new WaitHandleCannotBeOpenedException();
-
- case OpenExistingResult.NameInvalid:
- throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
-
- case OpenExistingResult.PathNotFound:
- throw new IOException(SR.Format(SR.IO_PathNotFound_Path, name));
-
- default:
- return result;
- }
- }
-
- public static bool TryOpenExisting(string name, out Mutex result) =>
- OpenExistingWorker(name, out result) == OpenExistingResult.Success;
-
- public void ReleaseMutex()
- {
- // The field value is modifiable via the public <see cref="WaitHandle.SafeWaitHandle"/> property, save it locally
- // to ensure that one instance is used in all places in this method
- SafeWaitHandle waitHandle = _waitHandle;
- if (waitHandle == null)
- {
- ThrowInvalidHandleException();
- }
-
- waitHandle.DangerousAddRef();
- try
- {
- ReleaseMutexCore(waitHandle.DangerousGetHandle());
- }
- finally
- {
- waitHandle.DangerousRelease();
- }
- }
- }
-}
diff --git a/src/System.Private.CoreLib/src/System/Threading/Overlapped.cs b/src/System.Private.CoreLib/src/System/Threading/Overlapped.cs
index 787436965..0a1c2ce72 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Overlapped.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Overlapped.cs
@@ -19,73 +19,63 @@
**
=============================================================================*/
+using System.Diagnostics;
using System.Runtime;
using System.Runtime.InteropServices;
-using System.Runtime.CompilerServices;
-using System.Runtime.Versioning;
-using System.Security;
-using System.Runtime.ConstrainedExecution;
-using System.Diagnostics;
-using System.Collections.Concurrent;
-
using Internal.Runtime.CompilerServices;
namespace System.Threading
{
#region class _IOCompletionCallback
- internal class _IOCompletionCallback
+ internal unsafe class _IOCompletionCallback
{
private IOCompletionCallback _ioCompletionCallback;
private ExecutionContext _executionContext;
private uint _errorCode; // Error code
private uint _numBytes; // No. of bytes transferred
- private unsafe NativeOverlapped* _pOVERLAP;
+ private NativeOverlapped* _pNativeOverlapped;
- internal _IOCompletionCallback(IOCompletionCallback ioCompletionCallback)
+ internal _IOCompletionCallback(IOCompletionCallback ioCompletionCallback, ExecutionContext executionContext)
{
_ioCompletionCallback = ioCompletionCallback;
- _executionContext = ExecutionContext.Capture();
+ _executionContext = executionContext;
}
- private static ContextCallback s_ccb = new ContextCallback(IOCompletionCallback_Context);
-
- private static unsafe void IOCompletionCallback_Context(Object state)
+ // Context callback: same sig for SendOrPostCallback and ContextCallback
+ internal static ContextCallback s_ccb = new ContextCallback(IOCompletionCallback_Context);
+ private static void IOCompletionCallback_Context(object state)
{
_IOCompletionCallback helper = (_IOCompletionCallback)state;
Debug.Assert(helper != null, "_IOCompletionCallback cannot be null");
- helper._ioCompletionCallback(helper._errorCode, helper._numBytes, helper._pOVERLAP);
+ helper._ioCompletionCallback(helper._errorCode, helper._numBytes, helper._pNativeOverlapped);
}
- internal static unsafe void PerformIOCompletionCallback(uint errorCode, uint numBytes, NativeOverlapped* pOVERLAP)
+ internal static unsafe void PerformIOCompletionCallback(uint errorCode, uint numBytes, NativeOverlapped* pNativeOverlapped)
{
- Overlapped overlapped;
- _IOCompletionCallback helper;
-
do
{
- overlapped = OverlappedData.GetOverlappedFromNative(pOVERLAP).m_overlapped;
- helper = overlapped.iocbHelper;
+ OverlappedData overlapped = OverlappedData.GetOverlappedFromNative(pNativeOverlapped);
- if (helper == null || helper._executionContext == null || helper._executionContext == ExecutionContext.Default)
+ if (overlapped._callback is IOCompletionCallback iocb)
{
- // We got here because of UnsafePack (or) Pack with EC flow supressed
- IOCompletionCallback callback = overlapped.UserCallback;
- callback(errorCode, numBytes, pOVERLAP);
+ // We got here because of UnsafePack (or) Pack with EC flow suppressed
+ iocb(errorCode, numBytes, pNativeOverlapped);
}
else
{
// We got here because of Pack
+ var helper = (_IOCompletionCallback)overlapped._callback;
helper._errorCode = errorCode;
helper._numBytes = numBytes;
- helper._pOVERLAP = pOVERLAP;
+ helper._pNativeOverlapped = pNativeOverlapped;
ExecutionContext.Run(helper._executionContext, s_ccb, helper);
}
//Quickly check the VM again, to see if a packet has arrived.
//OverlappedData.CheckVMForIOPacket(out pOVERLAP, out errorCode, out numBytes);
- pOVERLAP = null;
- } while (pOVERLAP != null);
+ pNativeOverlapped = null;
+ } while (pNativeOverlapped != null);
}
}
@@ -93,115 +83,100 @@ namespace System.Threading
#region class OverlappedData
- internal sealed class OverlappedData
+ internal unsafe sealed class OverlappedData
{
- // The offset of m_nativeOverlapped field from m_pEEType
- private static int s_nativeOverlappedOffset;
-
- internal IAsyncResult m_asyncResult;
- internal IOCompletionCallback m_iocb;
- internal _IOCompletionCallback m_iocbHelper;
- internal Overlapped m_overlapped;
- private Object m_userObject;
- private IntPtr m_pinSelf;
- private GCHandle[] m_pinnedData;
- internal NativeOverlapped m_nativeOverlapped;
-
- // Adding an empty default ctor for annotation purposes
- internal OverlappedData() { }
-
- ~OverlappedData()
+ internal IAsyncResult _asyncResult;
+ internal object _callback; // IOCompletionCallback or _IOCompletionCallback
+ internal Overlapped _overlapped;
+ private object _userObject;
+ private NativeOverlapped * _pNativeOverlapped;
+ private IntPtr _eventHandle;
+ private int _offsetLow;
+ private int _offsetHigh;
+ private GCHandle[] _pinnedData;
+
+ internal ref IAsyncResult AsyncResult => ref _asyncResult;
+
+ internal ref int OffsetLow => ref (_pNativeOverlapped != null) ? ref _pNativeOverlapped->OffsetLow : ref _offsetLow;
+ internal ref int OffsetHigh => ref (_pNativeOverlapped != null) ? ref _pNativeOverlapped->OffsetHigh : ref _offsetHigh;
+ internal ref IntPtr EventHandle => ref (_pNativeOverlapped != null) ? ref _pNativeOverlapped->EventHandle : ref _eventHandle;
+
+ internal unsafe NativeOverlapped* Pack(IOCompletionCallback iocb, object userData)
{
- if (m_pinnedData != null)
+ if (_pNativeOverlapped != null)
{
- for (int i = 0; i < m_pinnedData.Length; i++)
- {
- if (m_pinnedData[i].IsAllocated)
- {
- m_pinnedData[i].Free();
- }
- }
+ throw new InvalidOperationException(SR.InvalidOperation_Overlapped_Pack);
}
- }
-
- internal void ReInitialize()
- {
- m_asyncResult = null;
- m_iocb = null;
- m_iocbHelper = null;
- m_overlapped = null;
- m_userObject = null;
- Debug.Assert(m_pinSelf == IntPtr.Zero, "OverlappedData has not been freed: m_pinSelf");
- m_pinSelf = IntPtr.Zero;
- // Reuse m_pinnedData array
- m_nativeOverlapped = default(NativeOverlapped);
- }
- internal unsafe NativeOverlapped* Pack(IOCompletionCallback iocb, Object userData)
- {
- if (m_pinSelf != IntPtr.Zero)
+ if (iocb != null)
{
- throw new InvalidOperationException(SR.InvalidOperation_Overlapped_Pack);
+ ExecutionContext ec = ExecutionContext.Capture();
+ _callback = (ec != null && !ec.IsDefault) ? new _IOCompletionCallback(iocb, ec) : (object)iocb;
}
- m_iocb = iocb;
- m_iocbHelper = (iocb != null) ? new _IOCompletionCallback(iocb) : null;
- m_userObject = userData;
+ else
+ {
+ _callback = null;
+ }
+ _userObject = userData;
return AllocateNativeOverlapped();
}
- internal unsafe NativeOverlapped* UnsafePack(IOCompletionCallback iocb, Object userData)
+ internal unsafe NativeOverlapped* UnsafePack(IOCompletionCallback iocb, object userData)
{
- if (m_pinSelf != IntPtr.Zero)
+ if (_pNativeOverlapped != null)
{
throw new InvalidOperationException(SR.InvalidOperation_Overlapped_Pack);
}
- m_iocb = iocb;
- m_iocbHelper = null;
- m_userObject = userData;
+ _userObject = userData;
+ _callback = iocb;
return AllocateNativeOverlapped();
}
- internal IntPtr UserHandle
- {
- get { return m_nativeOverlapped.EventHandle; }
- set { m_nativeOverlapped.EventHandle = value; }
- }
-
private unsafe NativeOverlapped* AllocateNativeOverlapped()
{
- if (m_userObject != null)
+ Debug.Assert(_pinnedData == null);
+
+ bool success = false;
+ try
{
- if (m_userObject.GetType() == typeof(Object[]))
+ if (_userObject != null)
{
- Object[] objArray = (Object[])m_userObject;
- if (m_pinnedData == null || m_pinnedData.Length < objArray.Length)
- Array.Resize(ref m_pinnedData, objArray.Length);
+ if (_userObject.GetType() == typeof(object[]))
+ {
+ object[] objArray = (object[])_userObject;
- for (int i = 0; i < objArray.Length; i++)
+ _pinnedData = new GCHandle[objArray.Length];
+ for (int i = 0; i < objArray.Length; i++)
+ {
+ _pinnedData[i] = GCHandle.Alloc(objArray[i], GCHandleType.Pinned);
+ }
+ }
+ else
{
- if (!m_pinnedData[i].IsAllocated)
- m_pinnedData[i] = GCHandle.Alloc(objArray[i], GCHandleType.Pinned);
- else
- m_pinnedData[i].Target = objArray[i];
+ _pinnedData = new GCHandle[1];
+ _pinnedData[0] = GCHandle.Alloc(_userObject, GCHandleType.Pinned);
}
}
- else
- {
- if (m_pinnedData == null || m_pinnedData.Length < 1)
- m_pinnedData = new GCHandle[1];
- if (!m_pinnedData[0].IsAllocated)
- m_pinnedData[0] = GCHandle.Alloc(m_userObject, GCHandleType.Pinned);
- else
- m_pinnedData[0].Target = m_userObject;
- }
- }
+ NativeOverlapped* pNativeOverlapped = (NativeOverlapped*)Interop.MemAlloc((UIntPtr)(sizeof(NativeOverlapped) + sizeof(GCHandle)));
+ *(GCHandle*)(pNativeOverlapped + 1) = default(GCHandle);
+ _pNativeOverlapped = pNativeOverlapped;
+
+ _pNativeOverlapped->InternalLow = default;
+ _pNativeOverlapped->InternalHigh = default;
+ _pNativeOverlapped->OffsetLow = _offsetLow;
+ _pNativeOverlapped->OffsetHigh = _offsetHigh;
+ _pNativeOverlapped->EventHandle = _eventHandle;
- m_pinSelf = RuntimeImports.RhHandleAlloc(this, GCHandleType.Pinned);
+ *(GCHandle*)(_pNativeOverlapped + 1) = GCHandle.Alloc(this);
- fixed (NativeOverlapped* pNativeOverlapped = &m_nativeOverlapped)
+ success = true;
+ return _pNativeOverlapped;
+ }
+ finally
{
- return pNativeOverlapped;
+ if (!success)
+ FreeNativeOverlapped();
}
}
@@ -213,47 +188,33 @@ namespace System.Threading
private void FreeNativeOverlapped()
{
- IntPtr pinSelf = m_pinSelf;
- if (pinSelf != IntPtr.Zero)
+ if (_pinnedData != null)
{
- if (Interlocked.CompareExchange(ref m_pinSelf, IntPtr.Zero, pinSelf) == pinSelf)
+ for (int i = 0; i < _pinnedData.Length; i++)
{
- if (m_pinnedData != null)
+ if (_pinnedData[i].IsAllocated)
{
- for (int i = 0; i < m_pinnedData.Length; i++)
- {
- if (m_pinnedData[i].IsAllocated && (m_pinnedData[i].Target != null))
- {
- m_pinnedData[i].Target = null;
- }
- }
+ _pinnedData[i].Free();
}
-
- RuntimeImports.RhHandleFree(pinSelf);
}
+ _pinnedData = null;
}
- }
- internal static unsafe OverlappedData GetOverlappedFromNative(NativeOverlapped* nativeOverlappedPtr)
- {
- if (s_nativeOverlappedOffset == 0)
+ if (_pNativeOverlapped != null)
{
- CalculateNativeOverlappedOffset();
- }
+ GCHandle handle = *(GCHandle*)(_pNativeOverlapped + 1);
+ if (handle.IsAllocated)
+ handle.Free();
- void* pOverlappedData = (byte*)nativeOverlappedPtr - s_nativeOverlappedOffset;
- return Unsafe.Read<OverlappedData>(&pOverlappedData);
+ Interop.MemFree((IntPtr)_pNativeOverlapped);
+ _pNativeOverlapped = null;
+ }
}
- private static unsafe void CalculateNativeOverlappedOffset()
+ internal static unsafe OverlappedData GetOverlappedFromNative(NativeOverlapped* pNativeOverlapped)
{
- OverlappedData overlappedData = new OverlappedData();
-
- fixed (IntPtr* pEETypePtr = &overlappedData.m_pEEType)
- fixed (NativeOverlapped* pNativeOverlapped = &overlappedData.m_nativeOverlapped)
- {
- s_nativeOverlappedOffset = (int)((byte*)pNativeOverlapped - (byte*)pEETypePtr);
- }
+ GCHandle handle = *(GCHandle*)(pNativeOverlapped + 1);
+ return (OverlappedData)handle.Target;
}
}
@@ -263,24 +224,20 @@ namespace System.Threading
public class Overlapped
{
- private static PinnableBufferCache s_overlappedDataCache = new PinnableBufferCache("System.Threading.OverlappedData", () => new OverlappedData());
-
- private OverlappedData m_overlappedData;
+ private OverlappedData _overlappedData;
public Overlapped()
{
- m_overlappedData = (OverlappedData)s_overlappedDataCache.Allocate();
- m_overlappedData.m_overlapped = this;
+ _overlappedData = new OverlappedData();
+ _overlappedData._overlapped = this;
}
- public Overlapped(int offsetLo, int offsetHi, IntPtr hEvent, IAsyncResult ar)
+ public Overlapped(int offsetLo, int offsetHi, IntPtr hEvent, IAsyncResult ar) : this()
{
- m_overlappedData = (OverlappedData)s_overlappedDataCache.Allocate();
- m_overlappedData.m_overlapped = this;
- m_overlappedData.m_nativeOverlapped.OffsetLow = offsetLo;
- m_overlappedData.m_nativeOverlapped.OffsetHigh = offsetHi;
- m_overlappedData.UserHandle = hEvent;
- m_overlappedData.m_asyncResult = ar;
+ _overlappedData.OffsetLow = offsetLo;
+ _overlappedData.OffsetHigh = offsetHi;
+ _overlappedData.EventHandle = hEvent;
+ _overlappedData.AsyncResult = ar;
}
[Obsolete("This constructor is not 64-bit compatible. Use the constructor that takes an IntPtr for the event handle. http://go.microsoft.com/fwlink/?linkid=14202")]
@@ -290,43 +247,33 @@ namespace System.Threading
public IAsyncResult AsyncResult
{
- get { return m_overlappedData.m_asyncResult; }
- set { m_overlappedData.m_asyncResult = value; }
+ get { return _overlappedData.AsyncResult; }
+ set { _overlappedData.AsyncResult = value; }
}
public int OffsetLow
{
- get { return m_overlappedData.m_nativeOverlapped.OffsetLow; }
- set { m_overlappedData.m_nativeOverlapped.OffsetLow = value; }
+ get { return _overlappedData.OffsetLow; }
+ set { _overlappedData.OffsetLow = value; }
}
public int OffsetHigh
{
- get { return m_overlappedData.m_nativeOverlapped.OffsetHigh; }
- set { m_overlappedData.m_nativeOverlapped.OffsetHigh = value; }
+ get { return _overlappedData.OffsetHigh; }
+ set { _overlappedData.OffsetHigh = value; }
}
[Obsolete("This property is not 64-bit compatible. Use EventHandleIntPtr instead. http://go.microsoft.com/fwlink/?linkid=14202")]
public int EventHandle
{
- get { return m_overlappedData.UserHandle.ToInt32(); }
- set { m_overlappedData.UserHandle = new IntPtr(value); }
+ get { return EventHandleIntPtr.ToInt32(); }
+ set { EventHandleIntPtr = new IntPtr(value); }
}
public IntPtr EventHandleIntPtr
{
- get { return m_overlappedData.UserHandle; }
- set { m_overlappedData.UserHandle = value; }
- }
-
- internal _IOCompletionCallback iocbHelper
- {
- get { return m_overlappedData.m_iocbHelper; }
- }
-
- internal IOCompletionCallback UserCallback
- {
- get { return m_overlappedData.m_iocb; }
+ get { return _overlappedData.EventHandle; }
+ set { _overlappedData.EventHandle = value; }
}
/*====================================================================
@@ -342,9 +289,9 @@ namespace System.Threading
}
[CLSCompliant(false)]
- public unsafe NativeOverlapped* Pack(IOCompletionCallback iocb, Object userData)
+ public unsafe NativeOverlapped* Pack(IOCompletionCallback iocb, object userData)
{
- return m_overlappedData.Pack(iocb, userData);
+ return _overlappedData.Pack(iocb, userData);
}
[Obsolete("This method is not safe. Use UnsafePack (iocb, userData) instead. http://go.microsoft.com/fwlink/?linkid=14202")]
@@ -355,9 +302,9 @@ namespace System.Threading
}
[CLSCompliant(false)]
- public unsafe NativeOverlapped* UnsafePack(IOCompletionCallback iocb, Object userData)
+ public unsafe NativeOverlapped* UnsafePack(IOCompletionCallback iocb, object userData)
{
- return m_overlappedData.UnsafePack(iocb, userData);
+ return _overlappedData.UnsafePack(iocb, userData);
}
/*====================================================================
@@ -370,9 +317,7 @@ namespace System.Threading
if (nativeOverlappedPtr == null)
throw new ArgumentNullException(nameof(nativeOverlappedPtr));
- Overlapped overlapped = OverlappedData.GetOverlappedFromNative(nativeOverlappedPtr).m_overlapped;
-
- return overlapped;
+ return OverlappedData.GetOverlappedFromNative(nativeOverlappedPtr)._overlapped;
}
[CLSCompliant(false)]
@@ -381,14 +326,10 @@ namespace System.Threading
if (nativeOverlappedPtr == null)
throw new ArgumentNullException(nameof(nativeOverlappedPtr));
- Overlapped overlapped = OverlappedData.GetOverlappedFromNative(nativeOverlappedPtr).m_overlapped;
+ OverlappedData.GetOverlappedFromNative(nativeOverlappedPtr)._overlapped._overlappedData = null;
OverlappedData.FreeNativeOverlapped(nativeOverlappedPtr);
- OverlappedData overlappedData = overlapped.m_overlappedData;
- overlapped.m_overlappedData = null;
- overlappedData.ReInitialize();
- s_overlappedDataCache.Free(overlappedData);
}
}
#endregion class Overlapped
-} // namespace
+}
diff --git a/src/System.Private.CoreLib/src/System/Threading/PinnableBufferCache.cs b/src/System.Private.CoreLib/src/System/Threading/PinnableBufferCache.cs
deleted file mode 100644
index 5ebeb4441..000000000
--- a/src/System.Private.CoreLib/src/System/Threading/PinnableBufferCache.cs
+++ /dev/null
@@ -1,693 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-//#define ENABLE
-//#define MINBUFFERS
-
-using System.Collections.Generic;
-using System.Runtime.ConstrainedExecution;
-using System.Runtime.InteropServices;
-
-namespace System.Threading
-{
- // Reduced copy of System.Collections.Concurrent.ConcurrentStack<T>
- internal class ConcurrentStack<T>
- {
- private class Node
- {
- internal readonly T _value; // Value of the node.
- internal Node _next; // Next pointer.
-
- internal Node(T value)
- {
- _value = value;
- _next = null;
- }
- }
-
- private volatile Node _head; // The stack is a singly linked list, and only remembers the head.
-
- private const int BACKOFF_MAX_YIELDS = 8; // Arbitrary number to cap backoff.
-
- public int Count
- {
- get
- {
- int count = 0;
-
- for (Node curr = _head; curr != null; curr = curr._next)
- {
- count++; //we don't handle overflow, to be consistent with existing generic collection types in CLR
- }
-
- return count;
- }
- }
-
- public void Push(T item)
- {
- Node newNode = new Node(item);
- newNode._next = _head;
- if (Interlocked.CompareExchange(ref _head, newNode, newNode._next) == newNode._next)
- {
- return;
- }
-
- // If we failed, go to the slow path and loop around until we succeed.
- PushCore(newNode, newNode);
- }
-
- private void PushCore(Node head, Node tail)
- {
- SpinWait spin = new SpinWait();
-
- // Keep trying to CAS the existing head with the new node until we succeed.
- do
- {
- spin.SpinOnce();
- // Reread the head and link our new node.
- tail._next = _head;
- }
- while (Interlocked.CompareExchange(
- ref _head, head, tail._next) != tail._next);
- }
-
- public bool TryPop(out T result)
- {
- Node head = _head;
- //stack is empty
- if (head == null)
- {
- result = default(T);
- return false;
- }
- if (Interlocked.CompareExchange(ref _head, head._next, head) == head)
- {
- result = head._value;
- return true;
- }
-
- // Fall through to the slow path.
- return TryPopCore(out result);
- }
-
- private bool TryPopCore(out T result)
- {
- Node poppedNode;
-
- if (TryPopCore(1, out poppedNode) == 1)
- {
- result = poppedNode._value;
- return true;
- }
-
- result = default(T);
- return false;
- }
-
- private int TryPopCore(int count, out Node poppedHead)
- {
- SpinWait spin = new SpinWait();
-
- // Try to CAS the head with its current next. We stop when we succeed or
- // when we notice that the stack is empty, whichever comes first.
- Node head;
- Node next;
- int backoff = 1;
- Random r = null;
- while (true)
- {
- head = _head;
- // Is the stack empty?
- if (head == null)
- {
- poppedHead = null;
- return 0;
- }
- next = head;
- int nodesCount = 1;
- for (; nodesCount < count && next._next != null; nodesCount++)
- {
- next = next._next;
- }
-
- // Try to swap the new head. If we succeed, break out of the loop.
- if (Interlocked.CompareExchange(ref _head, next._next, head) == head)
- {
- // Return the popped Node.
- poppedHead = head;
- return nodesCount;
- }
-
- // We failed to CAS the new head. Spin briefly and retry.
- for (int i = 0; i < backoff; i++)
- {
- spin.SpinOnce();
- }
-
- if (spin.NextSpinWillYield)
- {
- if (r == null)
- {
- r = new Random();
- }
- backoff = r.Next(1, BACKOFF_MAX_YIELDS);
- }
- else
- {
- backoff *= 2;
- }
- }
- }
- }
-
- internal sealed class PinnableBufferCache
- {
- /// <summary>
- /// Create a PinnableBufferCache that works on any object (it is intended for OverlappedData)
- /// This is only used in mscorlib.
- /// </summary>
- internal PinnableBufferCache(string cacheName, Func<object> factory)
- {
- m_NotGen2 = new List<object>(DefaultNumberOfBuffers);
- m_factory = factory;
-#if ENABLE
- // Check to see if we should disable the cache.
- string envVarName = "PinnableBufferCache_" + cacheName + "_Disabled";
- try
- {
- string envVar = Environment.GetEnvironmentVariable(envVarName);
- if (envVar != null)
- {
- PinnableBufferCacheEventSource.Log.DebugMessage("Creating " + cacheName + " PinnableBufferCacheDisabled=" + envVar);
- int index = envVar.IndexOf(cacheName, StringComparison.OrdinalIgnoreCase);
- if (0 <= index)
- {
- // The cache is disabled because we haven't set the cache name.
- PinnableBufferCacheEventSource.Log.DebugMessage("Disabling " + cacheName);
- return;
- }
- }
- }
- catch
- {
- // Ignore failures when reading the environment variable.
- }
-#endif
-#if MINBUFFERS
- // Allow the environment to specify a minimum buffer count.
- string minEnvVarName = "PinnableBufferCache_" + cacheName + "_MinCount";
- try
- {
- string minEnvVar = Environment.GetEnvironmentVariable(minEnvVarName);
- if (minEnvVar != null)
- {
- if (int.TryParse(minEnvVar, out m_minBufferCount))
- CreateNewBuffers();
- }
- }
- catch
- {
- // Ignore failures when reading the environment variable.
- }
-#endif
-
- PinnableBufferCacheEventSource.Log.Create(cacheName);
- m_CacheName = cacheName;
- }
-
- /// <summary>
- /// Get a object from the buffer manager. If no buffers exist, allocate a new one.
- /// </summary>
- internal object Allocate()
- {
-#if ENABLE
- // Check to see whether or not the cache is disabled.
- if (m_CacheName == null)
- return m_factory();
-#endif
- // Fast path, get it from our Gen2 aged m_FreeList.
- object returnBuffer;
- if (!m_FreeList.TryPop(out returnBuffer))
- Restock(out returnBuffer);
-
-#if LOGGING
- // Computing free count is expensive enough that we don't want to compute it unless logging is on.
- if (PinnableBufferCacheEventSource.Log.IsEnabled())
- {
- int numAllocCalls = Interlocked.Increment(ref m_numAllocCalls);
- if (numAllocCalls >= 1024)
- {
- lock (this)
- {
- int previousNumAllocCalls = Interlocked.Exchange(ref m_numAllocCalls, 0);
- if (previousNumAllocCalls >= 1024)
- {
- int nonGen2Count = 0;
- foreach (object o in m_FreeList)
- {
- if (GC.GetGeneration(o) < GC.MaxGeneration)
- {
- nonGen2Count++;
- }
- }
-
- PinnableBufferCacheEventSource.Log.WalkFreeListResult(m_CacheName, m_FreeList.Count, nonGen2Count);
- }
- }
- }
-
- PinnableBufferCacheEventSource.Log.AllocateBuffer(m_CacheName, PinnableBufferCacheEventSource.AddressOf(returnBuffer), returnBuffer.GetHashCode(), GC.GetGeneration(returnBuffer), m_FreeList.Count);
- }
-#endif
- return returnBuffer;
- }
-
- /// <summary>
- /// Return a buffer back to the buffer manager.
- /// </summary>
- internal void Free(object buffer)
- {
-#if ENABLE
- // Check to see whether or not the cache is disabled.
- if (m_CacheName == null)
- return;
-#endif
- if (PinnableBufferCacheEventSource.Log.IsEnabled())
- PinnableBufferCacheEventSource.Log.FreeBuffer(m_CacheName, PinnableBufferCacheEventSource.AddressOf(buffer), buffer.GetHashCode(), m_FreeList.Count);
-
-
- // After we've done 3 gen1 GCs, assume that all buffers have aged into gen2 on the free path.
- if ((m_gen1CountAtLastRestock + 3) > GC.CollectionCount(GC.MaxGeneration - 1))
- {
- lock (this)
- {
- if (GC.GetGeneration(buffer) < GC.MaxGeneration)
- {
- // The buffer is not aged, so put it in the non-aged free list.
- m_moreThanFreeListNeeded = true;
- PinnableBufferCacheEventSource.Log.FreeBufferStillTooYoung(m_CacheName, m_NotGen2.Count);
- m_NotGen2.Add(buffer);
- m_gen1CountAtLastRestock = GC.CollectionCount(GC.MaxGeneration - 1);
- return;
- }
- }
- }
-
- // If we discovered that it is indeed Gen2, great, put it in the Gen2 list.
- m_FreeList.Push(buffer);
- }
-
- #region Private
-
- /// <summary>
- /// Called when we don't have any buffers in our free list to give out.
- /// </summary>
- /// <returns></returns>
- private void Restock(out object returnBuffer)
- {
- lock (this)
- {
- // Try again after getting the lock as another thread could have just filled the free list. If we don't check
- // then we unnecessarily grab a new set of buffers because we think we are out.
- if (m_FreeList.TryPop(out returnBuffer))
- return;
-
- // Lazy init, Ask that TrimFreeListIfNeeded be called on every Gen 2 GC.
- if (m_restockSize == 0)
- Gen2GcCallback.Register(Gen2GcCallbackFunc, this);
-
- // Indicate to the trimming policy that the free list is insufficent.
- m_moreThanFreeListNeeded = true;
- PinnableBufferCacheEventSource.Log.AllocateBufferFreeListEmpty(m_CacheName, m_NotGen2.Count);
-
- // Get more buffers if needed.
- if (m_NotGen2.Count == 0)
- CreateNewBuffers();
-
- // We have no buffers in the aged freelist, so get one from the newer list. Try to pick the best one.
- // Debug.Assert(m_NotGen2.Count != 0);
- int idx = m_NotGen2.Count - 1;
- if (GC.GetGeneration(m_NotGen2[idx]) < GC.MaxGeneration && GC.GetGeneration(m_NotGen2[0]) == GC.MaxGeneration)
- idx = 0;
- returnBuffer = m_NotGen2[idx];
- m_NotGen2.RemoveAt(idx);
-
- // Remember any sub-optimial buffer so we don't put it on the free list when it gets freed.
- if (PinnableBufferCacheEventSource.Log.IsEnabled() && GC.GetGeneration(returnBuffer) < GC.MaxGeneration)
- {
- PinnableBufferCacheEventSource.Log.AllocateBufferFromNotGen2(m_CacheName, m_NotGen2.Count);
- }
-
- // If we have a Gen1 collection, then everything on m_NotGen2 should have aged. Move them to the m_Free list.
- if (!AgePendingBuffers())
- {
- // Before we could age at set of buffers, we have handed out half of them.
- // This implies we should be proactive about allocating more (since we will trim them if we over-allocate).
- if (m_NotGen2.Count == m_restockSize / 2)
- {
- PinnableBufferCacheEventSource.Log.DebugMessage("Proactively adding more buffers to aging pool");
- CreateNewBuffers();
- }
- }
- }
- }
-
- /// <summary>
- /// See if we can promote the buffers to the free list. Returns true if sucessful.
- /// </summary>
- private bool AgePendingBuffers()
- {
- if (m_gen1CountAtLastRestock < GC.CollectionCount(GC.MaxGeneration - 1))
- {
- // Allocate a temp list of buffers that are not actually in gen2, and swap it in once
- // we're done scanning all buffers.
- int promotedCount = 0;
- List<object> notInGen2 = new List<object>();
- PinnableBufferCacheEventSource.Log.AllocateBufferAged(m_CacheName, m_NotGen2.Count);
- for (int i = 0; i < m_NotGen2.Count; i++)
- {
- // We actually check every object to ensure that we aren't putting non-aged buffers into the free list.
- object currentBuffer = m_NotGen2[i];
- if (GC.GetGeneration(currentBuffer) >= GC.MaxGeneration)
- {
- m_FreeList.Push(currentBuffer);
- promotedCount++;
- }
- else
- {
- notInGen2.Add(currentBuffer);
- }
- }
- PinnableBufferCacheEventSource.Log.AgePendingBuffersResults(m_CacheName, promotedCount, notInGen2.Count);
- m_NotGen2 = notInGen2;
-
- return true;
- }
- return false;
- }
-
- /// <summary>
- /// Generates some buffers to age into Gen2.
- /// </summary>
- private void CreateNewBuffers()
- {
- // We choose a very modest number of buffers initially because for the client case. This is often enough.
- if (m_restockSize == 0)
- m_restockSize = 4;
- else if (m_restockSize < DefaultNumberOfBuffers)
- m_restockSize = DefaultNumberOfBuffers;
- else if (m_restockSize < 256)
- m_restockSize = m_restockSize * 2; // Grow quickly at small sizes
- else if (m_restockSize < 4096)
- m_restockSize = m_restockSize * 3 / 2; // Less aggressively at large ones
- else
- m_restockSize = 4096; // Cap how aggressive we are
-
- // Ensure we hit our minimums
- if (m_minBufferCount > m_buffersUnderManagement)
- m_restockSize = Math.Max(m_restockSize, m_minBufferCount - m_buffersUnderManagement);
-
- PinnableBufferCacheEventSource.Log.AllocateBufferCreatingNewBuffers(m_CacheName, m_buffersUnderManagement, m_restockSize);
- for (int i = 0; i < m_restockSize; i++)
- {
- // Make a new buffer.
- object newBuffer = m_factory();
-
- // Create space between the objects. We do this because otherwise it forms a single plug (group of objects)
- // and the GC pins the entire plug making them NOT move to Gen1 and Gen2. by putting space between them
- // we ensure that object get a chance to move independently (even if some are pinned).
- var dummyObject = new object();
- m_NotGen2.Add(newBuffer);
- }
- m_buffersUnderManagement += m_restockSize;
- m_gen1CountAtLastRestock = GC.CollectionCount(GC.MaxGeneration - 1);
- }
-
- /// <summary>
- /// This is the static function that is called from the gen2 GC callback.
- /// The input object is the cache itself.
- /// NOTE: The reason that we make this functionstatic and take the cache as a parameter is that
- /// otherwise, we root the cache to the Gen2GcCallback object, and leak the cache even when
- /// the application no longer needs it.
- /// </summary>
- private static bool Gen2GcCallbackFunc(object targetObj)
- {
- return ((PinnableBufferCache)(targetObj)).TrimFreeListIfNeeded();
- }
-
- /// <summary>
- /// This is called on every gen2 GC to see if we need to trim the free list.
- /// NOTE: DO NOT CALL THIS DIRECTLY FROM THE GEN2GCCALLBACK. INSTEAD CALL IT VIA A STATIC FUNCTION (SEE ABOVE).
- /// If you register a non-static function as a callback, then this object will be leaked.
- /// </summary>
- private bool TrimFreeListIfNeeded()
- {
- int curMSec = Environment.TickCount;
- int deltaMSec = curMSec - m_msecNoUseBeyondFreeListSinceThisTime;
- PinnableBufferCacheEventSource.Log.TrimCheck(m_CacheName, m_buffersUnderManagement, m_moreThanFreeListNeeded, deltaMSec);
-
- // If we needed more than just the set of aged buffers since the last time we were called,
- // we obviously should not be trimming any memory, so do nothing except reset the flag
- if (m_moreThanFreeListNeeded)
- {
- m_moreThanFreeListNeeded = false;
- m_trimmingExperimentInProgress = false;
- m_msecNoUseBeyondFreeListSinceThisTime = curMSec;
- return true;
- }
-
- // We require a minimum amount of clock time to pass (10 seconds) before we trim. Ideally this time
- // is larger than the typical buffer hold time.
- if (0 <= deltaMSec && deltaMSec < 10000)
- return true;
-
- // If we got here we have spend the last few second without needing to lengthen the free list. Thus
- // we have 'enough' buffers, but maybe we have too many.
- // See if we can trim
- lock (this)
- {
- // Hit a race, try again later.
- if (m_moreThanFreeListNeeded)
- {
- m_moreThanFreeListNeeded = false;
- m_trimmingExperimentInProgress = false;
- m_msecNoUseBeyondFreeListSinceThisTime = curMSec;
- return true;
- }
-
- var freeCount = m_FreeList.Count; // This is expensive to fetch, do it once.
-
- // If there is something in m_NotGen2 it was not used for the last few seconds, it is trimable.
- if (m_NotGen2.Count > 0)
- {
- // If we are not performing an experiment and we have stuff that is waiting to go into the
- // free list but has not made it there, it could be becasue the 'slow path' of restocking
- // has not happened, so force this (which should flush the list) and start over.
- if (!m_trimmingExperimentInProgress)
- {
- PinnableBufferCacheEventSource.Log.TrimFlush(m_CacheName, m_buffersUnderManagement, freeCount, m_NotGen2.Count);
- AgePendingBuffers();
- m_trimmingExperimentInProgress = true;
- return true;
- }
-
- PinnableBufferCacheEventSource.Log.TrimFree(m_CacheName, m_buffersUnderManagement, freeCount, m_NotGen2.Count);
- m_buffersUnderManagement -= m_NotGen2.Count;
-
- // Possibly revise the restocking down. We don't want to grow agressively if we are trimming.
- var newRestockSize = m_buffersUnderManagement / 4;
- if (newRestockSize < m_restockSize)
- m_restockSize = Math.Max(newRestockSize, DefaultNumberOfBuffers);
-
- m_NotGen2.Clear();
- m_trimmingExperimentInProgress = false;
- return true;
- }
-
- // Set up an experiment where we use 25% less buffers in our free list. We put them in
- // m_NotGen2, and if they are needed they will be put back in the free list again.
- var trimSize = freeCount / 4 + 1;
-
- // We are OK with a 15% overhead, do nothing in that case.
- if (freeCount * 15 <= m_buffersUnderManagement || m_buffersUnderManagement - trimSize <= m_minBufferCount)
- {
- PinnableBufferCacheEventSource.Log.TrimFreeSizeOK(m_CacheName, m_buffersUnderManagement, freeCount);
- return true;
- }
-
- // Move buffers from the free list back to the non-aged list. If we don't use them by next time, then we'll consider trimming them.
- PinnableBufferCacheEventSource.Log.TrimExperiment(m_CacheName, m_buffersUnderManagement, freeCount, trimSize);
- object buffer;
- for (int i = 0; i < trimSize; i++)
- {
- if (m_FreeList.TryPop(out buffer))
- m_NotGen2.Add(buffer);
- }
- m_msecNoUseBeyondFreeListSinceThisTime = curMSec;
- m_trimmingExperimentInProgress = true;
- }
-
- // Indicate that we want to be called back on the next Gen 2 GC.
- return true;
- }
-
- private const int DefaultNumberOfBuffers = 16;
- private string m_CacheName;
- private Func<object> m_factory;
-
- /// <summary>
- /// Contains 'good' buffers to reuse. They are guarenteed to be Gen 2 ENFORCED!
- /// </summary>
- private ConcurrentStack<object> m_FreeList = new ConcurrentStack<object>();
- /// <summary>
- /// Contains buffers that are not gen 2 and thus we do not wish to give out unless we have to.
- /// To implement trimming we sometimes put aged buffers in here as a place to 'park' them
- /// before true deletion.
- /// </summary>
- private List<object> m_NotGen2;
- /// <summary>
- /// What whas the gen 1 count the last time re restocked? If it is now greater, then
- /// we know that all objects are in Gen 2 so we don't have to check. Should be updated
- /// every time something gets added to the m_NotGen2 list.
- /// </summary>
- private int m_gen1CountAtLastRestock;
-
- /// <summary>
- /// Used to ensure we have a minimum time between trimmings.
- /// </summary>
- private int m_msecNoUseBeyondFreeListSinceThisTime;
- /// <summary>
- /// To trim, we remove things from the free list (which is Gen 2) and see if we 'hit bottom'
- /// This flag indicates that we hit bottom (we really needed a bigger free list).
- /// </summary>
- private bool m_moreThanFreeListNeeded;
- /// <summary>
- /// The total number of buffers that this cache has ever allocated.
- /// Used in trimming heuristics.
- /// </summary>
- private int m_buffersUnderManagement;
- /// <summary>
- /// The number of buffers we added the last time we restocked.
- /// </summary>
- private int m_restockSize;
- /// <summary>
- /// Did we put some buffers into m_NotGen2 to see if we can trim?
- /// </summary>
- private bool m_trimmingExperimentInProgress;
-#pragma warning disable 0649
- /// <summary>
- /// A forced minimum number of buffers.
- /// </summary>
- private int m_minBufferCount;
-#pragma warning restore 0649
-#if LOGGING
- /// <summary>
- /// The number of calls to Allocate.
- /// </summary>
- private int m_numAllocCalls;
-#endif
-
- #endregion
- }
-
- /// <summary>
- /// Schedules a callback roughly every gen 2 GC (you may see a Gen 0 an Gen 1 but only once)
- /// (We can fix this by capturing the Gen 2 count at startup and testing, but I mostly don't care)
- /// </summary>
- internal sealed class Gen2GcCallback : CriticalFinalizerObject
- {
- public Gen2GcCallback()
- : base()
- {
- }
-
- /// <summary>
- /// Schedule 'callback' to be called in the next GC. If the callback returns true it is
- /// rescheduled for the next Gen 2 GC. Otherwise the callbacks stop.
- ///
- /// NOTE: This callback will be kept alive until either the callback function returns false,
- /// or the target object dies.
- /// </summary>
- public static void Register(Func<object, bool> callback, object targetObj)
- {
- // Create a unreachable object that remembers the callback function and target object.
- Gen2GcCallback gcCallback = new Gen2GcCallback();
- gcCallback.Setup(callback, targetObj);
- }
-
- #region Private
-
- private Func<object, bool> m_callback;
- private GCHandle m_weakTargetObj;
-
- private void Setup(Func<object, bool> callback, object targetObj)
- {
- m_callback = callback;
- m_weakTargetObj = GCHandle.Alloc(targetObj, GCHandleType.Weak);
- }
-
- ~Gen2GcCallback()
- {
- // Check to see if the target object is still alive.
- object targetObj = m_weakTargetObj.Target;
- if (targetObj == null)
- {
- // The target object is dead, so this callback object is no longer needed.
- m_weakTargetObj.Free();
- return;
- }
-
- // Execute the callback method.
- try
- {
- if (!m_callback(targetObj))
- {
- // If the callback returns false, this callback object is no longer needed.
- return;
- }
- }
- catch
- {
- // Ensure that we still get a chance to resurrect this object, even if the callback throws an exception.
- }
-
- // Resurrect ourselves by re-registering for finalization.
- if (!Environment.HasShutdownStarted /*&& !AppDomain.CurrentDomain.IsFinalizingForUnload()*/)
- {
- GC.ReRegisterForFinalize(this);
- }
- }
-
- #endregion
- }
-
- internal sealed class PinnableBufferCacheEventSource
- {
- public static readonly PinnableBufferCacheEventSource Log = new PinnableBufferCacheEventSource();
-
- public bool IsEnabled() { return false; }
- public void DebugMessage(string message) { }
- public void Create(string cacheName) { }
- public void AllocateBuffer(string cacheName, ulong objectId, int objectHash, int objectGen, int freeCountAfter) { }
- public void AllocateBufferFromNotGen2(string cacheName, int notGen2CountAfter) { }
- public void AllocateBufferCreatingNewBuffers(string cacheName, int totalBuffsBefore, int objectCount) { }
- public void AllocateBufferAged(string cacheName, int agedCount) { }
- public void AllocateBufferFreeListEmpty(string cacheName, int notGen2CountBefore) { }
- public void FreeBuffer(string cacheName, ulong objectId, int objectHash, int freeCountBefore) { }
- public void FreeBufferStillTooYoung(string cacheName, int notGen2CountBefore) { }
- public void TrimCheck(string cacheName, int totalBuffs, bool neededMoreThanFreeList, int deltaMSec) { }
- public void TrimFree(string cacheName, int totalBuffs, int freeListCount, int toBeFreed) { }
- public void TrimExperiment(string cacheName, int totalBuffs, int freeListCount, int numTrimTrial) { }
- public void TrimFreeSizeOK(string cacheName, int totalBuffs, int freeListCount) { }
- public void TrimFlush(string cacheName, int totalBuffs, int freeListCount, int notGen2CountBefore) { }
- public void AgePendingBuffersResults(string cacheName, int promotedToFreeListCount, int heldBackCount) { }
- public void WalkFreeListResult(string cacheName, int freeListCount, int gen0BuffersInFreeList) { }
-
- static internal ulong AddressOf(object obj)
- {
- return 0;
- }
- }
-}
diff --git a/src/System.Private.CoreLib/src/System/Threading/Semaphore.Unix.cs b/src/System.Private.CoreLib/src/System/Threading/Semaphore.Unix.cs
index 229cd0c49..04f34bce4 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Semaphore.Unix.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Semaphore.Unix.cs
@@ -2,24 +2,21 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using Microsoft.Win32.SafeHandles;
using System.Diagnostics;
using System.IO;
+using System.Runtime.InteropServices;
namespace System.Threading
{
public sealed partial class Semaphore
{
- private static void VerifyNameForCreate(string name)
+ private void CreateSemaphoreCore(int initialCount, int maximumCount, string name, out bool createdNew)
{
if (name != null)
{
throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
}
- }
-
- private void CreateSemaphoreCore(int initialCount, int maximumCount, string name, out bool createdNew)
- {
- Debug.Assert(name == null);
SafeWaitHandle = WaitSubsystem.NewSemaphore(initialCount, maximumCount);
createdNew = true;
@@ -30,9 +27,25 @@ namespace System.Threading
throw new PlatformNotSupportedException(SR.PlatformNotSupported_NamedSynchronizationPrimitives);
}
- private static int ReleaseCore(IntPtr handle, int releaseCount)
+ private int ReleaseCore(int releaseCount)
{
- return WaitSubsystem.ReleaseSemaphore(handle, releaseCount);
+ // The field value is modifiable via the public <see cref="WaitHandle.SafeWaitHandle"/> property, save it locally
+ // to ensure that one instance is used in all places in this method
+ SafeWaitHandle waitHandle = _waitHandle;
+ if (waitHandle == null)
+ {
+ ThrowInvalidHandleException();
+ }
+
+ waitHandle.DangerousAddRef();
+ try
+ {
+ return WaitSubsystem.ReleaseSemaphore(waitHandle.DangerousGetHandle(), releaseCount);
+ }
+ finally
+ {
+ waitHandle.DangerousRelease();
+ }
}
}
}
diff --git a/src/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs b/src/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs
deleted file mode 100644
index 3eab7f5d2..000000000
--- a/src/System.Private.CoreLib/src/System/Threading/Semaphore.Windows.cs
+++ /dev/null
@@ -1,106 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-using Microsoft.Win32.SafeHandles;
-
-namespace System.Threading
-{
- public sealed partial class Semaphore
- {
- private const uint AccessRights = (uint)(Interop.Constants.MaximumAllowed | Interop.Constants.Synchronize | Interop.Constants.SemaphoreModifyState);
-
- private Semaphore(SafeWaitHandle handle)
- {
- SafeWaitHandle = handle;
- }
-
- private static void VerifyNameForCreate(string name)
- {
- if (null != name && Interop.Kernel32.MAX_PATH < name.Length)
- {
- throw new ArgumentException(SR.Format(SR.Argument_WaitHandleNameTooLong, Interop.Kernel32.MAX_PATH), nameof(name));
- }
- }
-
- private void CreateSemaphoreCore(int initialCount, int maximumCount, string name, out bool createdNew)
- {
- Debug.Assert(initialCount >= 0);
- Debug.Assert(maximumCount >= 1);
- Debug.Assert(initialCount <= maximumCount);
- Debug.Assert(name == null || name.Length <= Interop.Kernel32.MAX_PATH);
-
- SafeWaitHandle myHandle = Interop.mincore.CreateSemaphoreEx(IntPtr.Zero, initialCount, maximumCount, name, 0, AccessRights);
-
- if (myHandle.IsInvalid)
- {
- int errorCode = Marshal.GetLastWin32Error();
- if (null != name && 0 != name.Length && Interop.Errors.ERROR_INVALID_HANDLE == errorCode)
- throw new WaitHandleCannotBeOpenedException(SR.Format(SR.Threading_WaitHandleCannotBeOpenedException_InvalidHandle, name));
- throw ExceptionFromCreationError(errorCode, name);
- }
- else if (name != null)
- {
- int errorCode = Marshal.GetLastWin32Error();
- createdNew = errorCode != Interop.Errors.ERROR_ALREADY_EXISTS;
- }
- else
- {
- createdNew = true;
- }
-
- SafeWaitHandle = myHandle;
- }
-
- private static OpenExistingResult OpenExistingWorker(string name, out Semaphore result)
- {
- if (name == null)
- {
- throw new ArgumentNullException(nameof(name));
- }
- if (name.Length == 0)
- {
- throw new ArgumentException(SR.Argument_EmptyName, nameof(name));
- }
- if (null != name && Interop.Kernel32.MAX_PATH < name.Length)
- {
- throw new ArgumentException(SR.Format(SR.Argument_WaitHandleNameTooLong, Interop.Kernel32.MAX_PATH), nameof(name));
- }
-
- result = null;
-
- SafeWaitHandle myHandle = Interop.mincore.OpenSemaphore(AccessRights, false, name);
-
- if (myHandle.IsInvalid)
- {
- int errorCode = Marshal.GetLastWin32Error();
-
- if (Interop.Errors.ERROR_FILE_NOT_FOUND == errorCode || Interop.Errors.ERROR_INVALID_NAME == errorCode)
- return OpenExistingResult.NameNotFound;
- if (Interop.Errors.ERROR_PATH_NOT_FOUND == errorCode)
- return OpenExistingResult.PathNotFound;
- if (null != name && 0 != name.Length && Interop.Errors.ERROR_INVALID_HANDLE == errorCode)
- return OpenExistingResult.NameInvalid;
-
- throw ExceptionFromCreationError(errorCode, name);
- }
- result = new Semaphore(myHandle);
- return OpenExistingResult.Success;
- }
-
- private static int ReleaseCore(IntPtr handle, int releaseCount)
- {
- Debug.Assert(releaseCount > 0);
-
- int previousCount;
- if (!Interop.mincore.ReleaseSemaphore(handle, releaseCount, out previousCount))
- {
- ThrowSignalOrUnsignalException();
- }
-
- return previousCount;
- }
- }
-}
diff --git a/src/System.Private.CoreLib/src/System/Threading/SynchronizationContext.cs b/src/System.Private.CoreLib/src/System/Threading/SynchronizationContext.cs
index 92df1152a..f939c1647 100644
--- a/src/System.Private.CoreLib/src/System/Threading/SynchronizationContext.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/SynchronizationContext.cs
@@ -43,12 +43,12 @@ namespace System.Threading
return ((_props & SynchronizationContextProperties.RequireWaitNotification) != 0);
}
- public virtual void Send(SendOrPostCallback d, Object state)
+ public virtual void Send(SendOrPostCallback d, object state)
{
d(state);
}
- public virtual void Post(SendOrPostCallback d, Object state)
+ public virtual void Post(SendOrPostCallback d, object state)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(d), state);
}
diff --git a/src/System.Private.CoreLib/src/System/Threading/Tasks/DebuggerSupport.Dummy.cs b/src/System.Private.CoreLib/src/System/Threading/Tasks/DebuggerSupport.Dummy.cs
index 2cfa1be1f..12da2bd90 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Tasks/DebuggerSupport.Dummy.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Tasks/DebuggerSupport.Dummy.cs
@@ -22,7 +22,7 @@ namespace System.Threading.Tasks
}
}
- public static void TraceOperationCreation(CausalityTraceLevel traceLevel, Task task, String operationName, ulong relatedContext)
+ public static void TraceOperationCreation(CausalityTraceLevel traceLevel, Task task, string operationName, ulong relatedContext)
{
}
diff --git a/src/System.Private.CoreLib/src/System/Threading/Tasks/DebuggerSupport.cs b/src/System.Private.CoreLib/src/System/Threading/Tasks/DebuggerSupport.cs
index 0ee81c937..d58332dc1 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Tasks/DebuggerSupport.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Tasks/DebuggerSupport.cs
@@ -60,7 +60,7 @@ namespace System.Threading.Tasks
}
private static readonly LowLevelDictionary<int, Task> s_activeTasks = new LowLevelDictionary<int, Task>();
- private static readonly Object s_activeTasksLock = new Object();
+ private static readonly object s_activeTasksLock = new object();
//==============================================================================================================
// This section of the class wraps calls to get the lazy-created Task object for the purpose of reporting
diff --git a/src/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs b/src/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs
index ed2c06d74..6cb386ce0 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs
@@ -128,7 +128,6 @@ namespace System.Threading.Tasks
: this(function, null, default(CancellationToken),
TaskCreationOptions.None, InternalTaskOptions.None, null)
{
- PossiblyCaptureContext();
}
@@ -150,7 +149,6 @@ namespace System.Threading.Tasks
: this(function, null, cancellationToken,
TaskCreationOptions.None, InternalTaskOptions.None, null)
{
- PossiblyCaptureContext();
}
/// <summary>
@@ -174,7 +172,6 @@ namespace System.Threading.Tasks
public Task(Func<TResult> function, TaskCreationOptions creationOptions)
: this(function, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken), creationOptions, InternalTaskOptions.None, null)
{
- PossiblyCaptureContext();
}
/// <summary>
@@ -202,7 +199,6 @@ namespace System.Threading.Tasks
public Task(Func<TResult> function, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
: this(function, Task.InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null)
{
- PossiblyCaptureContext();
}
/// <summary>
@@ -220,7 +216,6 @@ namespace System.Threading.Tasks
: this(function, state, null, default(CancellationToken),
TaskCreationOptions.None, InternalTaskOptions.None, null)
{
- PossiblyCaptureContext();
}
/// <summary>
@@ -242,7 +237,6 @@ namespace System.Threading.Tasks
: this(function, state, null, cancellationToken,
TaskCreationOptions.None, InternalTaskOptions.None, null)
{
- PossiblyCaptureContext();
}
/// <summary>
@@ -268,7 +262,6 @@ namespace System.Threading.Tasks
: this(function, state, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken),
creationOptions, InternalTaskOptions.None, null)
{
- PossiblyCaptureContext();
}
@@ -299,7 +292,6 @@ namespace System.Threading.Tasks
: this(function, state, Task.InternalCurrentIfAttached(creationOptions), cancellationToken,
creationOptions, InternalTaskOptions.None, null)
{
- PossiblyCaptureContext();
}
/// <summary>
@@ -315,7 +307,6 @@ namespace System.Threading.Tasks
TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler) :
base(valueSelector, null, parent, cancellationToken, creationOptions, internalOptions, scheduler)
{
- PossiblyCaptureContext();
}
@@ -333,7 +324,6 @@ namespace System.Threading.Tasks
TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler) :
base(valueSelector, state, parent, cancellationToken, creationOptions, internalOptions, scheduler)
{
- PossiblyCaptureContext();
}
@@ -783,7 +773,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
- public Task ContinueWith(Action<Task<TResult>, Object> continuationAction, Object state)
+ public Task ContinueWith(Action<Task<TResult>, object> continuationAction, object state)
{
return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None);
}
@@ -810,7 +800,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- public Task ContinueWith(Action<Task<TResult>, Object> continuationAction, Object state, CancellationToken cancellationToken)
+ public Task ContinueWith(Action<Task<TResult>, object> continuationAction, object state, CancellationToken cancellationToken)
{
return ContinueWith(continuationAction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
@@ -839,7 +829,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
- public Task ContinueWith(Action<Task<TResult>, Object> continuationAction, Object state, TaskScheduler scheduler)
+ public Task ContinueWith(Action<Task<TResult>, object> continuationAction, object state, TaskScheduler scheduler)
{
return ContinueWith(continuationAction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None);
}
@@ -873,7 +863,7 @@ namespace System.Threading.Tasks
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
- public Task ContinueWith(Action<Task<TResult>, Object> continuationAction, Object state, TaskContinuationOptions continuationOptions)
+ public Task ContinueWith(Action<Task<TResult>, object> continuationAction, object state, TaskContinuationOptions continuationOptions)
{
return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions);
}
@@ -917,14 +907,14 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- public Task ContinueWith(Action<Task<TResult>, Object> continuationAction, Object state, CancellationToken cancellationToken,
+ public Task ContinueWith(Action<Task<TResult>, object> continuationAction, object state, CancellationToken cancellationToken,
TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
return ContinueWith(continuationAction, state, scheduler, cancellationToken, continuationOptions);
}
// Same as the above overload, only with a stack mark.
- internal Task ContinueWith(Action<Task<TResult>, Object> continuationAction, Object state, TaskScheduler scheduler, CancellationToken cancellationToken,
+ internal Task ContinueWith(Action<Task<TResult>, object> continuationAction, object state, TaskScheduler scheduler, CancellationToken cancellationToken,
TaskContinuationOptions continuationOptions)
{
if (continuationAction == null)
@@ -1195,7 +1185,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
- public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, Object, TNewResult> continuationFunction, Object state)
+ public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state)
{
return ContinueWith<TNewResult>(continuationFunction, state, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None);
}
@@ -1225,7 +1215,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, Object, TNewResult> continuationFunction, Object state,
+ public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state,
CancellationToken cancellationToken)
{
return ContinueWith<TNewResult>(continuationFunction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
@@ -1257,7 +1247,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
- public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, Object, TNewResult> continuationFunction, Object state,
+ public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state,
TaskScheduler scheduler)
{
return ContinueWith<TNewResult>(continuationFunction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None);
@@ -1301,7 +1291,7 @@ namespace System.Threading.Tasks
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
- public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, Object, TNewResult> continuationFunction, Object state,
+ public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state,
TaskContinuationOptions continuationOptions)
{
return ContinueWith<TNewResult>(continuationFunction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions);
@@ -1356,14 +1346,14 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, Object, TNewResult> continuationFunction, Object state,
+ public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state,
CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
return ContinueWith<TNewResult>(continuationFunction, state, scheduler, cancellationToken, continuationOptions);
}
// Same as the above overload, just with a stack mark.
- internal Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, Object, TNewResult> continuationFunction, Object state,
+ internal Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, object, TNewResult> continuationFunction, object state,
TaskScheduler scheduler, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
{
if (continuationFunction == null)
diff --git a/src/System.Private.CoreLib/src/System/Threading/Tasks/FutureFactory.cs b/src/System.Private.CoreLib/src/System/Threading/Tasks/FutureFactory.cs
index b27b1858f..f1b4d0e74 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Tasks/FutureFactory.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Tasks/FutureFactory.cs
@@ -401,7 +401,7 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- public Task<TResult> StartNew(Func<Object, TResult> function, Object state)
+ public Task<TResult> StartNew(Func<object, TResult> function, object state)
{
Task currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
@@ -430,7 +430,7 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- public Task<TResult> StartNew(Func<Object, TResult> function, Object state, CancellationToken cancellationToken)
+ public Task<TResult> StartNew(Func<object, TResult> function, object state, CancellationToken cancellationToken)
{
Task currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, state, cancellationToken,
@@ -461,7 +461,7 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- public Task<TResult> StartNew(Func<Object, TResult> function, Object state, TaskCreationOptions creationOptions)
+ public Task<TResult> StartNew(Func<object, TResult> function, object state, TaskCreationOptions creationOptions)
{
Task currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
@@ -503,7 +503,7 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- public Task<TResult> StartNew(Func<Object, TResult> function, Object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler)
+ public Task<TResult> StartNew(Func<object, TResult> function, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler)
{
return Task<TResult>.StartNew(Task.InternalCurrentIfAttached(creationOptions), function, state, cancellationToken,
creationOptions, InternalTaskOptions.None, scheduler);
@@ -679,10 +679,10 @@ namespace System.Threading.Tasks
// Just specify this task as detached. No matter what happens, we want endMethod
// to be called -- even if the parent is canceled. So we don't want to flow
// RespectParentCancellation.
- Task t = new Task(delegate
+ Task t = new Task(new Action<object>(delegate
{
FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: true);
- },
+ }),
(object)null, null,
default(CancellationToken), TaskCreationOptions.None, InternalTaskOptions.None, null);
diff --git a/src/System.Private.CoreLib/src/System/Threading/Tasks/ProducerConsumerQueues.cs b/src/System.Private.CoreLib/src/System/Threading/Tasks/ProducerConsumerQueues.cs
index 915f7c41f..83ff877e3 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Tasks/ProducerConsumerQueues.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Tasks/ProducerConsumerQueues.cs
@@ -135,7 +135,7 @@ namespace System.Threading.Tasks
/// <summary>The initial size to use for segments (in number of elements).</summary>
private const int INIT_SEGMENT_SIZE = 32; // must be a power of 2
/// <summary>The maximum size to use for segments (in number of elements).</summary>
- private const int MAX_SEGMENT_SIZE = 0x1000000; // this could be made as large as Int32.MaxValue / 2
+ private const int MAX_SEGMENT_SIZE = 0x1000000; // this could be made as large as int.MaxValue / 2
/// <summary>The head of the linked list of segments.</summary>
private volatile Segment m_head;
@@ -149,7 +149,7 @@ namespace System.Threading.Tasks
Debug.Assert(INIT_SEGMENT_SIZE > 0, "Initial segment size must be > 0.");
Debug.Assert((INIT_SEGMENT_SIZE & (INIT_SEGMENT_SIZE - 1)) == 0, "Initial segment size must be a power of 2");
Debug.Assert(INIT_SEGMENT_SIZE <= MAX_SEGMENT_SIZE, "Initial segment size should be <= maximum.");
- Debug.Assert(MAX_SEGMENT_SIZE < Int32.MaxValue / 2, "Max segment size * 2 must be < Int32.MaxValue, or else overflow could occur.");
+ Debug.Assert(MAX_SEGMENT_SIZE < int.MaxValue / 2, "Max segment size * 2 must be < int.MaxValue, or else overflow could occur.");
// Initialize the queue
m_head = m_tail = new Segment(INIT_SEGMENT_SIZE);
@@ -552,7 +552,7 @@ namespace System.Threading.Tasks
}
/// <summary>Padding structure used to minimize false sharing in SingleProducerSingleConsumerQueue{T}.</summary>
- [StructLayout(LayoutKind.Explicit, Size = PaddingHelpers.CACHE_LINE_SIZE - sizeof(Int32))] // Based on common case of 64-byte cache lines
+ [StructLayout(LayoutKind.Explicit, Size = PaddingHelpers.CACHE_LINE_SIZE - sizeof(int))] // Based on common case of 64-byte cache lines
internal struct PaddingFor32
{
}
diff --git a/src/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs b/src/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs
index 185449d18..f486de668 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs
@@ -245,11 +245,11 @@ namespace System.Threading.Tasks
}
/// <summary>
- /// Checks if we registered a CT callback during construction, and deregisters it.
+ /// Checks if we registered a CT callback during construction, and unregisters it.
/// This should be called when we know the registration isn't useful anymore. Specifically from Finish() if the task has completed
/// successfully or with an exception.
/// </summary>
- internal void DeregisterCancellationCallback()
+ internal void UnregisterCancellationCallback()
{
if (m_cancellationRegistration != null)
{
@@ -333,7 +333,6 @@ namespace System.Threading.Tasks
public Task(Action action)
: this(action, null, null, default(CancellationToken), TaskCreationOptions.None, InternalTaskOptions.None, null)
{
- PossiblyCaptureContext();
}
/// <summary>
@@ -349,7 +348,6 @@ namespace System.Threading.Tasks
public Task(Action action, CancellationToken cancellationToken)
: this(action, null, null, cancellationToken, TaskCreationOptions.None, InternalTaskOptions.None, null)
{
- PossiblyCaptureContext();
}
/// <summary>
@@ -370,7 +368,6 @@ namespace System.Threading.Tasks
public Task(Action action, TaskCreationOptions creationOptions)
: this(action, null, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken), creationOptions, InternalTaskOptions.None, null)
{
- PossiblyCaptureContext();
}
/// <summary>
@@ -395,7 +392,6 @@ namespace System.Threading.Tasks
public Task(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
: this(action, null, Task.InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null)
{
- PossiblyCaptureContext();
}
@@ -410,7 +406,6 @@ namespace System.Threading.Tasks
public Task(Action<object> action, object state)
: this(action, state, null, default(CancellationToken), TaskCreationOptions.None, InternalTaskOptions.None, null)
{
- PossiblyCaptureContext();
}
/// <summary>
@@ -428,7 +423,6 @@ namespace System.Threading.Tasks
public Task(Action<object> action, object state, CancellationToken cancellationToken)
: this(action, state, null, cancellationToken, TaskCreationOptions.None, InternalTaskOptions.None, null)
{
- PossiblyCaptureContext();
}
/// <summary>
@@ -450,7 +444,6 @@ namespace System.Threading.Tasks
public Task(Action<object> action, object state, TaskCreationOptions creationOptions)
: this(action, state, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken), creationOptions, InternalTaskOptions.None, null)
{
- PossiblyCaptureContext();
}
/// <summary>
@@ -476,19 +469,11 @@ namespace System.Threading.Tasks
public Task(Action<object> action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
: this(action, state, Task.InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null)
{
- PossiblyCaptureContext();
}
- internal Task(Action<object> action, object state, Task parent, CancellationToken cancellationToken,
- TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
- : this((Delegate)action, state, parent, cancellationToken, creationOptions, internalOptions, scheduler)
- {
- PossiblyCaptureContext();
- }
/// <summary>
/// An internal constructor used by the factory methods on task and its descendent(s).
- /// This variant does not capture the ExecutionContext; it is up to the caller to do that.
/// </summary>
/// <param name="action">An action to execute.</param>
/// <param name="state">Optional state to pass to the action.</param>
@@ -590,6 +575,11 @@ namespace System.Threading.Tasks
AssignCancellationToken(cancellationToken, null, null);
}
+
+ Debug.Assert(m_contingentProperties == null || m_contingentProperties.m_capturedContext == null,
+ "Captured an ExecutionContext when one was already captured.");
+
+ CapturedContext = ExecutionContext.Capture();
}
/// <summary>
@@ -658,8 +648,8 @@ namespace System.Threading.Tasks
// Static delegate to be used as a cancellation callback on unstarted tasks that have a valid cancellation token.
// This is necessary to transition them into canceled state if their cancellation token is signalled while they are still not queued
- private static readonly Action<Object> s_taskCancelCallback = new Action<Object>(TaskCancelCallback);
- private static void TaskCancelCallback(Object o)
+ private static readonly Action<object> s_taskCancelCallback = new Action<object>(TaskCancelCallback);
+ private static void TaskCancelCallback(object o)
{
var targetTask = o as Task;
if (targetTask == null)
@@ -782,19 +772,6 @@ namespace System.Threading.Tasks
}
}
- /// <summary>
- /// Captures the ExecutionContext so long as flow isn't suppressed.
- /// </summary>
- /// <param name="stackMark">A stack crawl mark pointing to the frame of the caller.</param>
-
- internal void PossiblyCaptureContext()
- {
- Debug.Assert(m_contingentProperties == null || m_contingentProperties.m_capturedContext == null,
- "Captured an ExecutionContext when one was already captured.");
-
- CapturedContext = ExecutionContext.Capture();
- }
-
// Internal property to process TaskCreationOptions access and mutation.
internal TaskCreationOptions Options
{
@@ -1273,7 +1250,6 @@ namespace System.Threading.Tasks
// Create and schedule the task. This throws an InvalidOperationException if already shut down.
// Here we add the InternalTaskOptions.QueuedByRuntime to the internalOptions, so that TaskConstructorCore can skip the cancellation token registration
Task t = new Task(action, state, creatingTask, cancellationToken, options, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler);
- t.PossiblyCaptureContext();
t.ScheduleAndStart(false);
return t;
@@ -2212,7 +2188,7 @@ namespace System.Threading.Tasks
if (cp != null)
{
cp.SetCompleted();
- cp.DeregisterCancellationCallback();
+ cp.UnregisterCancellationCallback();
}
// ready to run continuations and notify parent.
@@ -2675,7 +2651,7 @@ namespace System.Threading.Tasks
public bool Wait(TimeSpan timeout)
{
long totalMilliseconds = (long)timeout.TotalMilliseconds;
- if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
{
throw new ArgumentOutOfRangeException(nameof(timeout));
}
@@ -2951,27 +2927,19 @@ namespace System.Threading.Tasks
return false;
}
- //This code is pretty similar to the custom spinning in MRES except there is no yieling after we exceed the spin count
- const int YIELD_THRESHOLD = 10; // When to switch over to a true yield.
- int spinCount = PlatformHelper.IsSingleProcessor ? 1 : YIELD_THRESHOLD; //spin only once if we are running on a single CPU
- for (int i = 0; i < spinCount; i++)
+ int spinCount = Threading.SpinWait.SpinCountforSpinBeforeWait;
+ var spinner = new SpinWait();
+ while (spinner.Count < spinCount)
{
+ spinner.SpinOnce(sleep1Threshold: -1);
+
if (IsCompleted)
{
return true;
}
-
- if (i == spinCount / 2)
- {
- RuntimeThread.Yield();
- }
- else
- {
- RuntimeThread.SpinWait(PlatformHelper.ProcessorCount * (4 << i));
- }
}
- return IsCompleted;
+ return false;
}
/// <summary>
@@ -3142,7 +3110,7 @@ namespace System.Threading.Tasks
if (cp != null)
{
cp.SetCompleted();
- cp.DeregisterCancellationCallback();
+ cp.UnregisterCancellationCallback();
}
if (DebuggerSupport.LoggingOn)
@@ -3514,7 +3482,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
- public Task ContinueWith(Action<Task, Object> continuationAction, Object state)
+ public Task ContinueWith(Action<Task, object> continuationAction, object state)
{
return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None);
}
@@ -3540,7 +3508,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- public Task ContinueWith(Action<Task, Object> continuationAction, Object state, CancellationToken cancellationToken)
+ public Task ContinueWith(Action<Task, object> continuationAction, object state, CancellationToken cancellationToken)
{
return ContinueWith(continuationAction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
@@ -3568,7 +3536,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
- public Task ContinueWith(Action<Task, Object> continuationAction, Object state, TaskScheduler scheduler)
+ public Task ContinueWith(Action<Task, object> continuationAction, object state, TaskScheduler scheduler)
{
return ContinueWith(continuationAction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None);
}
@@ -3602,7 +3570,7 @@ namespace System.Threading.Tasks
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
- public Task ContinueWith(Action<Task, Object> continuationAction, Object state, TaskContinuationOptions continuationOptions)
+ public Task ContinueWith(Action<Task, object> continuationAction, object state, TaskContinuationOptions continuationOptions)
{
return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions);
}
@@ -3646,13 +3614,13 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- public Task ContinueWith(Action<Task, Object> continuationAction, Object state, CancellationToken cancellationToken,
+ public Task ContinueWith(Action<Task, object> continuationAction, object state, CancellationToken cancellationToken,
TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
return ContinueWith(continuationAction, state, scheduler, cancellationToken, continuationOptions);
}
- private Task ContinueWith(Action<Task, Object> continuationAction, Object state, TaskScheduler scheduler,
+ private Task ContinueWith(Action<Task, object> continuationAction, object state, TaskScheduler scheduler,
CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
{
// Throw on continuation with null action
@@ -3909,7 +3877,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
- public Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state)
+ public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state)
{
return ContinueWith<TResult>(continuationFunction, state, TaskScheduler.Current, default(CancellationToken),
TaskContinuationOptions.None);
@@ -3940,7 +3908,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- public Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state, CancellationToken cancellationToken)
+ public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, CancellationToken cancellationToken)
{
return ContinueWith<TResult>(continuationFunction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
@@ -3971,7 +3939,7 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
- public Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state, TaskScheduler scheduler)
+ public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, TaskScheduler scheduler)
{
return ContinueWith<TResult>(continuationFunction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None);
}
@@ -4008,7 +3976,7 @@ namespace System.Threading.Tasks
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
- public Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state, TaskContinuationOptions continuationOptions)
+ public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, TaskContinuationOptions continuationOptions)
{
return ContinueWith<TResult>(continuationFunction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions);
}
@@ -4055,14 +4023,14 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- public Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state, CancellationToken cancellationToken,
+ public Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, CancellationToken cancellationToken,
TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
return ContinueWith<TResult>(continuationFunction, state, scheduler, cancellationToken, continuationOptions);
}
// Same as the above overload, just with a stack mark parameter.
- private Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state, TaskScheduler scheduler,
+ private Task<TResult> ContinueWith<TResult>(Func<Task, object, TResult> continuationFunction, object state, TaskScheduler scheduler,
CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
{
// Throw on continuation with null function
@@ -4442,7 +4410,7 @@ namespace System.Threading.Tasks
public static bool WaitAll(Task[] tasks, TimeSpan timeout)
{
long totalMilliseconds = (long)timeout.TotalMilliseconds;
- if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
{
throw new ArgumentOutOfRangeException(nameof(timeout));
}
@@ -4825,7 +4793,7 @@ namespace System.Threading.Tasks
public static int WaitAny(Task[] tasks, TimeSpan timeout)
{
long totalMilliseconds = (long)timeout.TotalMilliseconds;
- if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
{
throw new ArgumentOutOfRangeException(nameof(timeout));
}
@@ -5267,7 +5235,7 @@ namespace System.Threading.Tasks
public static Task Delay(TimeSpan delay, CancellationToken cancellationToken)
{
long totalMilliseconds = (long)delay.TotalMilliseconds;
- if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
{
throw new ArgumentOutOfRangeException(nameof(delay), SR.Task_Delay_InvalidDelay);
}
diff --git a/src/System.Private.CoreLib/src/System/Threading/Tasks/TaskContinuation.cs b/src/System.Private.CoreLib/src/System/Threading/Tasks/TaskContinuation.cs
index 2ec382ad1..b268b097d 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Tasks/TaskContinuation.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Tasks/TaskContinuation.cs
@@ -36,7 +36,6 @@ namespace System.Threading.Tasks
Debug.Assert(action is Action<Task> || action is Action<Task, object>,
"Invalid delegate type in ContinuationTaskFromTask");
m_antecedent = antecedent;
- PossiblyCaptureContext();
}
/// <summary>
@@ -84,7 +83,6 @@ namespace System.Threading.Tasks
Debug.Assert(function is Func<Task, TResult> || function is Func<Task, object, TResult>,
"Invalid delegate type in ContinuationResultTaskFromTask");
m_antecedent = antecedent;
- PossiblyCaptureContext();
}
/// <summary>
@@ -132,7 +130,6 @@ namespace System.Threading.Tasks
Debug.Assert(action is Action<Task<TAntecedentResult>> || action is Action<Task<TAntecedentResult>, object>,
"Invalid delegate type in ContinuationTaskFromResultTask");
m_antecedent = antecedent;
- PossiblyCaptureContext();
}
/// <summary>
@@ -180,7 +177,6 @@ namespace System.Threading.Tasks
Debug.Assert(function is Func<Task<TAntecedentResult>, TResult> || function is Func<Task<TAntecedentResult>, object, TResult>,
"Invalid delegate type in ContinuationResultTaskFromResultTask");
m_antecedent = antecedent;
- PossiblyCaptureContext();
}
/// <summary>
diff --git a/src/System.Private.CoreLib/src/System/Threading/Tasks/TaskFactory.cs b/src/System.Private.CoreLib/src/System/Threading/Tasks/TaskFactory.cs
index 627a760c7..05c829cbb 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Tasks/TaskFactory.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Tasks/TaskFactory.cs
@@ -42,10 +42,10 @@ namespace System.Threading.Tasks
public class TaskFactory
{
// member variables
- private CancellationToken m_defaultCancellationToken;
- private TaskScheduler m_defaultScheduler;
- private TaskCreationOptions m_defaultCreationOptions;
- private TaskContinuationOptions m_defaultContinuationOptions;
+ private readonly CancellationToken m_defaultCancellationToken;
+ private readonly TaskScheduler m_defaultScheduler;
+ private readonly TaskCreationOptions m_defaultCreationOptions;
+ private readonly TaskContinuationOptions m_defaultContinuationOptions;
private TaskScheduler DefaultScheduler
@@ -88,7 +88,7 @@ namespace System.Threading.Tasks
/// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
/// </remarks>
public TaskFactory()
- : this(default(CancellationToken), TaskCreationOptions.None, TaskContinuationOptions.None, null)
+ : this(default, TaskCreationOptions.None, TaskContinuationOptions.None, null)
{
}
@@ -133,7 +133,7 @@ namespace System.Threading.Tasks
/// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
/// </remarks>
public TaskFactory(TaskScheduler scheduler) // null means to use TaskScheduler.Current
- : this(default(CancellationToken), TaskCreationOptions.None, TaskContinuationOptions.None, scheduler)
+ : this(default, TaskCreationOptions.None, TaskContinuationOptions.None, scheduler)
{
}
@@ -164,7 +164,7 @@ namespace System.Threading.Tasks
/// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
/// </remarks>
public TaskFactory(TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions)
- : this(default(CancellationToken), creationOptions, continuationOptions, null)
+ : this(default, creationOptions, continuationOptions, null)
{
}
@@ -416,7 +416,7 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- public Task StartNew(Action<Object> action, Object state)
+ public Task StartNew(Action<object> action, object state)
{
Task currTask = Task.InternalCurrent;
return Task.InternalStartNew(currTask, action, state, m_defaultCancellationToken, GetDefaultScheduler(currTask),
@@ -445,7 +445,7 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- public Task StartNew(Action<Object> action, Object state, CancellationToken cancellationToken)
+ public Task StartNew(Action<object> action, object state, CancellationToken cancellationToken)
{
Task currTask = Task.InternalCurrent;
return Task.InternalStartNew(currTask, action, state, cancellationToken, GetDefaultScheduler(currTask),
@@ -475,7 +475,7 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- public Task StartNew(Action<Object> action, Object state, TaskCreationOptions creationOptions)
+ public Task StartNew(Action<object> action, object state, TaskCreationOptions creationOptions)
{
Task currTask = Task.InternalCurrent;
return Task.InternalStartNew(currTask, action, state, m_defaultCancellationToken, GetDefaultScheduler(currTask),
@@ -516,7 +516,7 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- public Task StartNew(Action<Object> action, Object state, CancellationToken cancellationToken,
+ public Task StartNew(Action<object> action, object state, CancellationToken cancellationToken,
TaskCreationOptions creationOptions, TaskScheduler scheduler)
{
return Task.InternalStartNew(
@@ -677,7 +677,7 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- public Task<TResult> StartNew<TResult>(Func<Object, TResult> function, Object state)
+ public Task<TResult> StartNew<TResult>(Func<object, TResult> function, object state)
{
Task currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
@@ -710,7 +710,7 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- public Task<TResult> StartNew<TResult>(Func<Object, TResult> function, Object state, CancellationToken cancellationToken)
+ public Task<TResult> StartNew<TResult>(Func<object, TResult> function, object state, CancellationToken cancellationToken)
{
Task currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, state, cancellationToken,
@@ -744,7 +744,7 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- public Task<TResult> StartNew<TResult>(Func<Object, TResult> function, Object state, TaskCreationOptions creationOptions)
+ public Task<TResult> StartNew<TResult>(Func<object, TResult> function, object state, TaskCreationOptions creationOptions)
{
Task currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
@@ -789,7 +789,7 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- public Task<TResult> StartNew<TResult>(Func<Object, TResult> function, Object state, CancellationToken cancellationToken,
+ public Task<TResult> StartNew<TResult>(Func<object, TResult> function, object state, CancellationToken cancellationToken,
TaskCreationOptions creationOptions, TaskScheduler scheduler)
{
return Task<TResult>.StartNew(
@@ -1603,6 +1603,8 @@ namespace System.Threading.Tasks
Debug.Assert(_count >= 0, "Count should never go below 0");
}
+ public bool InvokeMayRunArbitraryCode { get { return true; } }
+
/// <summary>
/// Returns whether we should notify the debugger of a wait completion. This returns
/// true iff at least one constituent task has its bit set.
@@ -1616,8 +1618,6 @@ namespace System.Threading.Tasks
Task.AnyTaskRequiresNotifyDebuggerOfWaitCompletion(_tasks);
}
}
-
- public bool InvokeMayRunArbitraryCode { get { return true; } }
}
// Performs some logic common to all ContinueWhenAll() overloads
@@ -1675,6 +1675,8 @@ namespace System.Threading.Tasks
Debug.Assert(_count >= 0, "Count should never go below 0");
}
+ public bool InvokeMayRunArbitraryCode { get { return true; } }
+
/// <summary>
/// Returns whether we should notify the debugger of a wait completion. This returns
/// true iff at least one constituent task has its bit set.
@@ -1688,8 +1690,6 @@ namespace System.Threading.Tasks
Task.AnyTaskRequiresNotifyDebuggerOfWaitCompletion(_tasks);
}
}
-
- public bool InvokeMayRunArbitraryCode { get { return true; } }
}
diff --git a/src/System.Private.CoreLib/src/System/Threading/Tasks/TaskScheduler.cs b/src/System.Private.CoreLib/src/System/Threading/Tasks/TaskScheduler.cs
index 653345cef..026cfce6d 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Tasks/TaskScheduler.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Tasks/TaskScheduler.cs
@@ -148,11 +148,11 @@ namespace System.Threading.Tasks
/// Indicates the maximum concurrency level this
/// <see cref="TaskScheduler"/> is able to support.
/// </summary>
- public virtual Int32 MaximumConcurrencyLevel
+ public virtual int MaximumConcurrencyLevel
{
get
{
- return Int32.MaxValue;
+ return int.MaxValue;
}
}
@@ -366,7 +366,7 @@ namespace System.Threading.Tasks
/// <summary>
/// Gets the unique ID for this <see cref="TaskScheduler"/>.
/// </summary>
- public Int32 Id
+ public int Id
{
get
{
@@ -580,7 +580,7 @@ namespace System.Threading.Tasks
}
// returns the scheduler's Id
- public Int32 Id
+ public int Id
{
get { return m_taskScheduler.Id; }
}
@@ -623,7 +623,7 @@ namespace System.Threading.Tasks
}
/// <summary>
- /// Implemetation of <see cref="T:System.Threading.Tasks.TaskScheduler.QueueTask"/> for this scheduler class.
+ /// Implementation of <see cref="T:System.Threading.Tasks.TaskScheduler.QueueTask"/> for this scheduler class.
///
/// Simply posts the tasks to be executed on the associated <see cref="T:System.Threading.SynchronizationContext"/>.
/// </summary>
@@ -658,13 +658,13 @@ namespace System.Threading.Tasks
}
/// <summary>
- /// Implementes the <see cref="T:System.Threading.Tasks.TaskScheduler.MaximumConcurrencyLevel"/> property for
+ /// Implements the <see cref="T:System.Threading.Tasks.TaskScheduler.MaximumConcurrencyLevel"/> property for
/// this scheduler class.
///
/// By default it returns 1, because a <see cref="T:System.Threading.SynchronizationContext"/> based
/// scheduler only supports execution on a single thread.
/// </summary>
- public override Int32 MaximumConcurrencyLevel
+ public override int MaximumConcurrencyLevel
{
get
{
diff --git a/src/System.Private.CoreLib/src/System/Threading/ThreadPool.Portable.cs b/src/System.Private.CoreLib/src/System/Threading/ThreadPool.Portable.cs
index f7dff9475..2dbb6a2d2 100644
--- a/src/System.Private.CoreLib/src/System/Threading/ThreadPool.Portable.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/ThreadPool.Portable.cs
@@ -206,7 +206,8 @@ namespace System.Threading
{
if (handleValue != IntPtr.Zero && handleValue != (IntPtr)(-1))
{
- EventWaitHandle.Set(handleValue);
+ Debug.Assert(handleValue == handle.DangerousGetHandle());
+ WaitSubsystem.SetEvent(handleValue);
}
}
finally
diff --git a/src/System.Private.CoreLib/src/System/Threading/ThreadPool.Windows.cs b/src/System.Private.CoreLib/src/System/Threading/ThreadPool.Windows.cs
index 5ca0604b4..751fa683f 100644
--- a/src/System.Private.CoreLib/src/System/Threading/ThreadPool.Windows.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/ThreadPool.Windows.cs
@@ -186,7 +186,7 @@ namespace System.Threading
if ((safeWaitHandle != null) && !safeWaitHandle.IsInvalid)
{
- Interop.mincore.SetEvent(safeWaitHandle);
+ Interop.Kernel32.SetEvent(safeWaitHandle);
}
}
@@ -326,7 +326,7 @@ namespace System.Threading
private static RegisteredWaitHandle RegisterWaitForSingleObject(
WaitHandle waitObject,
WaitOrTimerCallback callBack,
- Object state,
+ object state,
uint millisecondsTimeOutInterval,
bool executeOnlyOnce,
bool flowExecutionContext)
diff --git a/src/System.Private.CoreLib/src/System/Threading/ThreadPool.cs b/src/System.Private.CoreLib/src/System/Threading/ThreadPool.cs
index c41b37753..9eaf1d4d5 100644
--- a/src/System.Private.CoreLib/src/System/Threading/ThreadPool.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/ThreadPool.cs
@@ -385,7 +385,7 @@ namespace System.Threading
}
}
- internal readonly LowLevelConcurrentQueue<IThreadPoolWorkItem> workItems = new LowLevelConcurrentQueue<IThreadPoolWorkItem>();
+ internal readonly ConcurrentQueue<IThreadPoolWorkItem> workItems = new ConcurrentQueue<IThreadPoolWorkItem>();
private volatile int numOutstandingThreadRequests = 0;
@@ -673,9 +673,9 @@ namespace System.Threading
}
}
- public delegate void WaitCallback(Object state);
+ public delegate void WaitCallback(object state);
- public delegate void WaitOrTimerCallback(Object state, bool timedOut); // signalled or timed out
+ public delegate void WaitOrTimerCallback(object state, bool timedOut); // signalled or timed out
//
// Interface to something that can be queued to the TP. This is implemented by
@@ -887,11 +887,11 @@ namespace System.Threading
{
private WaitOrTimerCallback _waitOrTimerCallback;
private ExecutionContext _executionContext;
- private Object _state;
+ private object _state;
private static readonly ContextCallback _ccbt = new ContextCallback(WaitOrTimerCallback_Context_t);
private static readonly ContextCallback _ccbf = new ContextCallback(WaitOrTimerCallback_Context_f);
- internal _ThreadPoolWaitOrTimerCallback(WaitOrTimerCallback waitOrTimerCallback, Object state, bool flowExecutionContext)
+ internal _ThreadPoolWaitOrTimerCallback(WaitOrTimerCallback waitOrTimerCallback, object state, bool flowExecutionContext)
{
_waitOrTimerCallback = waitOrTimerCallback;
_state = state;
@@ -903,13 +903,13 @@ namespace System.Threading
}
}
- private static void WaitOrTimerCallback_Context_t(Object state) =>
+ private static void WaitOrTimerCallback_Context_t(object state) =>
WaitOrTimerCallback_Context(state, timedOut: true);
- private static void WaitOrTimerCallback_Context_f(Object state) =>
+ private static void WaitOrTimerCallback_Context_f(object state) =>
WaitOrTimerCallback_Context(state, timedOut: false);
- private static void WaitOrTimerCallback_Context(Object state, bool timedOut)
+ private static void WaitOrTimerCallback_Context(object state, bool timedOut)
{
_ThreadPoolWaitOrTimerCallback helper = (_ThreadPoolWaitOrTimerCallback)state;
helper._waitOrTimerCallback(helper._state, timedOut);
@@ -938,7 +938,7 @@ namespace System.Threading
public static RegisteredWaitHandle RegisterWaitForSingleObject(
WaitHandle waitObject,
WaitOrTimerCallback callBack,
- Object state,
+ object state,
uint millisecondsTimeOutInterval,
bool executeOnlyOnce)
{
@@ -951,7 +951,7 @@ namespace System.Threading
public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(
WaitHandle waitObject,
WaitOrTimerCallback callBack,
- Object state,
+ object state,
uint millisecondsTimeOutInterval,
bool executeOnlyOnce)
{
@@ -963,71 +963,71 @@ namespace System.Threading
public static RegisteredWaitHandle RegisterWaitForSingleObject(
WaitHandle waitObject,
WaitOrTimerCallback callBack,
- Object state,
+ object state,
int millisecondsTimeOutInterval,
bool executeOnlyOnce)
{
if (millisecondsTimeOutInterval < -1)
throw new ArgumentOutOfRangeException(nameof(millisecondsTimeOutInterval), SR.ArgumentOutOfRange_NeedNonNegOrNegative1);
- return RegisterWaitForSingleObject(waitObject, callBack, state, (UInt32)millisecondsTimeOutInterval, executeOnlyOnce, true);
+ return RegisterWaitForSingleObject(waitObject, callBack, state, (uint)millisecondsTimeOutInterval, executeOnlyOnce, true);
}
public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(
WaitHandle waitObject,
WaitOrTimerCallback callBack,
- Object state,
+ object state,
int millisecondsTimeOutInterval,
bool executeOnlyOnce)
{
if (millisecondsTimeOutInterval < -1)
throw new ArgumentOutOfRangeException(nameof(millisecondsTimeOutInterval), SR.ArgumentOutOfRange_NeedNonNegOrNegative1);
- return RegisterWaitForSingleObject(waitObject, callBack, state, (UInt32)millisecondsTimeOutInterval, executeOnlyOnce, false);
+ return RegisterWaitForSingleObject(waitObject, callBack, state, (uint)millisecondsTimeOutInterval, executeOnlyOnce, false);
}
public static RegisteredWaitHandle RegisterWaitForSingleObject(
WaitHandle waitObject,
WaitOrTimerCallback callBack,
- Object state,
+ object state,
long millisecondsTimeOutInterval,
bool executeOnlyOnce)
{
if (millisecondsTimeOutInterval < -1 || millisecondsTimeOutInterval > int.MaxValue)
throw new ArgumentOutOfRangeException(nameof(millisecondsTimeOutInterval), SR.ArgumentOutOfRange_NeedNonNegOrNegative1);
- return RegisterWaitForSingleObject(waitObject, callBack, state, (UInt32)millisecondsTimeOutInterval, executeOnlyOnce, true);
+ return RegisterWaitForSingleObject(waitObject, callBack, state, (uint)millisecondsTimeOutInterval, executeOnlyOnce, true);
}
public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(
WaitHandle waitObject,
WaitOrTimerCallback callBack,
- Object state,
+ object state,
long millisecondsTimeOutInterval,
bool executeOnlyOnce)
{
if (millisecondsTimeOutInterval < -1 || millisecondsTimeOutInterval > int.MaxValue)
throw new ArgumentOutOfRangeException(nameof(millisecondsTimeOutInterval), SR.ArgumentOutOfRange_NeedNonNegOrNegative1);
- return RegisterWaitForSingleObject(waitObject, callBack, state, (UInt32)millisecondsTimeOutInterval, executeOnlyOnce, false);
+ return RegisterWaitForSingleObject(waitObject, callBack, state, (uint)millisecondsTimeOutInterval, executeOnlyOnce, false);
}
public static RegisteredWaitHandle RegisterWaitForSingleObject(
WaitHandle waitObject,
WaitOrTimerCallback callBack,
- Object state,
+ object state,
TimeSpan timeout,
bool executeOnlyOnce)
{
int tm = WaitHandle.ToTimeoutMilliseconds(timeout);
- return RegisterWaitForSingleObject(waitObject, callBack, state, (UInt32)tm, executeOnlyOnce, true);
+ return RegisterWaitForSingleObject(waitObject, callBack, state, (uint)tm, executeOnlyOnce, true);
}
public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(
WaitHandle waitObject,
WaitOrTimerCallback callBack,
- Object state,
+ object state,
TimeSpan timeout,
bool executeOnlyOnce)
{
int tm = WaitHandle.ToTimeoutMilliseconds(timeout);
- return RegisterWaitForSingleObject(waitObject, callBack, state, (UInt32)tm, executeOnlyOnce, false);
+ return RegisterWaitForSingleObject(waitObject, callBack, state, (uint)tm, executeOnlyOnce, false);
}
public static bool QueueUserWorkItem(WaitCallback callBack) =>
@@ -1069,7 +1069,7 @@ namespace System.Threading
return true;
}
- public static bool UnsafeQueueUserWorkItem(WaitCallback callBack, Object state)
+ public static bool UnsafeQueueUserWorkItem(WaitCallback callBack, object state)
{
if (callBack == null)
{
diff --git a/src/System.Private.CoreLib/src/System/Threading/ThreadStart.cs b/src/System.Private.CoreLib/src/System/Threading/ThreadStart.cs
deleted file mode 100644
index 5532539fc..000000000
--- a/src/System.Private.CoreLib/src/System/Threading/ThreadStart.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-/*=============================================================================
-**
-**
-**
-** Purpose: This class is a Delegate which defines the start method
-** for starting a thread. That method must match this delegate.
-**
-**
-=============================================================================*/
-
-namespace System.Threading
-{
- public delegate void ThreadStart();
-}
diff --git a/src/System.Private.CoreLib/src/System/Threading/Timer.Unix.cs b/src/System.Private.CoreLib/src/System/Threading/Timer.Unix.cs
index 403478d98..705f93e7a 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Timer.Unix.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Timer.Unix.cs
@@ -32,7 +32,7 @@ namespace System.Threading
// Note: AutoResetEvent.WaitOne takes an Int32 value as a timeout.
// The TimerQueue code ensures that timer duration is not greater than max Int32 value
- Debug.Assert(actualDuration <= (uint)Int32.MaxValue);
+ Debug.Assert(actualDuration <= (uint)int.MaxValue);
s_nextTimerDuration = (int)actualDuration;
// If this is the first time the timer is set then we need to create a thread that
diff --git a/src/System.Private.CoreLib/src/System/Threading/Timer.Windows.cs b/src/System.Private.CoreLib/src/System/Threading/Timer.Windows.cs
index 7020e1a2c..a3bea7088 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Timer.Windows.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Timer.Windows.cs
@@ -66,7 +66,7 @@ namespace System.Threading
{
private void SignalNoCallbacksRunning()
{
- Interop.mincore.SetEvent(_notifyWhenNoCallbacksRunning.SafeWaitHandle);
+ Interop.Kernel32.SetEvent(_notifyWhenNoCallbacksRunning.SafeWaitHandle);
}
}
}
diff --git a/src/System.Private.CoreLib/src/System/Threading/Timer.cs b/src/System.Private.CoreLib/src/System/Threading/Timer.cs
index fc284fd4e..9fd71a0b4 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Timer.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Timer.cs
@@ -6,7 +6,7 @@ using System.Diagnostics;
namespace System.Threading
{
- public delegate void TimerCallback(Object state);
+ public delegate void TimerCallback(object state);
//
// TimerQueue maintains a list of active timers in this AppDomain. We use a single native timer to schedule
@@ -51,7 +51,7 @@ namespace System.Threading
#region interface to native per-AppDomain timer
private int _currentNativeTimerStartTicks;
- private uint _currentNativeTimerDuration = UInt32.MaxValue;
+ private uint _currentNativeTimerDuration = uint.MaxValue;
private void EnsureAppDomainTimerFiresBy(uint requestedDuration)
{
@@ -66,7 +66,7 @@ namespace System.Threading
const uint maxPossibleDuration = 0x0fffffff;
uint actualDuration = Math.Min(requestedDuration, maxPossibleDuration);
- if (_currentNativeTimerDuration != UInt32.MaxValue)
+ if (_currentNativeTimerDuration != uint.MaxValue)
{
uint elapsed = (uint)(TickCount - _currentNativeTimerStartTicks);
if (elapsed >= _currentNativeTimerDuration)
@@ -109,7 +109,7 @@ namespace System.Threading
//
// since we got here, that means our previous timer has fired.
//
- _currentNativeTimerDuration = UInt32.MaxValue;
+ _currentNativeTimerDuration = uint.MaxValue;
bool haveTimerToSchedule = false;
uint nextAppDomainTimerDuration = uint.MaxValue;
@@ -298,7 +298,7 @@ namespace System.Threading
// Info about the user's callback
//
private readonly TimerCallback _timerCallback;
- private readonly Object _state;
+ private readonly object _state;
private readonly ExecutionContext _executionContext;
@@ -496,12 +496,12 @@ namespace System.Threading
public sealed class Timer : MarshalByRefObject, IDisposable
{
- private const UInt32 MAX_SUPPORTED_TIMEOUT = (uint)0xfffffffe;
+ private const uint MAX_SUPPORTED_TIMEOUT = (uint)0xfffffffe;
private TimerHolder _timer;
public Timer(TimerCallback callback,
- Object state,
+ object state,
int dueTime,
int period)
{
@@ -510,11 +510,11 @@ namespace System.Threading
if (period < -1)
throw new ArgumentOutOfRangeException(nameof(period), SR.ArgumentOutOfRange_NeedNonNegOrNegative1);
- TimerSetup(callback, state, (UInt32)dueTime, (UInt32)period);
+ TimerSetup(callback, state, (uint)dueTime, (uint)period);
}
public Timer(TimerCallback callback,
- Object state,
+ object state,
TimeSpan dueTime,
TimeSpan period)
{
@@ -530,20 +530,20 @@ namespace System.Threading
if (periodTm > MAX_SUPPORTED_TIMEOUT)
throw new ArgumentOutOfRangeException(nameof(periodTm), SR.ArgumentOutOfRange_PeriodTooLarge);
- TimerSetup(callback, state, (UInt32)dueTm, (UInt32)periodTm);
+ TimerSetup(callback, state, (uint)dueTm, (uint)periodTm);
}
[CLSCompliant(false)]
public Timer(TimerCallback callback,
- Object state,
- UInt32 dueTime,
- UInt32 period)
+ object state,
+ uint dueTime,
+ uint period)
{
TimerSetup(callback, state, dueTime, period);
}
public Timer(TimerCallback callback,
- Object state,
+ object state,
long dueTime,
long period)
{
@@ -555,7 +555,7 @@ namespace System.Threading
throw new ArgumentOutOfRangeException(nameof(dueTime), SR.ArgumentOutOfRange_TimeoutTooLarge);
if (period > MAX_SUPPORTED_TIMEOUT)
throw new ArgumentOutOfRangeException(nameof(period), SR.ArgumentOutOfRange_PeriodTooLarge);
- TimerSetup(callback, state, (UInt32)dueTime, (UInt32)period);
+ TimerSetup(callback, state, (uint)dueTime, (uint)period);
}
public Timer(TimerCallback callback)
@@ -565,13 +565,13 @@ namespace System.Threading
// for a timer to be fired before the returned value is assigned to the variable,
// potentially causing the callback to reference a bogus value (if passing the timer to the callback).
- TimerSetup(callback, this, (UInt32)dueTime, (UInt32)period);
+ TimerSetup(callback, this, (uint)dueTime, (uint)period);
}
private void TimerSetup(TimerCallback callback,
- Object state,
- UInt32 dueTime,
- UInt32 period)
+ object state,
+ uint dueTime,
+ uint period)
{
if (callback == null)
throw new ArgumentNullException(nameof(TimerCallback));
@@ -586,7 +586,7 @@ namespace System.Threading
if (period < -1)
throw new ArgumentOutOfRangeException(nameof(period), SR.ArgumentOutOfRange_NeedNonNegOrNegative1);
- return _timer.m_timer.Change((UInt32)dueTime, (UInt32)period);
+ return _timer.m_timer.Change((uint)dueTime, (uint)period);
}
public bool Change(TimeSpan dueTime, TimeSpan period)
@@ -595,7 +595,7 @@ namespace System.Threading
}
[CLSCompliant(false)]
- public bool Change(UInt32 dueTime, UInt32 period)
+ public bool Change(uint dueTime, uint period)
{
return _timer.m_timer.Change(dueTime, period);
}
@@ -611,7 +611,7 @@ namespace System.Threading
if (period > MAX_SUPPORTED_TIMEOUT)
throw new ArgumentOutOfRangeException(nameof(period), SR.ArgumentOutOfRange_PeriodTooLarge);
- return _timer.m_timer.Change((UInt32)dueTime, (UInt32)period);
+ return _timer.m_timer.Change((uint)dueTime, (uint)period);
}
public bool Dispose(WaitHandle notifyObject)
diff --git a/src/System.Private.CoreLib/src/System/Threading/Volatile.cs b/src/System.Private.CoreLib/src/System/Threading/Volatile.cs
index d9a009d73..00543f82d 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Volatile.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Volatile.cs
@@ -17,76 +17,76 @@ namespace System.Threading
public static unsafe class Volatile
{
#region Boolean
- private struct VolatileBoolean { public volatile Boolean Value; }
+ private struct VolatileBoolean { public volatile bool Value; }
- public static Boolean Read(ref Boolean location)
+ public static bool Read(ref bool location)
{
- return Unsafe.As<Boolean, VolatileBoolean>(ref location).Value;
+ return Unsafe.As<bool, VolatileBoolean>(ref location).Value;
}
- public static void Write(ref Boolean location, Boolean value)
+ public static void Write(ref bool location, bool value)
{
- Unsafe.As<Boolean, VolatileBoolean>(ref location).Value = value;
+ Unsafe.As<bool, VolatileBoolean>(ref location).Value = value;
}
#endregion
#region Byte
- private struct VolatileByte { public volatile Byte Value; }
+ private struct VolatileByte { public volatile byte Value; }
- public static Byte Read(ref Byte location)
+ public static byte Read(ref byte location)
{
- return Unsafe.As<Byte, VolatileByte>(ref location).Value;
+ return Unsafe.As<byte, VolatileByte>(ref location).Value;
}
- public static void Write(ref Byte location, Byte value)
+ public static void Write(ref byte location, byte value)
{
- Unsafe.As<Byte, VolatileByte>(ref location).Value = value;
+ Unsafe.As<byte, VolatileByte>(ref location).Value = value;
}
#endregion
#region Double
- public static Double Read(ref Double location)
+ public static double Read(ref double location)
{
- Int64 result = Read(ref Unsafe.As<Double, Int64>(ref location));
+ long result = Read(ref Unsafe.As<double, long>(ref location));
return *(double*)&result;
}
- public static void Write(ref Double location, Double value)
+ public static void Write(ref double location, double value)
{
- Write(ref Unsafe.As<Double, Int64>(ref location), *(Int64*)&value);
+ Write(ref Unsafe.As<double, long>(ref location), *(long*)&value);
}
#endregion
#region Int16
- private struct VolatileInt16 { public volatile Int16 Value; }
+ private struct VolatileInt16 { public volatile short Value; }
- public static Int16 Read(ref Int16 location)
+ public static short Read(ref short location)
{
- return Unsafe.As<Int16, VolatileInt16>(ref location).Value;
+ return Unsafe.As<short, VolatileInt16>(ref location).Value;
}
- public static void Write(ref Int16 location, Int16 value)
+ public static void Write(ref short location, short value)
{
- Unsafe.As<Int16, VolatileInt16>(ref location).Value = value;
+ Unsafe.As<short, VolatileInt16>(ref location).Value = value;
}
#endregion
#region Int32
- private struct VolatileInt32 { public volatile Int32 Value; }
+ private struct VolatileInt32 { public volatile int Value; }
- public static Int32 Read(ref Int32 location)
+ public static int Read(ref int location)
{
- return Unsafe.As<Int32, VolatileInt32>(ref location).Value;
+ return Unsafe.As<int, VolatileInt32>(ref location).Value;
}
- public static void Write(ref Int32 location, Int32 value)
+ public static void Write(ref int location, int value)
{
- Unsafe.As<Int32, VolatileInt32>(ref location).Value = value;
+ Unsafe.As<int, VolatileInt32>(ref location).Value = value;
}
#endregion
#region Int64
- public static Int64 Read(ref Int64 location)
+ public static long Read(ref long location)
{
#if BIT64
return (Int64)Unsafe.As<Int64, VolatileIntPtr>(ref location).Value;
@@ -95,7 +95,7 @@ namespace System.Threading
#endif
}
- public static void Write(ref Int64 location, Int64 value)
+ public static void Write(ref long location, long value)
{
#if BIT64
Unsafe.As<Int64, VolatileIntPtr>(ref location).Value = (IntPtr)value;
@@ -123,78 +123,78 @@ namespace System.Threading
#endregion
#region SByte
- private struct VolatileSByte { public volatile SByte Value; }
+ private struct VolatileSByte { public volatile sbyte Value; }
[CLSCompliant(false)]
- public static SByte Read(ref SByte location)
+ public static sbyte Read(ref sbyte location)
{
- return Unsafe.As<SByte, VolatileSByte>(ref location).Value;
+ return Unsafe.As<sbyte, VolatileSByte>(ref location).Value;
}
[CLSCompliant(false)]
- public static void Write(ref SByte location, SByte value)
+ public static void Write(ref sbyte location, sbyte value)
{
- Unsafe.As<SByte, VolatileSByte>(ref location).Value = value;
+ Unsafe.As<sbyte, VolatileSByte>(ref location).Value = value;
}
#endregion
#region Single
- private struct VolatileSingle { public volatile Single Value; }
+ private struct VolatileSingle { public volatile float Value; }
- public static Single Read(ref Single location)
+ public static float Read(ref float location)
{
- return Unsafe.As<Single, VolatileSingle>(ref location).Value;
+ return Unsafe.As<float, VolatileSingle>(ref location).Value;
}
- public static void Write(ref Single location, Single value)
+ public static void Write(ref float location, float value)
{
- Unsafe.As<Single, VolatileSingle>(ref location).Value = value;
+ Unsafe.As<float, VolatileSingle>(ref location).Value = value;
}
#endregion
#region UInt16
- private struct VolatileUInt16 { public volatile UInt16 Value; }
+ private struct VolatileUInt16 { public volatile ushort Value; }
[CLSCompliant(false)]
- public static UInt16 Read(ref UInt16 location)
+ public static ushort Read(ref ushort location)
{
- return Unsafe.As<UInt16, VolatileUInt16>(ref location).Value;
+ return Unsafe.As<ushort, VolatileUInt16>(ref location).Value;
}
[CLSCompliant(false)]
- public static void Write(ref UInt16 location, UInt16 value)
+ public static void Write(ref ushort location, ushort value)
{
- Unsafe.As<UInt16, VolatileUInt16>(ref location).Value = value;
+ Unsafe.As<ushort, VolatileUInt16>(ref location).Value = value;
}
#endregion
#region UInt32
- private struct VolatileUInt32 { public volatile UInt32 Value; }
+ private struct VolatileUInt32 { public volatile uint Value; }
[CLSCompliant(false)]
- public static UInt32 Read(ref UInt32 location)
+ public static uint Read(ref uint location)
{
- return Unsafe.As<UInt32, VolatileUInt32>(ref location).Value;
+ return Unsafe.As<uint, VolatileUInt32>(ref location).Value;
}
[CLSCompliant(false)]
- public static void Write(ref UInt32 location, UInt32 value)
+ public static void Write(ref uint location, uint value)
{
- Unsafe.As<UInt32, VolatileUInt32>(ref location).Value = value;
+ Unsafe.As<uint, VolatileUInt32>(ref location).Value = value;
}
#endregion
#region UInt64
[CLSCompliant(false)]
- public static UInt64 Read(ref UInt64 location)
+ public static ulong Read(ref ulong location)
{
- return (UInt64)Read(ref Unsafe.As<UInt64, Int64>(ref location));
+ return (ulong)Read(ref Unsafe.As<ulong, long>(ref location));
}
[CLSCompliant(false)]
- public static void Write(ref UInt64 location, UInt64 value)
+ public static void Write(ref ulong location, ulong value)
{
- Write(ref Unsafe.As<UInt64, Int64>(ref location), (Int64)value);
+ Write(ref Unsafe.As<ulong, long>(ref location), (long)value);
}
#endregion
@@ -215,7 +215,7 @@ namespace System.Threading
#endregion
#region T
- private struct VolatileObject { public volatile Object Value; }
+ private struct VolatileObject { public volatile object Value; }
public static T Read<T>(ref T location) where T : class
{
diff --git a/src/System.Private.CoreLib/src/System/Threading/WaitHandle.Windows.cs b/src/System.Private.CoreLib/src/System/Threading/WaitHandle.Windows.cs
index bda696cca..976836387 100644
--- a/src/System.Private.CoreLib/src/System/Threading/WaitHandle.Windows.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/WaitHandle.Windows.cs
@@ -260,7 +260,7 @@ namespace System.Threading
default:
var ex = new Exception();
- ex.SetErrorCode(errorCode);
+ ex.HResult = errorCode;
throw ex;
}
}
@@ -300,7 +300,7 @@ namespace System.Threading
default:
Exception ex = new Exception();
- ex.SetErrorCode(errorCode);
+ ex.HResult = errorCode;
throw ex;
}
}
diff --git a/src/System.Private.CoreLib/src/System/Threading/WaitHandle.cs b/src/System.Private.CoreLib/src/System/Threading/WaitHandle.cs
index ef7f47f5e..4d96a8830 100644
--- a/src/System.Private.CoreLib/src/System/Threading/WaitHandle.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/WaitHandle.cs
@@ -406,7 +406,7 @@ namespace System.Threading
internal static void ThrowInvalidHandleException()
{
var ex = new InvalidOperationException(SR.InvalidOperation_InvalidHandle);
- ex.SetErrorCode(HResults.E_HANDLE);
+ ex.HResult = HResults.E_HANDLE;
throw ex;
}
}
diff --git a/src/System.Private.CoreLib/src/System/Threading/Win32ThreadPoolNativeOverlapped.cs b/src/System.Private.CoreLib/src/System/Threading/Win32ThreadPoolNativeOverlapped.cs
index 3249e5037..a47c16d8f 100644
--- a/src/System.Private.CoreLib/src/System/Threading/Win32ThreadPoolNativeOverlapped.cs
+++ b/src/System.Private.CoreLib/src/System/Threading/Win32ThreadPoolNativeOverlapped.cs
@@ -199,6 +199,12 @@ namespace System.Threading
Debug.Assert(!data._completed);
data._completed = true;
+ if (data._executionContext == null)
+ {
+ data._callback(errorCode, bytesWritten, ToNativeOverlapped(overlapped));
+ return;
+ }
+
ContextCallback callback = s_executionContextCallback;
if (callback == null)
s_executionContextCallback = callback = OnExecutionContextCallback;
diff --git a/src/System.Private.CoreLib/src/System/ThrowHelper.cs b/src/System.Private.CoreLib/src/System/ThrowHelper.cs
index a3e3a0602..0aee323ef 100644
--- a/src/System.Private.CoreLib/src/System/ThrowHelper.cs
+++ b/src/System.Private.CoreLib/src/System/ThrowHelper.cs
@@ -203,6 +203,11 @@ namespace System
throw new InvalidOperationException(SR.InvalidOperation_NoValue);
}
+ internal static void ThrowInvalidOperationException_ConcurrentOperationsNotSupported()
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_ConcurrentOperationsNotSupported);
+ }
+
internal static void ThrowSerializationException(ExceptionResource resource)
{
throw new SerializationException(GetResourceString(resource));
@@ -321,6 +326,12 @@ namespace System
return "source";
case ExceptionArgument.state:
return "state";
+ case ExceptionArgument.length:
+ return "length";
+ case ExceptionArgument.comparisonType:
+ return "comparisonType";
+ case ExceptionArgument.manager:
+ return "manager";
default:
Debug.Fail("The enum value is not defined, please check the ExceptionArgument Enum.");
return "";
@@ -369,6 +380,10 @@ namespace System
return SR.TaskCompletionSourceT_TrySetException_NullException;
case ExceptionResource.TaskCompletionSourceT_TrySetException_NoExceptions:
return SR.TaskCompletionSourceT_TrySetException_NoExceptions;
+ case ExceptionResource.NotSupported_StringComparison:
+ return SR.NotSupported_StringComparison;
+ case ExceptionResource.ConcurrentCollection_SyncRoot_NotSupported:
+ return SR.ConcurrentCollection_SyncRoot_NotSupported;
default:
Debug.Assert(false,
"The enum value is not defined, please check the ExceptionResource Enum.");
@@ -414,7 +429,10 @@ namespace System
comparer,
comparable,
source,
- state
+ state,
+ length,
+ comparisonType,
+ manager
}
//
@@ -441,5 +459,7 @@ namespace System
TaskT_TransitionToFinal_AlreadyCompleted,
TaskCompletionSourceT_TrySetException_NullException,
TaskCompletionSourceT_TrySetException_NoExceptions,
+ NotSupported_StringComparison,
+ ConcurrentCollection_SyncRoot_NotSupported,
}
}
diff --git a/src/System.Private.CoreLib/src/System/TimeZoneInfo.WinRT.cs b/src/System.Private.CoreLib/src/System/TimeZoneInfo.WinRT.cs
index 4701b3e13..f0593b899 100644
--- a/src/System.Private.CoreLib/src/System/TimeZoneInfo.WinRT.cs
+++ b/src/System.Private.CoreLib/src/System/TimeZoneInfo.WinRT.cs
@@ -94,9 +94,9 @@ namespace System
return true;
}
- private TimeZoneInfo(TimeZoneInformation zone, Boolean dstDisabled)
+ private TimeZoneInfo(TimeZoneInformation zone, bool dstDisabled)
{
- if (String.IsNullOrEmpty(zone.StandardName))
+ if (string.IsNullOrEmpty(zone.StandardName))
{
_id = LocalId; // the ID must contain at least 1 character - initialize m_id to "Local"
}
@@ -134,9 +134,9 @@ namespace System
public unsafe TimeZoneInformation(TIME_DYNAMIC_ZONE_INFORMATION dtzi)
{
- StandardName = new String(dtzi.StandardName);
- DaylightName = new String(dtzi.DaylightName);
- TimeZoneKeyName = new String(dtzi.TimeZoneKeyName);
+ StandardName = new string(dtzi.StandardName);
+ DaylightName = new string(dtzi.DaylightName);
+ TimeZoneKeyName = new string(dtzi.TimeZoneKeyName);
Dtzi = dtzi;
}
}
@@ -150,7 +150,7 @@ namespace System
//
// assumes cachedData lock is taken
//
- private static TimeZoneInfoResult TryGetTimeZone(ref TimeZoneInformation timeZoneInformation, Boolean dstDisabled, out TimeZoneInfo value, out Exception e, CachedData cachedData)
+ private static TimeZoneInfoResult TryGetTimeZone(ref TimeZoneInformation timeZoneInformation, bool dstDisabled, out TimeZoneInfo value, out Exception e, CachedData cachedData)
{
TimeZoneInfoResult result = TimeZoneInfoResult.Success;
e = null;
@@ -822,10 +822,10 @@ namespace System
{
string s = new String(tdzi.StandardName);
- if (!String.IsNullOrEmpty(s) &&
+ if (!string.IsNullOrEmpty(s) &&
EqualStandardDates(timeZoneInformation, ref tdzi) &&
(notSupportedDaylightSaving || EqualDaylightDates(timeZoneInformation, ref tdzi)) &&
- String.Compare(s, timeZoneInformation.StandardName, StringComparison.Ordinal) == 0)
+ string.Compare(s, timeZoneInformation.StandardName, StringComparison.Ordinal) == 0)
{
// found a match
timeZoneInformation.TimeZoneKeyName = s;
@@ -861,10 +861,10 @@ namespace System
return CreateCustomTimeZone(LocalId, TimeSpan.Zero, LocalId, LocalId);
}
- Boolean dstDisabled = timeZoneInformation.Dtzi.DynamicDaylightTimeDisabled != 0;
+ bool dstDisabled = timeZoneInformation.Dtzi.DynamicDaylightTimeDisabled != 0;
//// check to see if we can use the key name returned from the API call
- if (!String.IsNullOrEmpty(timeZoneInformation.TimeZoneKeyName) || FindMatchToCurrentTimeZone(timeZoneInformation))
+ if (!string.IsNullOrEmpty(timeZoneInformation.TimeZoneKeyName) || FindMatchToCurrentTimeZone(timeZoneInformation))
{
TimeZoneInfo zone = null;
Exception ex;
diff --git a/src/System.Private.CoreLib/src/System/ValueType.cs b/src/System.Private.CoreLib/src/System/ValueType.cs
index 2c71bbcfe..7fad0ee31 100644
--- a/src/System.Private.CoreLib/src/System/ValueType.cs
+++ b/src/System.Private.CoreLib/src/System/ValueType.cs
@@ -26,7 +26,7 @@ namespace System
[System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public abstract class ValueType
{
- public override String ToString()
+ public override string ToString()
{
return this.GetType().ToString();
}
diff --git a/src/System.Private.CoreLib/src/System/WeakReference.cs b/src/System.Private.CoreLib/src/System/WeakReference.cs
index 4996e94ee..8ebe58b51 100644
--- a/src/System.Private.CoreLib/src/System/WeakReference.cs
+++ b/src/System.Private.CoreLib/src/System/WeakReference.cs
@@ -35,14 +35,14 @@ namespace System
// Creates a new WeakReference that keeps track of target.
// Assumes a Short Weak Reference (ie TrackResurrection is false.)
//
- public WeakReference(Object target)
+ public WeakReference(object target)
: this(target, false)
{
}
//Creates a new WeakReference that keeps track of target.
//
- public WeakReference(Object target, bool trackResurrection)
+ public WeakReference(object target, bool trackResurrection)
{
m_IsLongReference = trackResurrection;
m_handle = GCHandle.ToIntPtr(GCHandle.Alloc(target, trackResurrection ? GCHandleType.WeakTrackResurrection : GCHandleType.Weak));
@@ -58,7 +58,7 @@ namespace System
throw new ArgumentNullException(nameof(info));
}
- Object target = info.GetValue("TrackedObject", typeof(Object)); // Do not rename (binary serialization)
+ object target = info.GetValue("TrackedObject", typeof(object)); // Do not rename (binary serialization)
bool trackResurrection = info.GetBoolean("TrackResurrection"); // Do not rename (binary serialization)
m_IsLongReference = trackResurrection;
@@ -105,7 +105,7 @@ namespace System
//Gets the Object stored in the handle if it's accessible.
// Or sets it.
//
- public virtual Object Target
+ public virtual object Target
{
get
{
@@ -115,7 +115,7 @@ namespace System
if (default(IntPtr) == h)
return null;
- Object o = RuntimeImports.RhHandleGet(h);
+ object o = RuntimeImports.RhHandleGet(h);
if (o == null)
{
@@ -188,7 +188,7 @@ namespace System
/// and gets\create a new RCW in case it is alive.
/// </summary>
/// <returns></returns>
- private Object TryGetComTarget()
+ private object TryGetComTarget()
{
#if ENABLE_WINRT
WinRTInteropCallbacks callbacks = WinRTInterop.UnsafeCallbacks;
@@ -231,7 +231,7 @@ namespace System
throw new ArgumentNullException(nameof(info));
}
- info.AddValue("TrackedObject", Target, typeof(Object)); // Do not rename (binary serialization)
+ info.AddValue("TrackedObject", Target, typeof(object)); // Do not rename (binary serialization)
info.AddValue("TrackResurrection", m_IsLongReference); // Do not rename (binary serialization)
}
diff --git a/src/System.Private.CoreLib/src/System/WeakReferenceOfT.cs b/src/System.Private.CoreLib/src/System/WeakReferenceOfT.cs
index e36cda508..81040e3e4 100644
--- a/src/System.Private.CoreLib/src/System/WeakReferenceOfT.cs
+++ b/src/System.Private.CoreLib/src/System/WeakReferenceOfT.cs
@@ -134,7 +134,7 @@ namespace System
/// and gets\create a new RCW in case it is alive.
/// </summary>
/// <returns></returns>
- private Object TryGetComTarget()
+ private object TryGetComTarget()
{
#if ENABLE_WINRT
WinRTInteropCallbacks callbacks = WinRTInterop.UnsafeCallbacks;
diff --git a/src/System.Private.Interop/src/Interop/Interop.COM.Windows.cs b/src/System.Private.Interop/src/Interop/Interop.COM.Windows.cs
index df0b5d675..8aaa8930d 100644
--- a/src/System.Private.Interop/src/Interop/Interop.COM.Windows.cs
+++ b/src/System.Private.Interop/src/Interop/Interop.COM.Windows.cs
@@ -37,36 +37,6 @@ namespace System.Runtime.InteropServices
internal const string CORE_COM_AUT = "OleAut32.dll";
}
-#if CORECLR
- public static unsafe void SafeCoTaskMemFree(void* pv)
- {
- // Even though CoTaskMemFree is a no-op for NULLs, skipping the interop call entirely is faster
- if (pv != null)
- Marshal.FreeCoTaskMem(new IntPtr(pv));
- }
-
- public static unsafe IntPtr SysAllocStringLen(char* pStrIn, UInt32 dwSize)
- {
- string srcString = new string(pStrIn, 0, checked((int)dwSize));
- return Marshal.StringToBSTR(srcString);
- }
-
- public static unsafe void SysFreeString(void* pBSTR)
- {
- SysFreeString(new IntPtr(pBSTR));
- }
-
- public static unsafe void SysFreeString(IntPtr pBSTR)
- {
- Marshal.FreeBSTR(pBSTR);
- }
-
- internal static void VariantClear(IntPtr pObject)
- {
- //Nop
- }
-
-#else
[DllImport(Libraries.CORE_COM)]
[McgGeneratedNativeCallCodeAttribute]
internal static extern unsafe int CoCreateInstanceFromApp(
@@ -79,60 +49,26 @@ namespace System.Runtime.InteropServices
);
[DllImport(Libraries.CORE_COM, PreserveSig = false)]
- [SuppressUnmanagedCodeSecurity]
internal static extern void CreateBindCtx(UInt32 reserved, out IBindCtx ppbc);
[DllImport(Libraries.CORE_COM, PreserveSig = false)]
- [SuppressUnmanagedCodeSecurity]
internal static extern void MkParseDisplayName(IBindCtx pbc, [MarshalAs(UnmanagedType.LPWStr)] String szUserName, out UInt32 pchEaten, out IMoniker ppmk);
#if !TARGET_CORE_API_SET // BindMoniker not available in core API set
[DllImport(Libraries.CORE_COM, PreserveSig = false)]
- [SuppressUnmanagedCodeSecurity]
internal static extern void BindMoniker(IMoniker pmk, UInt32 grfOpt, ref Guid iidResult, [MarshalAs(UnmanagedType.Interface)] out Object ppvResult);
#endif
[DllImport(Libraries.CORE_COM_AUT)]
[McgGeneratedNativeCallCodeAttribute]
- [MethodImplAttribute(MethodImplOptions.NoInlining)]
- public static extern unsafe void SysFreeString(void* pBSTR);
-
- public static unsafe void SysFreeString(IntPtr pBstr)
- {
- SysFreeString((void*)pBstr);
- }
-
- [DllImport(Libraries.CORE_COM_AUT)]
- [McgGeneratedNativeCallCodeAttribute]
- [MethodImplAttribute(MethodImplOptions.NoInlining)]
- public static extern unsafe uint SysStringLen(void* pBSTR);
- public static unsafe uint SysStringLen(IntPtr pBSTR)
- {
- return SysStringLen((void*)pBSTR);
- }
-
- [DllImport(Libraries.CORE_COM_AUT)]
- [McgGeneratedNativeCallCodeAttribute]
- [MethodImplAttribute(MethodImplOptions.NoInlining)]
- public static extern unsafe IntPtr SysAllocString(IntPtr pStrIn);
-
- [DllImport(Libraries.CORE_COM_AUT)]
- [McgGeneratedNativeCallCodeAttribute]
- [MethodImplAttribute(MethodImplOptions.NoInlining)]
- public static extern unsafe char* SysAllocStringLen(char* pStrIn, uint len);
-
- [DllImport(Libraries.CORE_COM_AUT)]
- [McgGeneratedNativeCallCodeAttribute]
internal static extern void VariantClear(IntPtr pObject);
-
public static unsafe void SafeCoTaskMemFree(void* pv)
{
// Even though CoTaskMemFree is a no-op for NULLs, skipping the interop call entirely is faster
if (pv != null)
PInvokeMarshal.CoTaskMemFree(new IntPtr(pv));
}
-#endif //CORECLR
}
}
diff --git a/src/System.Private.Interop/src/Interop/Interop.Common.Windows.cs b/src/System.Private.Interop/src/Interop/Interop.Common.Windows.cs
index 46c5696e7..7d9c26bb9 100644
--- a/src/System.Private.Interop/src/Interop/Interop.Common.Windows.cs
+++ b/src/System.Private.Interop/src/Interop/Interop.Common.Windows.cs
@@ -32,13 +32,6 @@ namespace System.Runtime.InteropServices
internal const string CORE_DEBUG = "kernel32.dll";
#endif //TARGET_CORE_API_SET
}
-#if CORECLR
-
- internal static int GetLastWin32Error()
- {
- return 0;
- }
-#else
[DllImport(Libraries.CORE_DEBUG, EntryPoint = "OutputDebugStringW")]
[McgGeneratedNativeCallCodeAttribute]
@@ -51,6 +44,5 @@ namespace System.Runtime.InteropServices
OutputDebugString(pOutputString);
}
}
-#endif
}
}
diff --git a/src/System.Private.Interop/src/Interop/Interop.String.Windows.cs b/src/System.Private.Interop/src/Interop/Interop.String.Windows.cs
index 1b319926d..d8c5fcd34 100644
--- a/src/System.Private.Interop/src/Interop/Interop.String.Windows.cs
+++ b/src/System.Private.Interop/src/Interop/Interop.String.Windows.cs
@@ -37,23 +37,33 @@ namespace System.Runtime.InteropServices
#endif //TARGET_CORE_API_SET
}
-#if CORECLR
+ [DllImport(Libraries.CORE_COM_AUT)]
+ [McgGeneratedNativeCallCodeAttribute]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)]
+ public static extern unsafe void SysFreeString(void* pBSTR);
- public static unsafe uint SysStringLen(void* pBSTR)
+ public static unsafe void SysFreeString(IntPtr pBstr)
{
- throw new PlatformNotSupportedException("SysStringLen");
+ SysFreeString((void*)pBstr);
}
+ [DllImport(Libraries.CORE_COM_AUT)]
+ [McgGeneratedNativeCallCodeAttribute]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)]
+ public static extern unsafe uint SysStringLen(void* pBSTR);
public static unsafe uint SysStringLen(IntPtr pBSTR)
{
- throw new PlatformNotSupportedException("SysStringLen");
+ return SysStringLen((void*)pBSTR);
}
- // Do nothing
- internal static unsafe void OutputDebugString(string outputString)
- {
+ [DllImport(Libraries.CORE_COM_AUT)]
+ [McgGeneratedNativeCallCodeAttribute]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)]
+ public static extern unsafe IntPtr SysAllocString(IntPtr pStrIn);
- }
-#endif //CORECLR
+ [DllImport(Libraries.CORE_COM_AUT)]
+ [McgGeneratedNativeCallCodeAttribute]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)]
+ public static extern unsafe char* SysAllocStringLen(char* pStrIn, uint len);
}
}
diff --git a/src/System.Private.Interop/src/InteropExtensions/InteropExtensions.cs b/src/System.Private.Interop/src/InteropExtensions/InteropExtensions.cs
index 93c46d95b..1b6d888d8 100644
--- a/src/System.Private.Interop/src/InteropExtensions/InteropExtensions.cs
+++ b/src/System.Private.Interop/src/InteropExtensions/InteropExtensions.cs
@@ -374,7 +374,7 @@ namespace System.Runtime.InteropServices
{
throw new NotSupportedException("RuntimeHandleCompareExchangeVariableType");
}
-
+
public static void SetExceptionErrorCode(Exception exception, int hr)
{
throw new NotSupportedException("SetExceptionErrorCode");
diff --git a/src/System.Private.Interop/src/Shared/ComCallableObject.cs b/src/System.Private.Interop/src/Shared/ComCallableObject.cs
index 7bce62ca8..372621f9e 100644
--- a/src/System.Private.Interop/src/Shared/ComCallableObject.cs
+++ b/src/System.Private.Interop/src/Shared/ComCallableObject.cs
@@ -1722,6 +1722,10 @@ namespace System.Runtime.InteropServices
#endif
// IDispatch is not supported for UWP apps
new CCWWellKnownType() {guid = Interop.COM.IID_IDispatch, type = InternalTypes.IDispatch, ccwSupport = CCWSupport.NotSupport },
+#if ENABLE_WINRT
+ // ILanguageExceptionStackBackTrace is supported iff managed object is an Exception object
+ new CCWWellKnownType() {guid = Interop.COM.IID_ILanguageExceptionStackBackTrace, type = InternalTypes.ILanguageExceptionStackBackTrace, ccwSupport = CCWSupport.DependsOnCast, castToType = typeof(Exception).TypeHandle},
+#endif
};
private static bool IsWellKnownInterface(ref Guid guid, object targetObject,ref RuntimeTypeHandle interfaceType,out bool isCCWSupported)
diff --git a/src/System.Private.Interop/src/Shared/InternalModule.cs b/src/System.Private.Interop/src/Shared/InternalModule.cs
index 7fcf4a1d1..2a47be14c 100644
--- a/src/System.Private.Interop/src/Shared/InternalModule.cs
+++ b/src/System.Private.Interop/src/Shared/InternalModule.cs
@@ -30,6 +30,7 @@ namespace System.Runtime.InteropServices
internal static RuntimeTypeHandle IManagedActivationFactory = typeof(System.Runtime.InteropServices.WindowsRuntime.IManagedActivationFactory).TypeHandle;
internal static RuntimeTypeHandle IRestrictedErrorInfo = typeof(System.Runtime.InteropServices.ExceptionHelpers.__com_IRestrictedErrorInfo).TypeHandle;
internal static RuntimeTypeHandle HSTRING = typeof(System.Runtime.InteropServices.HSTRING).TypeHandle;
+ internal static RuntimeTypeHandle ILanguageExceptionStackBackTrace = typeof(System.Runtime.InteropServices.ExceptionHelpers.__com_ILanguageExceptionStackBackTrace).TypeHandle;
#endif
}
@@ -195,6 +196,15 @@ namespace System.Runtime.InteropServices
{
ItfType = InternalTypes.HSTRING
};
+
+ // ILanguageExceptionStackBackTrace
+ internal static McgInterfaceData s_ILanguageExceptionStackBackTrace = new McgInterfaceData
+ {
+ ItfType = InternalTypes.ILanguageExceptionStackBackTrace,
+ ItfGuid = Interop.COM.IID_ILanguageExceptionStackBackTrace,
+ Flags = McgInterfaceFlags.isInternal,
+ CcwVtable = System.Runtime.InteropServices.ExceptionHelpers.__vtable_ILanguageExceptionStackBackTrace.GetVtableFuncPtr(),
+ };
#endif
static readonly McgInterfaceData[] s_interfaceData = new McgInterfaceData[] {
@@ -220,7 +230,8 @@ namespace System.Runtime.InteropServices
s_IDispatch,
#if ENABLE_WINRT
- s_HSTRING
+ s_HSTRING,
+ s_ILanguageExceptionStackBackTrace
#endif
};
}
diff --git a/src/System.Private.Interop/src/Shared/Interop.Manual.cs b/src/System.Private.Interop/src/Shared/Interop.Manual.cs
index fe0861c0d..75c5868f4 100644
--- a/src/System.Private.Interop/src/Shared/Interop.Manual.cs
+++ b/src/System.Private.Interop/src/Shared/Interop.Manual.cs
@@ -58,6 +58,8 @@ partial class Interop
internal static Guid IID_IDispatch = new Guid(0x00020400, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
internal static Guid IID_IManagedActivationFactory = new Guid(0x60D27C8D, 0x5F61, 0x4CCE, 0xB7, 0x51, 0x69, 0x0F, 0xAE, 0x66, 0xAA, 0x53);
internal static Guid IID_IActivationFactoryInternal = new Guid(0x00000035, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
+ // CBE53FB5-F967-4258-8D34-42F5E25833DE
+ internal static Guid IID_ILanguageExceptionStackBackTrace = new Guid(unchecked((int)0xCBE53FB5), unchecked((short)0xF967), 0x4258, 0x8D, 0x34, 0x42, 0xF5, 0xE2, 0x58, 0x33,0xDE);
//
// Jupiter IIDs.
//
diff --git a/src/System.Private.Interop/src/Shared/McgHelpers.cs b/src/System.Private.Interop/src/Shared/McgHelpers.cs
index d6d8caac6..bb6ffd7c3 100644
--- a/src/System.Private.Interop/src/Shared/McgHelpers.cs
+++ b/src/System.Private.Interop/src/Shared/McgHelpers.cs
@@ -394,7 +394,7 @@ namespace System.Runtime.InteropServices
*((IntPtr*)pItem) = McgMarshal.ObjectToComInterface(item, interfaceType.GetElementInterfaceType());
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
if (hrExcep is ArgumentOutOfRangeException)
@@ -424,7 +424,7 @@ namespace System.Runtime.InteropServices
*((uint*)pSize) = (uint)CalliIntrinsics.Call<int>(thunk, list, Toolbox.IList_Oper.GetCount, 0, ref dummy);
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -452,7 +452,7 @@ namespace System.Runtime.InteropServices
*((IntPtr*)pView) = McgMarshal.ObjectToComInterface(view, interfaceType.GetVectorViewType());
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -492,7 +492,7 @@ namespace System.Runtime.InteropServices
*((int*)pIndex) = index;
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -525,7 +525,7 @@ namespace System.Runtime.InteropServices
CalliIntrinsics.Call<int>(thunk, list, Toolbox.IList_Oper.SetItem, (int)index, ref value);
}
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
if (hrExcep is ArgumentOutOfRangeException)
@@ -565,7 +565,7 @@ namespace System.Runtime.InteropServices
CalliIntrinsics.Call<int>(thunk, list, Toolbox.IList_Oper.Insert, (int)index, ref value);
}
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
if (hrExcep is ArgumentOutOfRangeException)
@@ -600,7 +600,7 @@ namespace System.Runtime.InteropServices
}
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
if (hrExcep is ArgumentOutOfRangeException)
@@ -631,7 +631,7 @@ namespace System.Runtime.InteropServices
CalliIntrinsics.Call<int>(thunk, list, Toolbox.IList_Oper.Add, 0, ref value);
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -667,7 +667,7 @@ namespace System.Runtime.InteropServices
CalliIntrinsics.Call<int>(thunk, list, Toolbox.IList_Oper.RemoveAt, (int)(listCount - 1), ref dummy);
}
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
if (hrExcep is ArgumentOutOfRangeException)
@@ -698,7 +698,7 @@ namespace System.Runtime.InteropServices
CalliIntrinsics.Call<int>(thunk, list, Toolbox.IList_Oper.Clear, 0, ref dummy);
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -754,7 +754,7 @@ namespace System.Runtime.InteropServices
*((uint*)pCount) = itemCount;
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -789,7 +789,7 @@ namespace System.Runtime.InteropServices
CalliIntrinsics.Call<int>(thunk, list, Toolbox.IList_Oper.Add, 0, ref value);
}
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -870,7 +870,7 @@ namespace System.Runtime.InteropServices
CalliIntrinsics.Call<object>(thunk, list, Toolbox.IList_Oper.GetItem, ref index, pItem);
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
if (hrExcep is ArgumentOutOfRangeException)
@@ -901,7 +901,7 @@ namespace System.Runtime.InteropServices
*((uint*)pSize) = (uint)size;
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -928,7 +928,7 @@ namespace System.Runtime.InteropServices
*((IntPtr*)pView) = McgMarshal.ObjectToComInterface(view, interfaceType.GetVectorViewType());
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -967,7 +967,7 @@ namespace System.Runtime.InteropServices
*((int*)pIndex) = index;
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -992,7 +992,7 @@ namespace System.Runtime.InteropServices
int index = (int)_index;
CalliIntrinsics.Call<object>(thunk, list, Toolbox.IList_Oper.SetItem, ref index, (IntPtr)(&_value));
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
if (hrExcep is ArgumentOutOfRangeException)
@@ -1023,7 +1023,7 @@ namespace System.Runtime.InteropServices
CalliIntrinsics.Call<object>(thunk, list, Toolbox.IList_Oper.Insert, ref index, (IntPtr)(&_value));
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
if (hrExcep is ArgumentOutOfRangeException)
@@ -1053,7 +1053,7 @@ namespace System.Runtime.InteropServices
CalliIntrinsics.Call<object>(thunk, list, Toolbox.IList_Oper.RemoveAt, ref index, default(IntPtr));
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
if (hrExcep is ArgumentOutOfRangeException)
@@ -1084,7 +1084,7 @@ namespace System.Runtime.InteropServices
CalliIntrinsics.Call<object>(thunk, list, Toolbox.IList_Oper.Add, ref dummy, (IntPtr)(&_value));
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -1122,7 +1122,7 @@ namespace System.Runtime.InteropServices
CalliIntrinsics.Call<object>(thunk, list, Toolbox.IList_Oper.RemoveAt, ref index, default(IntPtr));
}
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
if (hrExcep is ArgumentOutOfRangeException)
@@ -1152,7 +1152,7 @@ namespace System.Runtime.InteropServices
int dummy = 0;
CalliIntrinsics.Call<object>(thunk, list, Toolbox.IList_Oper.Clear, ref dummy, default(IntPtr));
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -1204,7 +1204,7 @@ namespace System.Runtime.InteropServices
*((uint*)pCount) = itemCount;
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -1239,7 +1239,7 @@ namespace System.Runtime.InteropServices
pItems = (IntPtr)((byte*)pItems + byteSize);
}
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -1389,7 +1389,7 @@ namespace System.Runtime.InteropServices
// Marshal to native iterator
*((IntPtr*)pResult) = McgMarshal.ObjectToComInterface(enumerator, interfaceType.GetIteratorType());
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -1468,7 +1468,7 @@ namespace System.Runtime.InteropServices
*((IntPtr*)pValue) = McgMarshal.ObjectToComInterface(item, interfaceType.GetElementInterfaceType());
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -1493,7 +1493,7 @@ namespace System.Runtime.InteropServices
object item = null;
*((byte*)pValue) = (byte)CalliIntrinsics.Call<int>(thunk, iterator, Toolbox.IIterator_Oper.get_HasCurrent, ref item, 0);
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -1518,7 +1518,7 @@ namespace System.Runtime.InteropServices
object item = null;
*((byte*)pValue) = (byte)CalliIntrinsics.Call<int>(thunk, iterator, Toolbox.IIterator_Oper.MoveNext, ref item, 0);
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -1553,7 +1553,7 @@ namespace System.Runtime.InteropServices
dst[i] = McgMarshal.ObjectToComInterface(src[i], interfaceType.GetElementInterfaceType());
}
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -1619,7 +1619,7 @@ namespace System.Runtime.InteropServices
int dummy = 0;
CalliIntrinsics.Call<Array>(thunk, iterator, Toolbox.IIterator_Oper.get_Current, pValue, ref dummy);
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -1646,7 +1646,7 @@ namespace System.Runtime.InteropServices
*((byte*)pValue) = (byte)has;
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -1673,7 +1673,7 @@ namespace System.Runtime.InteropServices
*((byte*)pValue) = (byte)has;
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -1702,7 +1702,7 @@ namespace System.Runtime.InteropServices
PInvokeMarshal.CopyToNative(data, 0, pDest, count);
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
@@ -1753,7 +1753,7 @@ namespace System.Runtime.InteropServices
// Call handler.Invoke(asyncInfo, asyncStatus)
CalliIntrinsics.Call<int>(thunk, handler, asyncInfo, asyncStatus);
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
hr = McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
diff --git a/src/System.Private.Interop/src/Shared/McgIntrinsics.cs b/src/System.Private.Interop/src/Shared/McgIntrinsics.cs
index 6c18ea147..ca48d577b 100644
--- a/src/System.Private.Interop/src/Shared/McgIntrinsics.cs
+++ b/src/System.Private.Interop/src/Shared/McgIntrinsics.cs
@@ -620,6 +620,8 @@ namespace System.Runtime.InteropServices
// ICommand
internal delegate int AddrOfICommandremove_CanExecuteChanged(IntPtr pComThis, System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken unsafe_token);
#endif
+ // ILanguageExceptionStackBackTrace
+ internal delegate int AddrOfILanguageExceptionStackBackTraceGetStackBackTrace(IntPtr pComThis, uint maxFramesToCapture, IntPtr stackBackTrace, IntPtr framesCaptured);
}
#if ENABLE_MIN_WINRT
diff --git a/src/System.Private.Interop/src/Shared/McgMarshal.cs b/src/System.Private.Interop/src/Shared/McgMarshal.cs
index d6ef590c2..40ddc4f9d 100644
--- a/src/System.Private.Interop/src/Shared/McgMarshal.cs
+++ b/src/System.Private.Interop/src/Shared/McgMarshal.cs
@@ -4,8 +4,12 @@
// ----------------------------------------------------------------------------------
// Interop library code
//
-// Marshalling helpers used by MCG
-//
+// Marshalling helpers used by MCG generated stub
+// McgMarshal covers full marshalling surface area and is entrypoint for all marshalling support.
+// In long term:
+// 1. MCG generated code should call McgMarshal to do marshalling
+// 2. Public Marhshal API should call McgMarshal to do marshalling
+
// NOTE:
// These source code are being published to InternalAPIs and consumed by RH builds
// Use PublishInteropAPI.bat to keep the InternalAPI copies in sync
@@ -143,7 +147,7 @@ namespace System.Runtime.InteropServices
}
#if ENABLE_MIN_WINRT
- public static unsafe void SetExceptionErrorCode(Exception exception, int errorCode)
+ public static unsafe void SetExceptionErrorCode(Exception exception, int errorCode)
{
InteropExtensions.SetExceptionErrorCode(exception, errorCode);
}
@@ -364,6 +368,149 @@ namespace System.Runtime.InteropServices
{
return PInvokeMarshal.ByValAnsiStringToString(pchBuffer, charCount);
}
+
+ /// <summary>
+ /// CoTaskMemAlloc + ZeroMemory
+ /// @TODO - we can probably optimize the zero memory part later
+ /// </summary>
+ public unsafe static void* CoTaskMemAllocAndZeroMemory(IntPtr size)
+ {
+ void *ptr = (void*)PInvokeMarshal.CoTaskMemAlloc(new UIntPtr((void*)size));
+ if (ptr == null)
+ return ptr;
+
+ byte *pByte = (byte*)ptr;
+ long lSize = size.ToInt64();
+ while (lSize > 0)
+ {
+ lSize--;
+ (*pByte++) = 0;
+ }
+
+ return ptr;
+ }
+
+ /// <summary>
+ /// Free allocated memory. The allocated memory should be allocated by CoTaskMemAlloc
+ /// </summary>
+ public static void SafeCoTaskMemFree(IntPtr allocatedMemory)
+ {
+ if (allocatedMemory != IntPtr.Zero)
+ PInvokeMarshal.CoTaskMemFree(allocatedMemory);
+ }
+
+ /// <summary>
+ /// Free allocated memory. The allocated memory should be allocated by CoTaskMemAlloc
+ /// </summary>
+ public static unsafe void SafeCoTaskMemFree(void* pv)
+ {
+ if (pv != null)
+ PInvokeMarshal.CoTaskMemFree(new IntPtr(pv));
+ }
+
+ /// <summary>
+ /// Allocate a buffer with enough size to store the unicode characters saved in source
+ /// Buffer is allocated with CoTaskMemAlloc
+ /// </summary>
+ public unsafe static void *AllocUnicodeBuffer(string source)
+ {
+ if (source == null)
+ return null;
+
+ int byteLen = checked((source.Length + 1) * 2);
+
+ char* pBuf = (char*)PInvokeMarshal.CoTaskMemAlloc(new UIntPtr((uint)byteLen));
+ if (pBuf == null)
+ throw new System.OutOfMemoryException();
+
+ return pBuf;
+ }
+
+ /// <summary>
+ /// Copy unicode characters in source into dest, and terminating with null
+ /// </summary>
+ public unsafe static void CopyUnicodeString(string source, void* _dest)
+ {
+ if (source == null)
+ return;
+
+ char* dest = (char *)_dest;
+ fixed (char* pSource = source)
+ {
+ int len = source.Length;
+ char* src = pSource;
+
+ // Copy characters one by one, including the null terminator
+ for (int i = 0; i <= len; ++i)
+ {
+ *(dest++) = *(src++);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Convert String to BSTR
+ /// </summary>
+ public unsafe static ushort* ConvertStringToBSTR(
+ ushort* ptrToFirstCharInBSTR,
+ string strManaged)
+ {
+ if (strManaged == null)
+ return null;
+
+ if (ptrToFirstCharInBSTR == null)
+ {
+ // If caller don't provided buffer, allocate the buffer and create string using SysAllocStringLen
+ fixed (char* ch = strManaged)
+ {
+ return (ushort*) ExternalInterop.SysAllocStringLen(ch, (uint)strManaged.Length);
+ }
+ }
+ else
+ {
+ // If caller provided a buffer, construct the BSTR manually.
+
+ // set length
+ *((int*)ptrToFirstCharInBSTR - 1) = checked(strManaged.Length * 2);
+
+ // copy characters from the managed string
+ fixed (char* ch = strManaged)
+ {
+ InteropExtensions.Memcpy(
+ (System.IntPtr)ptrToFirstCharInBSTR,
+ (System.IntPtr)ch,
+ (strManaged.Length + 1) * 2);
+ }
+
+ return ptrToFirstCharInBSTR;
+ }
+ }
+
+ /// <summary>
+ /// Convert BSTR to String
+ /// </summary>
+ public unsafe static string ConvertBSTRToString(ushort* bstr)
+ {
+ if (bstr == null)
+ return null;
+ return new string((char*)bstr, 0, (int)ExternalInterop.SysStringLen(bstr));
+ }
+
+ /// <summary>
+ /// Free Allocated BSTR
+ /// </summary>
+ public static unsafe void SysFreeString(void* pBSTR)
+ {
+ SysFreeString(new IntPtr(pBSTR));
+ }
+
+ /// <summary>
+ /// Free Allocated BSTR
+ /// </summary>
+ public unsafe static void SysFreeString(IntPtr pBSTR)
+ {
+ ExternalInterop.SysFreeString(pBSTR);
+ }
#endif
#if ENABLE_MIN_WINRT
@@ -975,7 +1122,7 @@ namespace System.Runtime.InteropServices
#endregion
/// <summary>
- /// This method returns HR for the exception being thrown.
+ /// This method propagate the exception being thrown.
/// 1. On Windows8+, WinRT scenarios we do the following.
/// a. Check whether the exception has any IRestrictedErrorInfo associated with it.
/// If so, it means that this exception was actually caused by a native exception in which case we do simply use the same
@@ -983,6 +1130,27 @@ namespace System.Runtime.InteropServices
/// b. If not, this is actually a managed exception and in this case we RoOriginateLanguageException with the msg, hresult and the IErrorInfo
/// associated with the managed exception. This helps us to retrieve the same exception in case it comes back to native.
/// 2. On win8 and for classic COM scenarios.
+ /// a. This method should not be called
+ /// </summary>
+ /// <param name="ex"></param>
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public static bool PropagateException(Exception ex)
+ {
+#if ENABLE_WINRT
+ return ExceptionHelpers.PropagateException(ex);
+#else
+ // TODO : ExceptionHelpers should be platform specific , move it to
+ // seperate source files
+ return true;
+#endif
+ }
+
+ /// <summary>
+ /// This method returns HR for the exception being thrown.
+ /// 1. On Windows8+, WinRT scenarios
+ /// The work to propagate the exception should have already performed in the exception filter
+ /// by calling PropagateException()
+ /// 2. On win8 and for classic COM scenarios.
/// a. We create IErrorInfo for the given Exception object and SetErrorInfo with the given IErrorInfo.
/// </summary>
/// <param name="ex"></param>
diff --git a/src/System.Private.Interop/src/Shared/StandardInterfaces.cs b/src/System.Private.Interop/src/Shared/StandardInterfaces.cs
index 24c04ecce..d21279cc6 100644
--- a/src/System.Private.Interop/src/Shared/StandardInterfaces.cs
+++ b/src/System.Private.Interop/src/Shared/StandardInterfaces.cs
@@ -742,7 +742,7 @@ namespace System.Runtime.InteropServices
else
*unsafe_stringRepresentation = McgMarshal.StringToHString(stringRepresentation);
}
- catch (Exception ex)
+ catch (Exception ex) when (McgMarshal.PropagateException(ex))
{
return McgMarshal.GetHRForExceptionWinRT(ex);
}
@@ -1214,7 +1214,7 @@ namespace System.Runtime.InteropServices
return hr;
}
- catch (Exception ex)
+ catch (Exception ex) when (McgMarshal.PropagateException(ex))
{
return McgMarshal.GetHRForExceptionWinRT(ex);
}
@@ -1443,7 +1443,7 @@ namespace System.Runtime.InteropServices
*pResult = (IntPtr)((IActivationFactoryInternal)target).ActivateInstance();
return Interop.COM.S_OK;
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
*pResult = default(IntPtr);
return McgMarshal.GetHRForExceptionWinRT(hrExcep);
@@ -1513,7 +1513,7 @@ namespace System.Runtime.InteropServices
((IManagedActivationFactory)ComCallableObject.GetTarget(pComThis)).RunClassConstructor();
return Interop.COM.S_OK;
}
- catch (System.Exception hrExcep)
+ catch (System.Exception hrExcep) when (McgMarshal.PropagateException(hrExcep))
{
return McgMarshal.GetHRForExceptionWinRT(hrExcep);
}
diff --git a/src/System.Private.Interop/src/Shared/StringPool.cs b/src/System.Private.Interop/src/Shared/StringPool.cs
index d78fdedd7..eea2db4a6 100644
--- a/src/System.Private.Interop/src/Shared/StringPool.cs
+++ b/src/System.Private.Interop/src/Shared/StringPool.cs
@@ -19,7 +19,7 @@ namespace System.Runtime.InteropServices
/// Functions:
/// 1. GetString converts compressed string represented by an index to original System.String
/// 2. StableStringHash computes hash code without decoding to System.String
- /// 3. IsStringEqual compares compressed string represented by anindex with System.String
+ /// 3. IsStringEqual compares compressed string represented by an index with System.String
///
/// TODO:
/// 1. More string reuse
diff --git a/src/System.Private.Interop/src/Shared/__ComObject.cs b/src/System.Private.Interop/src/Shared/__ComObject.cs
index b68a81e0b..0efd00ae2 100644
--- a/src/System.Private.Interop/src/Shared/__ComObject.cs
+++ b/src/System.Private.Interop/src/Shared/__ComObject.cs
@@ -1174,7 +1174,7 @@ namespace System
/// <summary>
/// Slow path of QueryInterface that does not look at any cache.
- /// NOTE: MethodImpl(NoInlining) is necessary becauase Bartok is trying to be "helpful" by inlining
+ /// NOTE: MethodImpl(NoInlining) is necessary because Bartok is trying to be "helpful" by inlining
/// these calls while in other cases it does not inline when it should.
/// </summary>
[MethodImpl(MethodImplOptions.NoInlining)]
diff --git a/src/System.Private.Interop/src/System.Private.Interop.Experimental.csproj b/src/System.Private.Interop/src/System.Private.Interop.Experimental.csproj
new file mode 100644
index 000000000..3fcaee81c
--- /dev/null
+++ b/src/System.Private.Interop/src/System.Private.Interop.Experimental.csproj
@@ -0,0 +1,9 @@
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+ <PropertyGroup>
+ <AssemblyName>System.Private.Interop.Experimental</AssemblyName>
+ <EcmaMetadataSupport>true</EcmaMetadataSupport>
+ <DynamicCodeSupport>true</DynamicCodeSupport>
+ </PropertyGroup>
+
+ <Import Project="System.Private.Interop.csproj" />
+</Project>
diff --git a/src/System.Private.Interop/src/System.Private.Interop.csproj b/src/System.Private.Interop/src/System.Private.Interop.csproj
index 73411b210..f3561abda 100644
--- a/src/System.Private.Interop/src/System.Private.Interop.csproj
+++ b/src/System.Private.Interop/src/System.Private.Interop.csproj
@@ -1,7 +1,7 @@
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <AssemblyName>System.Private.Interop</AssemblyName>
+ <AssemblyName Condition="'$(AssemblyName)' == ''">System.Private.Interop</AssemblyName>
<OutputType>Library</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants>$(DefineConstants);TARGET_CORE_API_SET</DefineConstants>
@@ -21,7 +21,8 @@
<SkipGetTargetFrameworkProperties>true</SkipGetTargetFrameworkProperties>
</ProjectReference>
<ProjectReference Include="..\..\System.Private.CoreLib\src\System.Private.CoreLib.csproj" />
- <ProjectReference Include="..\..\System.Private.TypeLoader\src\System.Private.TypeLoader.csproj" />
+ <ProjectReference Condition="'$(DynamicCodeSupport)' != 'true'" Include="..\..\System.Private.TypeLoader\src\System.Private.TypeLoader.csproj" />
+ <ProjectReference Condition="'$(DynamicCodeSupport)' == 'true'" Include="..\..\System.Private.TypeLoader\src\System.Private.TypeLoader.Experimental.csproj" />
</ItemGroup>
<Import Project="System.Private.Interop.Shared.projitems" />
diff --git a/src/System.Private.Interop/src/System/Runtime/InteropServices/Marshal.cs b/src/System.Private.Interop/src/System/Runtime/InteropServices/Marshal.cs
index d565e199f..31365c9c7 100644
--- a/src/System.Private.Interop/src/System/Runtime/InteropServices/Marshal.cs
+++ b/src/System.Private.Interop/src/System/Runtime/InteropServices/Marshal.cs
@@ -111,6 +111,44 @@ namespace System.Runtime.InteropServices
return PtrToStringUni(ptr);
}
+ public static unsafe String PtrToStringUTF8(IntPtr ptr)
+ {
+ if (IntPtr.Zero == ptr)
+ {
+ return null;
+ }
+ else
+ {
+ int nbBytes = lstrlenA(ptr);
+ return PtrToStringUTF8(ptr, nbBytes);
+ }
+ }
+
+ public static unsafe String PtrToStringUTF8(IntPtr ptr, int byteLen)
+ {
+ if (byteLen < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(byteLen), SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ else if (IntPtr.Zero == ptr)
+ {
+ return null;
+ }
+ else if (IsWin32Atom(ptr))
+ {
+ return null;
+ }
+ else if (byteLen == 0)
+ {
+ return string.Empty;
+ }
+ else
+ {
+ byte* pByte = (byte*)ptr.ToPointer();
+ return Encoding.UTF8.GetString(pByte, byteLen);
+ }
+ }
+
//====================================================================
// SizeOf()
//====================================================================
@@ -125,16 +163,16 @@ namespace System.Runtime.InteropServices
public static int SizeOf<T>(T structure)
{
- return SizeOf<T>();
+ return SizeOf((object)structure);
}
- public static int SizeOf(Object structure)
+ public static int SizeOf(object structure)
{
if (structure == null)
throw new ArgumentNullException(nameof(structure));
// we never had a check for generics here
- return SizeOfHelper(structure.GetType(), true);
+ return SizeOfHelper(structure.GetType());
}
public static int SizeOf(Type t)
@@ -144,27 +182,27 @@ namespace System.Runtime.InteropServices
if (t.TypeHandle.IsGenericType() || t.TypeHandle.IsGenericTypeDefinition())
throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(t));
- return SizeOfHelper(t, true);
+ return SizeOfHelper(t);
}
- private static int SizeOfHelper(Type t, bool throwIfNotMarshalable)
+ private static int SizeOfHelper(Type t)
{
RuntimeTypeHandle typeHandle = t.TypeHandle;
- int size;
- if (RuntimeInteropData.Instance.TryGetStructUnsafeStructSize(typeHandle, out size))
+ if (RuntimeInteropData.Instance.TryGetStructUnsafeStructSize(typeHandle, out int size))
{
return size;
}
- if (!typeHandle.IsBlittable() && !typeHandle.IsValueType())
- {
- throw new MissingInteropDataException(SR.StructMarshalling_MissingInteropData, t);
- }
- else
+ // IsBlittable() checks whether the type contains GC references. It is approximate check with false positives.
+ // This fallback path will return incorrect answer for types that do not contain GC references, but that are
+ // not actually blittable; e.g. for types with bool fields.
+ if (typeHandle.IsBlittable() && typeHandle.IsValueType())
{
return typeHandle.GetValueTypeSize();
}
+
+ throw new MissingInteropDataException(SR.StructMarshalling_MissingInteropData, t);
}
//====================================================================
@@ -181,15 +219,7 @@ namespace System.Runtime.InteropServices
if (t.TypeHandle.IsGenericType() || t.TypeHandle.IsGenericTypeDefinition())
throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(t));
-
- return OffsetOfHelper(t, fieldName);
- }
-
- private static IntPtr OffsetOfHelper(Type t, String fieldName)
- {
- bool structExists;
- uint offset;
- if (RuntimeInteropData.Instance.TryGetStructFieldOffset(t.TypeHandle, fieldName, out structExists, out offset))
+ if (RuntimeInteropData.Instance.TryGetStructFieldOffset(t.TypeHandle, fieldName, out bool structExists, out uint offset))
{
return new IntPtr(offset);
}
@@ -199,10 +229,8 @@ namespace System.Runtime.InteropServices
{
throw new ArgumentException(SR.Format(SR.Argument_OffsetOfFieldNotFound, t.TypeHandle.GetDisplayName()), nameof(fieldName));
}
- else
- {
- throw new MissingInteropDataException(SR.StructMarshalling_MissingInteropData, t);
- }
+
+ throw new MissingInteropDataException(SR.StructMarshalling_MissingInteropData, t);
}
public static IntPtr OffsetOf<T>(String fieldName)
@@ -813,6 +841,35 @@ namespace System.Runtime.InteropServices
}
}
+ public static unsafe IntPtr StringToCoTaskMemUTF8(String s)
+ {
+ if (s == null)
+ {
+ return IntPtr.Zero;
+ }
+ else
+ {
+ int nb = Encoding.UTF8.GetMaxByteCount(s.Length);
+
+ IntPtr pMem = PInvokeMarshal.CoTaskMemAlloc(new UIntPtr((uint)nb + 1));
+
+ if (pMem == IntPtr.Zero)
+ {
+ throw new OutOfMemoryException();
+ }
+ else
+ {
+ fixed (char* firstChar = s)
+ {
+ byte* pbMem = (byte*)pMem;
+ int nbWritten = Encoding.UTF8.GetBytes(firstChar, s.Length, pbMem, nb);
+ pbMem[nbWritten] = 0;
+ }
+ return pMem;
+ }
+ }
+ }
+
public static unsafe IntPtr StringToCoTaskMemAnsi(String s)
{
if (s == null)
@@ -945,7 +1002,7 @@ namespace System.Runtime.InteropServices
{
if (IsNotWin32Atom(ptr))
{
- ExternalInterop.SysFreeString(ptr);
+ McgMarshal.SysFreeString(ptr);
}
}
@@ -991,6 +1048,12 @@ namespace System.Runtime.InteropServices
FreeCoTaskMem(s);
}
+ public static unsafe void ZeroFreeCoTaskMemUTF8(IntPtr s)
+ {
+ SecureZeroMemory(s, lstrlenA(s));
+ FreeCoTaskMem(s);
+ }
+
public static void ZeroFreeGlobalAllocAnsi(IntPtr s)
{
SecureZeroMemory(s, lstrlenA(s));
@@ -1029,8 +1092,27 @@ namespace System.Runtime.InteropServices
// Boxed struct start at offset 1 (EEType* at offset 0) while class start at offset 0
int offset = structureTypeHandle.IsValueType() ? 1 : 0;
+ bool useMemCpy = false;
+
+ if (RuntimeInteropData.Instance.TryGetStructUnmarshalStub(structureTypeHandle, out IntPtr unmarshalStub))
+ {
+ if (unmarshalStub != IntPtr.Zero)
+ {
+ InteropExtensions.PinObjectAndCall(structure,
+ unboxedStructPtr =>
+ {
+ CalliIntrinsics.Call<int>(
+ unmarshalStub,
+ (void*)ptr, // unsafe (no need to adjust as it is always struct)
+ ((void*)((IntPtr*)unboxedStructPtr + offset)) // safe (need to adjust offset as it could be class)
+ );
+ });
+ return;
+ }
+ useMemCpy = true;
+ }
- if (structureTypeHandle.IsBlittable() && structureTypeHandle.IsValueType())
+ if (useMemCpy || structureTypeHandle.IsBlittable())
{
int structSize = Marshal.SizeOf(structure);
InteropExtensions.PinObjectAndCall(structure,
@@ -1045,21 +1127,6 @@ namespace System.Runtime.InteropServices
return;
}
- IntPtr unmarshalStub;
- if (RuntimeInteropData.Instance.TryGetStructUnmarshalStub(structureTypeHandle, out unmarshalStub))
- {
- InteropExtensions.PinObjectAndCall(structure,
- unboxedStructPtr =>
- {
- CalliIntrinsics.Call<int>(
- unmarshalStub,
- (void*)ptr, // unsafe (no need to adjust as it is always struct)
- ((void*)((IntPtr*)unboxedStructPtr + offset)) // safe (need to adjust offset as it could be class)
- );
- });
- return;
- }
-
throw new MissingInteropDataException(SR.StructMarshalling_MissingInteropData, structure.GetType());
}
@@ -1067,12 +1134,8 @@ namespace System.Runtime.InteropServices
// Creates a new instance of "structuretype" and marshals data from a
// native memory block to it.
//====================================================================
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
public static Object PtrToStructure(IntPtr ptr, Type structureType)
{
- // Boxing the struct here is important to ensure that the original copy is written to,
- // not the autoboxed copy
-
if (ptr == IntPtr.Zero)
throw new ArgumentNullException(nameof(ptr));
@@ -1138,10 +1201,9 @@ namespace System.Runtime.InteropServices
// Boxed struct start at offset 1 (EEType* at offset 0) while class start at offset 0
int offset = structureTypeHandle.IsValueType() ? 1 : 0;
+ bool useMemCpy = false;
- bool isBlittable = false; // whether Mcg treat this struct as blittable struct
- IntPtr marshalStub;
- if (RuntimeInteropData.Instance.TryGetStructMarshalStub(structureTypeHandle, out marshalStub))
+ if (RuntimeInteropData.Instance.TryGetStructMarshalStub(structureTypeHandle, out IntPtr marshalStub))
{
if (marshalStub != IntPtr.Zero)
{
@@ -1156,13 +1218,10 @@ namespace System.Runtime.InteropServices
});
return;
}
- else
- {
- isBlittable = true;
- }
+ useMemCpy = true;
}
- if (isBlittable || structureTypeHandle.IsBlittable()) // blittable
+ if (useMemCpy || structureTypeHandle.IsBlittable())
{
int structSize = Marshal.SizeOf(structure);
InteropExtensions.PinObjectAndCall(structure,
@@ -1189,7 +1248,7 @@ namespace System.Runtime.InteropServices
// DestroyStructure()
//
//====================================================================
- public static void DestroyStructure(IntPtr ptr, Type structuretype)
+ public static unsafe void DestroyStructure(IntPtr ptr, Type structuretype)
{
if (ptr == IntPtr.Zero)
throw new ArgumentNullException(nameof(ptr));
@@ -1209,14 +1268,6 @@ namespace System.Runtime.InteropServices
throw new ArgumentException(SR.Argument_MustHaveLayoutOrBeBlittable, structureTypeHandle.GetDisplayName());
}
-
- DestroyStructureHelper(ptr, structuretype);
- }
-
- private static unsafe void DestroyStructureHelper(IntPtr ptr, Type structuretype)
- {
- RuntimeTypeHandle structureTypeHandle = structuretype.TypeHandle;
-
// Boxed struct start at offset 1 (EEType* at offset 0) while class start at offset 0
int offset = structureTypeHandle.IsValueType() ? 1 : 0;
@@ -1226,9 +1277,7 @@ namespace System.Runtime.InteropServices
return;
}
- IntPtr destroyStructureStub;
- bool hasInvalidLayout;
- if (RuntimeInteropData.Instance.TryGetDestroyStructureStub(structureTypeHandle, out destroyStructureStub, out hasInvalidLayout))
+ if (RuntimeInteropData.Instance.TryGetDestroyStructureStub(structureTypeHandle, out IntPtr destroyStructureStub, out bool hasInvalidLayout))
{
if (hasInvalidLayout)
throw new ArgumentException(SR.Argument_MustHaveLayoutOrBeBlittable, structureTypeHandle.GetDisplayName());
diff --git a/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/CustomPropertyImpl.cs b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/CustomPropertyImpl.cs
index 70678b9ef..6a1887b3f 100644
--- a/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/CustomPropertyImpl.cs
+++ b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/CustomPropertyImpl.cs
@@ -133,7 +133,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
);
// We need to make sure it has the same HR that we were returning in desktop
- InteropExtensions.SetExceptionErrorCode(ex, __HResults.COR_E_METHODACCESS);
+ ex.HResult = __HResults.COR_E_METHODACCESS;
throw ex;
}
}
diff --git a/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationTokenTable.cs b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationTokenTable.cs
index c89fe9e29..002bdf888 100644
--- a/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationTokenTable.cs
+++ b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationTokenTable.cs
@@ -185,7 +185,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
public void RemoveEventHandler(T handler)
{
- // To match the Windows Runtime behaivor when adding a null handler, removing one is a no-op
+ // To match the Windows Runtime behavior when adding a null handler, removing one is a no-op
if (handler == null)
{
return;
diff --git a/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/PropertyValueImpl.cs b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/PropertyValueImpl.cs
index d4df5c9dd..670506256 100644
--- a/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/PropertyValueImpl.cs
+++ b/src/System.Private.Interop/src/System/Runtime/InteropServices/WindowsRuntime/PropertyValueImpl.cs
@@ -419,9 +419,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
PropertyType type,
PropertyType unboxType)
{
- System.InvalidCastException ex = new System.InvalidCastException(SR.Format(SR.PropertyValue_InvalidCast, type, unboxType));
- McgMarshal.SetExceptionErrorCode(ex, Interop.COM.TYPE_E_TYPEMISMATCH);
- return ex;
+ return new System.InvalidCastException(SR.Format(SR.PropertyValue_InvalidCast, type, unboxType), Interop.COM.TYPE_E_TYPEMISMATCH);
}
private static System.InvalidCastException CreateExceptionForInvalidCoersion(
@@ -430,9 +428,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
PropertyType unboxType,
int hr)
{
- InvalidCastException ex = new InvalidCastException(SR.Format(SR.PropertyValue_InvalidCoersion, type, value, unboxType));
- McgMarshal.SetExceptionErrorCode(ex, hr);
- return ex;
+ return new InvalidCastException(SR.Format(SR.PropertyValue_InvalidCoersion, type, value, unboxType), hr);
}
}
diff --git a/src/System.Private.Interop/src/WinRT/ExceptionHelpers.cs b/src/System.Private.Interop/src/WinRT/ExceptionHelpers.cs
index 6f9be707d..ae1fed82f 100644
--- a/src/System.Private.Interop/src/WinRT/ExceptionHelpers.cs
+++ b/src/System.Private.Interop/src/WinRT/ExceptionHelpers.cs
@@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.
using System;
+using System.Collections.Generic.Internal;
using System.Diagnostics;
using System.Runtime.CompilerServices;
@@ -16,6 +17,46 @@ namespace System.Runtime.InteropServices
/// </summary>
public static unsafe partial class ExceptionHelpers
{
+#if DEBUG
+ [ThreadStatic]
+ private static Dictionary<Exception, bool> t_propagatedExceptions = new Dictionary<Exception, bool>();
+#endif
+
+ public static bool PropagateException(Exception ex)
+ {
+#if DEBUG
+ Debug.Assert(!ExceptionHelpers.t_propagatedExceptions.ContainsKey(ex));
+ ExceptionHelpers.t_propagatedExceptions.Add(ex, true);
+#endif
+ try
+ {
+ IntPtr pRestrictedErrorInfo;
+ object restrictedErrorInfo;
+ if (InteropExtensions.TryGetRestrictedErrorObject(ex, out restrictedErrorInfo) && restrictedErrorInfo != null)
+ {
+ // We have the restricted errorInfo associated with this object and hence this exception was created by an hr entering managed through native.
+ pRestrictedErrorInfo = McgMarshal.ObjectToComInterface(restrictedErrorInfo, InternalTypes.IRestrictedErrorInfo);
+ if (pRestrictedErrorInfo != IntPtr.Zero)
+ {
+ // We simply call SetRestrictedErrorInfo since we do not want to originate the exception again.
+ ExternalInterop.SetRestrictedErrorInfo(pRestrictedErrorInfo);
+ McgMarshal.ComSafeRelease(pRestrictedErrorInfo);
+ }
+ }
+ else
+ {
+ // we are in windows 8.1+ and hence we can preserve our exception so that we can reuse this exception in case it comes back and provide richer exception support.
+ OriginateLanguageException(ex);
+ }
+ }
+ catch (Exception)
+ {
+ // We can't throw an exception here and hence simply swallow it.
+ }
+
+ return true;
+ }
+
/// <summary>
/// This class is a helper class to call into IRestrictedErrorInfo methods.
/// </summary>
@@ -56,11 +97,11 @@ namespace System.Runtime.InteropServices
finally
{
if (pErrDes != IntPtr.Zero)
- ExternalInterop.SysFreeString(pErrDes);
+ McgMarshal.SysFreeString(pErrDes);
if (pResErrDes != IntPtr.Zero)
- ExternalInterop.SysFreeString(pResErrDes);
+ McgMarshal.SysFreeString(pResErrDes);
if (pErrCapSid != IntPtr.Zero)
- ExternalInterop.SysFreeString(pErrCapSid);
+ McgMarshal.SysFreeString(pErrCapSid);
}
return result >= 0;
@@ -88,7 +129,7 @@ namespace System.Runtime.InteropServices
finally
{
if (pReference != IntPtr.Zero)
- ExternalInterop.SysFreeString(pReference);
+ McgMarshal.SysFreeString(pReference);
}
}
}
@@ -160,6 +201,78 @@ namespace System.Runtime.InteropServices
internal System.IntPtr pfnGetReference;
}
+ internal unsafe struct __com_ILanguageExceptionStackBackTrace
+ {
+ internal __vtable_ILanguageExceptionStackBackTrace* pVtable;
+ }
+
+ internal unsafe struct __vtable_ILanguageExceptionStackBackTrace
+ {
+ private IntPtr pfnQueryInterface;
+ private IntPtr pfnAddRef;
+ private IntPtr pfnRelease;
+ internal IntPtr pfnGetStackBackTrace;
+
+ public static IntPtr pNativeVtable;
+ private static __vtable_ILanguageExceptionStackBackTrace s_theCcwVtable = new __vtable_ILanguageExceptionStackBackTrace
+ {
+ // IUnknown
+ pfnQueryInterface = AddrOfIntrinsics.AddrOf<AddrOfQueryInterface>(__vtable_IUnknown.QueryInterface),
+ pfnAddRef = AddrOfIntrinsics.AddrOf<AddrOfAddRef>(__vtable_IUnknown.AddRef),
+ pfnRelease = AddrOfIntrinsics.AddrOf<AddrOfRelease>(__vtable_IUnknown.Release),
+ // ILanguageExceptionStackBackTrace
+ pfnGetStackBackTrace = AddrOfIntrinsics.AddrOf<System.Runtime.InteropServices.AddrOfIntrinsics.AddrOfILanguageExceptionStackBackTraceGetStackBackTrace>(GetStackBackTrace),
+ };
+
+ internal static IntPtr GetVtableFuncPtr()
+ {
+ return AddrOfIntrinsics.AddrOf<AddrOfGetCCWVtable>(GetCcwvtable_ILanguageExceptionStackBackTrace);
+ }
+
+ internal static unsafe IntPtr GetCcwvtable_ILanguageExceptionStackBackTrace()
+ {
+ if (pNativeVtable == default(IntPtr))
+ {
+ fixed (void* pVtbl = &s_theCcwVtable)
+ {
+ McgMarshal.GetCCWVTableCopy(pVtbl, ref __vtable_ILanguageExceptionStackBackTrace.pNativeVtable,sizeof(__vtable_ILanguageExceptionStackBackTrace));
+
+ }
+ }
+ return __vtable_ILanguageExceptionStackBackTrace.pNativeVtable;
+ }
+
+ [NativeCallable]
+ public static int GetStackBackTrace(IntPtr pComThis, uint maxFramesToCapture, IntPtr stackBackTrace, IntPtr framesCaptured)
+ {
+ try
+ {
+ object target = ComCallableObject.FromThisPointer(pComThis).TargetObject;
+ Debug.Assert(target is Exception);
+ IntPtr[] stackIPs = InteropExtensions.ExceptionGetStackIPs(target as Exception);
+ uint* pFramesCaptured = (uint*)framesCaptured;
+ *pFramesCaptured = Math.Min((uint)stackIPs.Length, maxFramesToCapture);
+ if (stackBackTrace != IntPtr.Zero)
+ {
+ unsafe
+ {
+ IntPtr* pStackBackTrace = (IntPtr*)stackBackTrace;
+ for (uint i = 0; i < *pFramesCaptured ; i++)
+ {
+ *pStackBackTrace = stackIPs[i];
+ pStackBackTrace++;
+ }
+ }
+ }
+ return Interop.COM.S_OK;
+ }
+ catch (System.Exception hrExcep)
+ {
+ return McgMarshal.GetHRForExceptionWinRT(hrExcep);
+ }
+ }
+ }
+
#pragma warning restore 649, 169
/// <summary>
@@ -200,24 +313,10 @@ namespace System.Runtime.InteropServices
// Check whether the exception has an associated RestrictedErrorInfo associated with it.
if (isWinRTScenario)
{
- IntPtr pRestrictedErrorInfo;
- object restrictedErrorInfo;
- if (InteropExtensions.TryGetRestrictedErrorObject(ex, out restrictedErrorInfo) && restrictedErrorInfo != null)
- {
- // We have the restricted errorInfo associated with this object and hence this exception was created by an hr entering managed through native.
- pRestrictedErrorInfo = McgMarshal.ObjectToComInterface(restrictedErrorInfo, InternalTypes.IRestrictedErrorInfo);
- if (pRestrictedErrorInfo != IntPtr.Zero)
- {
- // We simply call SetRestrictedErrorInfo since we do not want to originate the exception again.
- ExternalInterop.SetRestrictedErrorInfo(pRestrictedErrorInfo);
- McgMarshal.ComSafeRelease(pRestrictedErrorInfo);
- }
- }
- else
- {
- // we are in windows blue and hence we can preserve our exception so that we can reuse this exception in case it comes back and provide richer exception support.
- OriginateLanguageException(ex);
- }
+#if DEBUG
+ Debug.Assert(ExceptionHelpers.t_propagatedExceptions.ContainsKey(ex));
+ ExceptionHelpers.t_propagatedExceptions.Remove(ex);
+#endif
}
else
{
@@ -719,7 +818,7 @@ namespace System.Runtime.InteropServices
InteropExtensions.SetExceptionMessage(exception, message);
}
- InteropExtensions.SetExceptionErrorCode(exception, errorCode);
+ exception.HResult = errorCode;
return exception;
}
diff --git a/src/System.Private.Interpreter/src/Internal/Runtime/CompilerHelpers/LibraryInitializer.cs b/src/System.Private.Interpreter/src/Internal/Runtime/CompilerHelpers/LibraryInitializer.cs
new file mode 100644
index 000000000..82c5b1299
--- /dev/null
+++ b/src/System.Private.Interpreter/src/Internal/Runtime/CompilerHelpers/LibraryInitializer.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.Runtime.Interpreter;
+using Internal.Runtime.TypeLoader;
+
+namespace Internal.Runtime.CompilerHelpers
+{
+ public class LibraryInitializer
+ {
+ public static void InitializeLibrary()
+ {
+ MethodExecutionStrategy.GlobalExecutionStrategy = new InterpreterExecutionStrategy();
+ }
+ }
+}
diff --git a/src/System.Private.Interpreter/src/Internal/Runtime/Interpreter/ILImporter.Interpreter.cs b/src/System.Private.Interpreter/src/Internal/Runtime/Interpreter/ILImporter.Interpreter.cs
new file mode 100644
index 000000000..70b54d2a3
--- /dev/null
+++ b/src/System.Private.Interpreter/src/Internal/Runtime/Interpreter/ILImporter.Interpreter.cs
@@ -0,0 +1,501 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics;
+using Internal.Runtime.Interpreter;
+using Internal.TypeSystem;
+
+namespace Internal.IL
+{
+ partial class ILImporter
+ {
+ private class BasicBlock
+ {
+ // Common fields
+ public enum ImportState : byte
+ {
+ Unmarked,
+ IsPending
+ }
+
+ public BasicBlock Next;
+
+ public int StartOffset;
+ public ImportState State = ImportState.Unmarked;
+
+ public bool TryStart;
+ public bool FilterStart;
+ public bool HandlerStart;
+ }
+
+ private class ExceptionRegion
+ {
+ public ILExceptionRegion ILRegion;
+ }
+
+ private readonly byte[] _ilBytes;
+ private readonly MethodDesc _method;
+ private readonly MethodIL _methodIL;
+ private readonly ILInterpreter _interpreter;
+ private ExceptionRegion[] _exceptionRegions;
+
+ public ILImporter(ILInterpreter interpreter, MethodDesc method, MethodIL methodIL)
+ {
+ _ilBytes = methodIL.GetILBytes();
+ _method = method;
+ _methodIL = methodIL;
+ _interpreter = interpreter;
+
+ var ilExceptionRegions = methodIL.GetExceptionRegions();
+ _exceptionRegions = new ExceptionRegion[methodIL.GetExceptionRegions().Length];
+ for (int i = 0; i < ilExceptionRegions.Length; i++)
+ {
+ _exceptionRegions[i] = new ExceptionRegion() { ILRegion = ilExceptionRegions[i] };
+ }
+ }
+
+ public void Interpret()
+ {
+ FindBasicBlocks();
+ ImportBasicBlocks();
+ }
+
+ private void MarkInstructionBoundary() { }
+
+ private void StartImportingInstruction() { }
+
+ private void EndImportingInstruction() { }
+
+ private void StartImportingBasicBlock(BasicBlock basicBlock) { }
+
+ private void EndImportingBasicBlock(BasicBlock basicBlock) { }
+
+ private void ReportInvalidBranchTarget(int targetOffset)
+ {
+ ThrowHelper.ThrowInvalidProgramException();
+ }
+
+ private void ReportFallthroughAtEndOfMethod()
+ {
+ ThrowHelper.ThrowInvalidProgramException();
+ }
+
+ private void ReportMethodEndInsideInstruction()
+ {
+ ThrowHelper.ThrowInvalidProgramException();
+ }
+
+ private void ReportInvalidInstruction(ILOpcode opcode)
+ {
+ ThrowHelper.ThrowInvalidProgramException();
+ }
+
+ private TypeDesc ResolveTypeToken(int token)
+ {
+ return (TypeDesc)_methodIL.GetObject(token);
+ }
+
+ private TypeDesc GetWellKnownType(WellKnownType wellKnownType)
+ {
+ return _interpreter.TypeSystemContext.GetWellKnownType(wellKnownType);
+ }
+
+ public StackItem PopWithValidation()
+ {
+ bool hasStackItem = _interpreter.EvaluationStack.TryPop(out StackItem stackItem);
+ if (!hasStackItem)
+ ThrowHelper.ThrowInvalidProgramException();
+
+ return stackItem;
+ }
+
+ private void ImportNop()
+ {
+ // Do nothing!
+ }
+
+ private void ImportBreak()
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportLoadVar(int index, bool argument)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportStoreVar(int index, bool argument)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportAddressOfVar(int index, bool argument)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportDup()
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportPop()
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportCalli(int token)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportLoadNull()
+ {
+ _interpreter.EvaluationStack.Push(StackItem.FromObjectRef(null));
+ }
+
+ private void ImportReturn()
+ {
+ var returnType = _method.Signature.ReturnType;
+ if (returnType.IsVoid)
+ return;
+
+ StackItem stackItem = PopWithValidation();
+ TypeFlags category = returnType.Category;
+
+ switch (category)
+ {
+ case TypeFlags.Boolean:
+ _interpreter.SetReturnValue(stackItem.AsInt32() != 0);
+ break;
+ case TypeFlags.Char:
+ _interpreter.SetReturnValue((char)stackItem.AsInt32());
+ break;
+ case TypeFlags.SByte:
+ _interpreter.SetReturnValue((sbyte)stackItem.AsInt32());
+ break;
+ case TypeFlags.Byte:
+ _interpreter.SetReturnValue((byte)stackItem.AsInt32());
+ break;
+ case TypeFlags.Int16:
+ _interpreter.SetReturnValue((short)stackItem.AsInt32());
+ break;
+ case TypeFlags.UInt16:
+ _interpreter.SetReturnValue((ushort)stackItem.AsInt32());
+ break;
+ case TypeFlags.Int32:
+ case TypeFlags.UInt32:
+ _interpreter.SetReturnValue(stackItem.AsInt32());
+ break;
+ case TypeFlags.Int64:
+ case TypeFlags.UInt64:
+ _interpreter.SetReturnValue(stackItem.AsInt64());
+ break;
+ case TypeFlags.IntPtr:
+ case TypeFlags.UIntPtr:
+ _interpreter.SetReturnValue(stackItem.AsIntPtr());
+ break;
+ case TypeFlags.Single:
+ _interpreter.SetReturnValue((float)stackItem.AsDouble());
+ break;
+ case TypeFlags.Double:
+ _interpreter.SetReturnValue(stackItem.AsDouble());
+ break;
+ case TypeFlags.ValueType:
+ _interpreter.SetReturnValue(stackItem.AsValueType());
+ break;
+ case TypeFlags.Interface:
+ case TypeFlags.Class:
+ case TypeFlags.Array:
+ case TypeFlags.SzArray:
+ _interpreter.SetReturnValue(stackItem.AsObjectRef());
+ break;
+ case TypeFlags.Enum:
+ case TypeFlags.Nullable:
+ case TypeFlags.ByRef:
+ case TypeFlags.Pointer:
+ case TypeFlags.FunctionPointer:
+ case TypeFlags.GenericParameter:
+ default:
+ // TODO: Support more complex return types
+ break;
+ }
+ }
+
+ private void ImportLoadInt(long value, StackValueKind kind)
+ {
+ if (kind == StackValueKind.Int32)
+ _interpreter.EvaluationStack.Push(StackItem.FromInt32((int)value));
+ else if (kind == StackValueKind.Int64)
+ _interpreter.EvaluationStack.Push(StackItem.FromInt64(value));
+ }
+
+ private void ImportLoadFloat(double value)
+ {
+ _interpreter.EvaluationStack.Push(StackItem.FromDouble(value));
+ }
+
+ private void ImportShiftOperation(ILOpcode opcode)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportCompareOperation(ILOpcode opcode)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportConvert(WellKnownType wellKnownType, bool checkOverflow, bool unsigned)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportUnaryOperation(ILOpcode opCode)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportCpOpj(int token)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportCkFinite()
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportLocalAlloc()
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportEndFilter()
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportCpBlk()
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportInitBlk()
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportRethrow()
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportSizeOf(int token)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportUnalignedPrefix(byte alignment)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportVolatilePrefix()
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportTailPrefix()
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportNoPrefix(byte mask)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportThrow()
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportInitObj(int token)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportLoadLength()
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportEndFinally()
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportFallthrough(BasicBlock nextBasicBlock)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportReadOnlyPrefix()
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportRefAnyType()
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportConstrainedPrefix(int v)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportLdFtn(int v, ILOpcode opCode)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportArgList()
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportLeave(BasicBlock basicBlock)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportLdToken(int v)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportMkRefAny(int v)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportRefAnyVal(int v)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportAddressOfElement(int v)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportNewArray(int v)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportBox(int v)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportStoreField(int v1, bool v2)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportAddressOfField(int v1, bool v2)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportLoadField(int v1, bool v2)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportUnbox(int v, ILOpcode opCode)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportCasting(ILOpcode opCode, int v)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportLoadString(int token)
+ {
+ string str = (string)_methodIL.GetObject(token);
+ _interpreter.EvaluationStack.Push(StackItem.FromObjectRef(str));
+ }
+
+ private void ImportBinaryOperation(ILOpcode opCode)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportSwitchJump(int jmpBase, int[] jmpDelta, BasicBlock basicBlock)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportBranch(ILOpcode iLOpcode, BasicBlock basicBlock1, BasicBlock basicBlock2)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportCall(ILOpcode opCode, int v)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportJmp(int v)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportLoadIndirect(int token)
+ {
+ ImportLoadIndirect(ResolveTypeToken(token));
+ }
+
+ private void ImportLoadIndirect(TypeDesc type)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportStoreIndirect(int token)
+ {
+ ImportStoreIndirect(ResolveTypeToken(token));
+ }
+
+ private void ImportStoreIndirect(TypeDesc type)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportLoadElement(int token)
+ {
+ ImportLoadElement(ResolveTypeToken(token));
+ }
+
+ private void ImportLoadElement(TypeDesc elementType)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void ImportStoreElement(int token)
+ {
+ ImportStoreElement(ResolveTypeToken(token));
+ }
+
+ private void ImportStoreElement(TypeDesc elementType)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/System.Private.Interpreter/src/Internal/Runtime/Interpreter/ILInterpreter.cs b/src/System.Private.Interpreter/src/Internal/Runtime/Interpreter/ILInterpreter.cs
new file mode 100644
index 000000000..f5f947c74
--- /dev/null
+++ b/src/System.Private.Interpreter/src/Internal/Runtime/Interpreter/ILInterpreter.cs
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+
+using Internal.IL;
+using Internal.Runtime.CallInterceptor;
+using Internal.TypeSystem;
+
+namespace Internal.Runtime.Interpreter
+{
+ internal unsafe class ILInterpreter
+ {
+ private readonly MethodDesc _method;
+ private readonly MethodIL _methodIL;
+ private readonly TypeSystemContext _context;
+ private readonly LowLevelStack<StackItem> _stack;
+
+ private CallInterceptorArgs _callInterceptorArgs;
+
+ public LowLevelStack<StackItem> EvaluationStack => _stack;
+
+ public TypeSystemContext TypeSystemContext => _context;
+
+ public ILInterpreter(TypeSystemContext context, MethodDesc method, MethodIL methodIL)
+ {
+ _context = context;
+ _method = method;
+ _methodIL = methodIL;
+ _stack = new LowLevelStack<StackItem>();
+ }
+
+ public void InterpretMethod(ref CallInterceptorArgs callInterceptorArgs)
+ {
+ _callInterceptorArgs = callInterceptorArgs;
+ ILImporter importer = new ILImporter(this, _method, _methodIL);
+ importer.Interpret();
+ }
+
+ public void SetReturnValue<T>(T value)
+ {
+ _callInterceptorArgs.ArgumentsAndReturnValue.SetVar<T>(0, value);
+ }
+ }
+}
diff --git a/src/System.Private.Interpreter/src/Internal/Runtime/Interpreter/InterpreterCallInterceptor.cs b/src/System.Private.Interpreter/src/Internal/Runtime/Interpreter/InterpreterCallInterceptor.cs
new file mode 100644
index 000000000..3703d213b
--- /dev/null
+++ b/src/System.Private.Interpreter/src/Internal/Runtime/Interpreter/InterpreterCallInterceptor.cs
@@ -0,0 +1,72 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.IL;
+using Internal.Runtime.CallConverter;
+using Internal.Runtime.CallInterceptor;
+using Internal.TypeSystem;
+using Internal.TypeSystem.Ecma;
+
+namespace Internal.Runtime.Interpreter
+{
+ public class InterpreterCallInterceptor : CallInterceptor.CallInterceptor
+ {
+ private readonly MethodDesc _method;
+ private readonly MethodIL _methodIL;
+ private readonly TypeSystemContext _context;
+
+ public InterpreterCallInterceptor(TypeSystemContext context, MethodDesc method) : base(false)
+ {
+ _context = context;
+ _method = method;
+ _methodIL = EcmaMethodIL.Create(method as EcmaMethod);
+ }
+
+ public override LocalVariableType[] ArgumentAndReturnTypes
+ {
+ get
+ {
+ LocalVariableType[] localVariableTypes = new LocalVariableType[_method.Signature.Length + 1];
+ localVariableTypes[0] = new LocalVariableType(_method.Signature.ReturnType.RuntimeTypeHandle, false, _method.Signature.ReturnType.IsByRef);
+ for (int i = 0; i < _method.Signature.Length; i++)
+ {
+ var argument = _method.Signature[i];
+ localVariableTypes[i + 1] = new LocalVariableType(argument.RuntimeTypeHandle, false, argument.IsByRef);
+ }
+
+ return localVariableTypes;
+ }
+ }
+
+ public override CallingConvention CallingConvention
+ {
+ get
+ {
+ return _method.Signature.IsStatic ? CallingConvention.ManagedStatic : CallingConvention.ManagedInstance;
+ }
+ }
+
+ public override LocalVariableType[] LocalVariableTypes
+ {
+ get
+ {
+ LocalVariableDefinition[] locals = _methodIL.GetLocals();
+ LocalVariableType[] localVariableTypes = new LocalVariableType[locals.Length];
+ for (int i = 0; i < locals.Length; i++)
+ {
+ var variable = locals[i];
+ localVariableTypes[i] = new LocalVariableType(variable.Type.RuntimeTypeHandle, variable.IsPinned, variable.Type.IsByRef);
+ }
+
+ return localVariableTypes;
+ }
+ }
+
+ public override void ThunkExecute(ref CallInterceptorArgs callInterceptorArgs)
+ {
+ ILInterpreter interpreter = new ILInterpreter(_context, _method, _methodIL);
+ interpreter.InterpretMethod(ref callInterceptorArgs);
+ }
+ }
+}
diff --git a/src/System.Private.Interpreter/src/Internal/Runtime/Interpreter/InterpreterExecutionStrategy.cs b/src/System.Private.Interpreter/src/Internal/Runtime/Interpreter/InterpreterExecutionStrategy.cs
new file mode 100644
index 000000000..7fa3a5742
--- /dev/null
+++ b/src/System.Private.Interpreter/src/Internal/Runtime/Interpreter/InterpreterExecutionStrategy.cs
@@ -0,0 +1,22 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+using Internal.Runtime.TypeLoader;
+using Internal.TypeSystem;
+
+namespace Internal.Runtime.Interpreter
+{
+ public class InterpreterExecutionStrategy : MethodExecutionStrategy
+ {
+ public override IntPtr OnEntryPoint(MethodEntrypointPtr methodEntrypointPtr, IntPtr callerArgumentsInfo)
+ {
+ var context = TypeSystemContextFactory.Create();
+ MethodDesc method = methodEntrypointPtr.MethodIdentifier.ToMethodDesc(context);
+ InterpreterCallInterceptor callInterceptor = new InterpreterCallInterceptor(context, method);
+ return callInterceptor.GetThunkAddress();
+ }
+ }
+}
diff --git a/src/System.Private.Interpreter/src/Internal/Runtime/Interpreter/StackItem.cs b/src/System.Private.Interpreter/src/Internal/Runtime/Interpreter/StackItem.cs
new file mode 100644
index 000000000..97578b61d
--- /dev/null
+++ b/src/System.Private.Interpreter/src/Internal/Runtime/Interpreter/StackItem.cs
@@ -0,0 +1,105 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using Internal.IL;
+using Internal.TypeSystem;
+
+namespace Internal.Runtime.Interpreter
+{
+ [StructLayout(LayoutKind.Explicit)]
+ internal unsafe struct StackItem
+ {
+ [FieldOffset(0)]
+ private StackValueKind _kind;
+
+ [FieldOffset(8)]
+ private int _int32;
+
+ [FieldOffset(8)]
+ private long _int64;
+
+ [FieldOffset(8)]
+ private IntPtr _nativeInt;
+
+ [FieldOffset(8)]
+ private double _double;
+
+ [FieldOffset(16)]
+ private ValueType _valueType;
+
+ [FieldOffset(16)]
+ private object _objref;
+
+ public StackValueKind Kind => _kind;
+
+ public static StackItem FromInt32(int int32)
+ {
+ return new StackItem { _int32 = int32, _kind = StackValueKind.Int32 };
+ }
+
+ public int AsInt32()
+ {
+ Debug.Assert(_kind == StackValueKind.Int32);
+ return _int32;
+ }
+
+ public static StackItem FromInt64(long int64)
+ {
+ return new StackItem { _int64 = int64, _kind = StackValueKind.Int64 };
+ }
+
+ public long AsInt64()
+ {
+ Debug.Assert(_kind == StackValueKind.Int64);
+ return _int64;
+ }
+
+ public static StackItem FromIntPtr(IntPtr nativeInt)
+ {
+ return new StackItem { _nativeInt = nativeInt, _kind = StackValueKind.NativeInt };
+ }
+
+ public IntPtr AsIntPtr()
+ {
+ Debug.Assert(_kind == StackValueKind.NativeInt);
+ return _nativeInt;
+ }
+
+ public static StackItem FromDouble(double d)
+ {
+ return new StackItem { _double = d, _kind = StackValueKind.Float };
+ }
+
+ public double AsDouble()
+ {
+ Debug.Assert(_kind == StackValueKind.Float);
+ return _double;
+ }
+
+ public static StackItem FromValueType(ValueType valueType)
+ {
+ return new StackItem { _valueType = valueType, _kind = StackValueKind.ValueType };
+ }
+
+ public ValueType AsValueType()
+ {
+ Debug.Assert(_kind == StackValueKind.ValueType);
+ return _valueType;
+ }
+
+ public static StackItem FromObjectRef(object obj)
+ {
+ return new StackItem { _objref = obj, _kind = StackValueKind.ObjRef };
+ }
+
+ public object AsObjectRef()
+ {
+ Debug.Assert(_kind == StackValueKind.ObjRef);
+ return _objref;
+ }
+ }
+}
diff --git a/src/System.Private.Interpreter/src/System.Private.Interpreter.csproj b/src/System.Private.Interpreter/src/System.Private.Interpreter.csproj
new file mode 100644
index 000000000..3808516a4
--- /dev/null
+++ b/src/System.Private.Interpreter/src/System.Private.Interpreter.csproj
@@ -0,0 +1,35 @@
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <AssemblyName>System.Private.Interpreter</AssemblyName>
+ <AssemblyVersion>4.0.0.0</AssemblyVersion>
+ <OutputType>Library</OutputType>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <ItemGroup Condition="'$(IsProjectNLibrary)' != 'true'">
+ <ProjectReference Include="..\..\AotPackageReference\AotPackageReference.depproj">
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <SkipGetTargetFrameworkProperties>true</SkipGetTargetFrameworkProperties>
+ </ProjectReference>
+ <ReferencePath Include="$(AotPackageReferencePath)\System.Runtime.dll" />
+ <ReferencePath Include="$(AotPackageReferencePath)\System.Runtime.Extensions.dll" />
+ <ReferencePath Include="$(AotPackageReferencePath)\System.Private.Reflection.Metadata.Ecma335.dll" />
+ <ProjectReference Include="..\..\System.Private.CoreLib\src\System.Private.CoreLib.csproj" />
+ <ProjectReference Include="..\..\System.Private.Reflection.Metadata\src\System.Private.Reflection.Metadata.csproj" />
+ <ProjectReference Include="..\..\System.Private.TypeLoader\src\System.Private.TypeLoader.Experimental.csproj" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\..\Common\src\TypeSystem\IL\EcmaMethodIL.cs" />
+ <Compile Include="..\..\Common\src\TypeSystem\IL\ILImporter.cs" />
+ <Compile Include="..\..\Common\src\System\Collections\Generic\LowLevelStack.cs" />
+ <Compile Include="Internal\Runtime\CompilerHelpers\LibraryInitializer.cs" />
+ <Compile Include="Internal\Runtime\Interpreter\StackItem.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Internal\Runtime\Interpreter\ILImporter.Interpreter.cs" />
+ <Compile Include="Internal\Runtime\Interpreter\ILInterpreter.cs" />
+ <Compile Include="Internal\Runtime\Interpreter\InterpreterCallInterceptor.cs" />
+ <Compile Include="Internal\Runtime\Interpreter\InterpreterExecutionStrategy.cs" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project> \ No newline at end of file
diff --git a/src/System.Private.Jit/src/Internal/Runtime/CompilerHelpers/LibraryInitializer.cs b/src/System.Private.Jit/src/Internal/Runtime/CompilerHelpers/LibraryInitializer.cs
new file mode 100644
index 000000000..ff2abd9e8
--- /dev/null
+++ b/src/System.Private.Jit/src/Internal/Runtime/CompilerHelpers/LibraryInitializer.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.Runtime.JitSupport;
+using Internal.Runtime.TypeLoader;
+
+namespace Internal.Runtime.CompilerHelpers
+{
+ public class LibraryInitializer
+ {
+ public static void InitializeLibrary()
+ {
+ MethodExecutionStrategy.GlobalExecutionStrategy = new RyuJitExecutionStrategy();
+ }
+ }
+}
diff --git a/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitCompilation.cs b/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitCompilation.cs
index e628978b9..2c5f06f72 100644
--- a/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitCompilation.cs
+++ b/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitCompilation.cs
@@ -21,7 +21,8 @@ namespace ILCompiler
{
_typeSystemContext = context;
_typeGetTypeMethodThunks = new TypeGetTypeMethodThunkCache(context.GetWellKnownType(WellKnownType.Object));
- _methodILCache = new ILProvider(new PInvokeILProvider(new PInvokeILEmitterConfiguration(forceLazyResolution: true), null));
+ _pInvokeILProvider = new PInvokeILProvider(new PInvokeILEmitterConfiguration(forceLazyResolution: true), null);
+ _methodILCache = new ILProvider(_pInvokeILProvider);
_nodeFactory = new NodeFactory(context);
_devirtualizationManager = new DevirtualizationManager();
}
@@ -31,9 +32,11 @@ namespace ILCompiler
protected readonly Logger _logger = Logger.Null;
private readonly TypeGetTypeMethodThunkCache _typeGetTypeMethodThunks;
private ILProvider _methodILCache;
+ private PInvokeILProvider _pInvokeILProvider;
private readonly DevirtualizationManager _devirtualizationManager;
internal Logger Logger => _logger;
+ internal PInvokeILProvider PInvokeILProvider => _pInvokeILProvider;
public TypeSystemContext TypeSystemContext { get { return _typeSystemContext; } }
public NodeFactory NodeFactory { get { return _nodeFactory; } }
@@ -51,7 +54,7 @@ namespace ILCompiler
{
// Flush the cache when it grows too big
if (_methodILCache.Count > 1000)
- _methodILCache = new ILProvider(new PInvokeILProvider(new PInvokeILEmitterConfiguration(forceLazyResolution: true), null));
+ _methodILCache = new ILProvider(_pInvokeILProvider);
return _methodILCache.GetMethodIL(method);
}
@@ -142,4 +145,4 @@ namespace ILCompiler
return DelegateCreationInfo.Create(delegateType, target, NodeFactory, followVirtualDispatch);
}
}
-} \ No newline at end of file
+}
diff --git a/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitMethodCodeNode.cs b/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitMethodCodeNode.cs
index 4e66d5d38..b605c485b 100644
--- a/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitMethodCodeNode.cs
+++ b/src/System.Private.Jit/src/Internal/Runtime/JitSupport/JitMethodCodeNode.cs
@@ -28,6 +28,7 @@ namespace Internal.Runtime.JitSupport
private ObjectData _ehInfo;
private DebugLocInfo[] _debugLocInfos;
private DebugVarInfo[] _debugVarInfos;
+ private DebugEHClauseInfo[] _debugEHClauseInfos;
public void SetCode(ObjectData data)
{
@@ -60,6 +61,7 @@ namespace Internal.Runtime.JitSupport
}
public DebugLocInfo[] DebugLocInfos => _debugLocInfos;
public DebugVarInfo[] DebugVarInfos => _debugVarInfos;
+ public DebugEHClauseInfo[] DebugEHClauseInfos => _debugEHClauseInfos;
public void InitializeDebugLocInfos(DebugLocInfo[] debugLocInfos)
{
@@ -73,6 +75,12 @@ namespace Internal.Runtime.JitSupport
_debugVarInfos = debugVarInfos;
}
+ public void InitializeDebugEHClauseInfos(DebugEHClauseInfo[] debugEHClauseInfos)
+ {
+ Debug.Assert(_debugEHClauseInfos == null);
+ _debugEHClauseInfos = debugEHClauseInfos;
+ }
+
protected override string GetName(NodeFactory factory)
{
throw new PlatformNotSupportedException();
diff --git a/src/System.Private.Jit/src/Internal/Runtime/JitSupport/RyuJitExecutionStrategy.cs b/src/System.Private.Jit/src/Internal/Runtime/JitSupport/RyuJitExecutionStrategy.cs
index e67b3b8c4..9548f2f08 100644
--- a/src/System.Private.Jit/src/Internal/Runtime/JitSupport/RyuJitExecutionStrategy.cs
+++ b/src/System.Private.Jit/src/Internal/Runtime/JitSupport/RyuJitExecutionStrategy.cs
@@ -22,6 +22,8 @@ namespace Internal.Runtime.JitSupport
{
public class RyuJitExecutionStrategy : MethodExecutionStrategy
{
+ private const string NativeJitSupportLibrary = "*";
+
private CorInfoImpl _corInfoImpl;
private TypeSystemContext _context;
private NodeFactory _nodeFactory;
@@ -33,13 +35,13 @@ namespace Internal.Runtime.JitSupport
return;
}
- [DllImport("jitinterface")]
+ [DllImport(NativeJitSupportLibrary)]
static extern IntPtr AllocJittedCode(UInt32 cbCode, UInt32 align, out IntPtr pCodeManager);
- [DllImport("jitinterface")]
+ [DllImport(NativeJitSupportLibrary)]
static extern void SetEHInfoPtr(IntPtr pCodeManager, IntPtr pbCode, IntPtr ehInfo);
- [DllImport("jitinterface")]
+ [DllImport(NativeJitSupportLibrary)]
static extern unsafe IntPtr PublishRuntimeFunction(
IntPtr pCodeManager,
IntPtr pbCode,
@@ -51,10 +53,10 @@ namespace Internal.Runtime.JitSupport
byte[] pGCData,
UInt32 cbGCData);
- [DllImport("jitinterface")]
+ [DllImport(NativeJitSupportLibrary)]
static extern void UpdateRuntimeFunctionTable(IntPtr pCodeManager);
- [DllImport("jitinterface")]
+ [DllImport(NativeJitSupportLibrary)]
static extern void InitJitCodeManager(IntPtr mrtModule);
public override IntPtr OnEntryPoint(MethodEntrypointPtr methodEntrypoint, IntPtr callerArgs)
diff --git a/src/System.Private.Jit/src/Internal/Runtime/JitSupport/VirtualMethodSlotHelper.cs b/src/System.Private.Jit/src/Internal/Runtime/JitSupport/VirtualMethodSlotHelper.cs
index 10e3466bd..ab82c2d6f 100644
--- a/src/System.Private.Jit/src/Internal/Runtime/JitSupport/VirtualMethodSlotHelper.cs
+++ b/src/System.Private.Jit/src/Internal/Runtime/JitSupport/VirtualMethodSlotHelper.cs
@@ -23,7 +23,7 @@ namespace ILCompiler
/// Given a virtual method decl, return its VTable slot if the method is used on its containing type.
/// Return -1 if the virtual method is not used.
/// </summary>
- public static int GetVirtualMethodSlot(NodeFactory factory, MethodDesc method)
+ public static int GetVirtualMethodSlot(NodeFactory factory, MethodDesc method, TypeDesc implType)
{
Debug.Assert(method.IsVirtual);
diff --git a/src/System.Private.Jit/src/System.Private.Jit.csproj b/src/System.Private.Jit/src/System.Private.Jit.csproj
index 662339fa5..942a0b74b 100644
--- a/src/System.Private.Jit/src/System.Private.Jit.csproj
+++ b/src/System.Private.Jit/src/System.Private.Jit.csproj
@@ -1,4 +1,4 @@
-<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<AssemblyName>System.Private.Jit</AssemblyName>
@@ -31,7 +31,7 @@
</ProjectReference>
<ProjectReference Include="..\..\System.Private.Reflection.Metadata\src\System.Private.Reflection.Metadata.csproj" />
<ProjectReference Include="..\..\System.Private.TypeLoader\src\System.Private.TypeLoader.Experimental.csproj" />
- <ProjectReference Include="..\..\System.Private.Interop\src\System.Private.Interop.csproj" />
+ <ProjectReference Include="..\..\System.Private.Interop\src\System.Private.Interop.Experimental.csproj" />
</ItemGroup>
<PropertyGroup>
<NativeFormatCommonPath>..\..\Common\src\Internal\NativeFormat</NativeFormatCommonPath>
@@ -43,6 +43,7 @@
<JitInterfaceBasePath>..\..\JitInterface\src</JitInterfaceBasePath>
</PropertyGroup>
<ItemGroup>
+ <Compile Include="Internal\Runtime\CompilerHelpers\LibraryInitializer.cs" />
<Compile Include="Internal\Runtime\JitSupport\ExternObjectSymbolNode.cs" />
<Compile Include="Internal\Runtime\JitSupport\FrozenStrings.cs" />
<Compile Include="Internal\Runtime\JitSupport\JitCompilation.cs" />
@@ -69,6 +70,7 @@
<Compile Include="$(TypeSystemBasePath)\IL\Stubs\ArrayMethodILEmitter.cs" />
<Compile Include="$(TypeSystemBasePath)\IL\Stubs\CalliIntrinsic.cs" />
<Compile Include="$(TypeSystemBasePath)\IL\Stubs\ComparerIntrinsics.cs" />
+ <Compile Include="$(TypeSystemBasePath)\IL\Stubs\CalliMarshallingMethodThunk.cs" />
<Compile Include="$(TypeSystemBasePath)\IL\Stubs\DelegateMarshallingMethodThunk.cs" />
<Compile Include="$(TypeSystemBasePath)\IL\Stubs\ForwardDelegateCreationThunk.cs" />
<Compile Include="$(TypeSystemBasePath)\IL\Stubs\EETypePtrOfIntrinsic.cs" />
@@ -125,6 +127,7 @@
<Compile Include="$(ILCompilerBasePath)\Compiler\DependencyAnalysis\ObjectNodeSection.cs" />
<Compile Include="$(ILCompilerBasePath)\Compiler\DependencyAnalysis\ReadyToRunHelperNode.cs" />
<Compile Include="$(ILCompilerBasePath)\Compiler\DependencyAnalysis\Relocation.cs" />
+ <Compile Include="$(ILCompilerBasePath)\Compiler\DependencyAnalysis\ISortableNode.cs" />
<Compile Include="$(ILCompilerBasePath)\Compiler\DependencyAnalysis\SortableDependencyNode.cs" />
<Compile Include="$(ILCompilerBasePath)\Compiler\DelegateCreationInfo.cs" />
<Compile Include="$(ILCompilerBasePath)\Compiler\JitHelper.cs" />
@@ -153,4 +156,4 @@
<Compile Include="Internal\Runtime\JitSupport\VirtualMethodSlotHelper.cs" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
+</Project> \ No newline at end of file
diff --git a/src/System.Private.Reflection.Core/src/Resources/Strings.resx b/src/System.Private.Reflection.Core/src/Resources/Strings.resx
index 4d7615699..820a41e26 100644
--- a/src/System.Private.Reflection.Core/src/Resources/Strings.resx
+++ b/src/System.Private.Reflection.Core/src/Resources/Strings.resx
@@ -150,18 +150,12 @@
<data name="TypeLoad_TypeNotFoundInAssembly" xml:space="preserve">
<value>The type '{0}' cannot be found in assembly '{1}'.</value>
</data>
- <data name="TypeLoad_BadEscape" xml:space="preserve">
- <value>An invalid escape sequence was found inside a type name.</value>
- </data>
<data name="FileNotFound_AssemblyNotFound" xml:space="preserve">
<value>Cannot load assembly '{0}'. No metadata found for this assembly.</value>
</data>
<data name="Arg_HTCapacityOverflow" xml:space="preserve">
<value>Hashtable's capacity overflowed and went negative. Check load factor, capacity and the current size of the table.</value>
</data>
- <data name="NotSupported_ByRefReturn" xml:space="preserve">
- <value>ByRef return value not supported in reflection invocation.</value>
- </data>
<data name="Arg_DlgtTargMeth" xml:space="preserve">
<value>Cannot bind to the target method because its signature is not compatible with that of the delegate type.</value>
</data>
@@ -228,9 +222,6 @@
<data name="Arg_SetMethNotFnd" xml:space="preserve">
<value>Property set method not found.</value>
</data>
- <data name="TypeIsNotReflectable" xml:space="preserve">
- <value>Type instance is not IReflectable.</value>
- </data>
<data name="Arg_EmptyArray" xml:space="preserve">
<value>Array may not be empty.</value>
</data>
@@ -246,12 +237,6 @@
<data name="NoMetadataTokenAvailable" xml:space="preserve">
<value>There is no metadata token available for the given member.</value>
</data>
- <data name="ModuleVersionIdNotSupported" xml:space="preserve">
- <value>Module version IDs (MVIDs) cannot be retrieved on this platform.</value>
- </data>
- <data name="FileNotFound_ResolveAssembly" xml:space="preserve">
- <value>Could not resolve assembly '{0}'.</value>
- </data>
<data name="MissingField" xml:space="preserve">
<value>Field not found.</value>
</data>
@@ -286,18 +271,12 @@
<data name="Arg_NamedParamTooBig" xml:space="preserve">
<value>Named parameter array cannot be bigger than argument array.</value>
</data>
- <data name="Arg_COMAccess" xml:space="preserve">
- <value>Must specify property Set or Get or method call for a COM Object.</value>
- </data>
<data name="Arg_PropSetGet" xml:space="preserve">
<value>Cannot specify both Get and Set on a property.</value>
</data>
<data name="Arg_PropSetInvoke" xml:space="preserve">
<value>Cannot specify Set on a property and Invoke on a method.</value>
</data>
- <data name="Arg_COMPropSetPut" xml:space="preserve">
- <value>Only one of the following binding flags can be set: BindingFlags.SetProperty, BindingFlags.PutDispProperty, BindingFlags.PutRefDispProperty.</value>
- </data>
<data name="Arg_NamedParamNull" xml:space="preserve">
<value>Named parameter value must not be null.</value>
</data>
diff --git a/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.Experimental.csproj b/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.Experimental.csproj
index 75f14057a..2cc7b4b44 100644
--- a/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.Experimental.csproj
+++ b/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.Experimental.csproj
@@ -2,7 +2,7 @@
<PropertyGroup>
<AssemblyName>System.Private.Reflection.Core.Experimental</AssemblyName>
<EcmaMetadataSupport>true</EcmaMetadataSupport>
- <JitSupport>true</JitSupport>
+ <DynamicCodeSupport>true</DynamicCodeSupport>
</PropertyGroup>
<Import Project="System.Private.Reflection.Core.csproj" />
diff --git a/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj b/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj
index 696f74096..014a80f7f 100644
--- a/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj
+++ b/src/System.Private.Reflection.Core/src/System.Private.Reflection.Core.csproj
@@ -24,14 +24,15 @@
<SkipGetTargetFrameworkProperties>true</SkipGetTargetFrameworkProperties>
</ProjectReference>
<ProjectReference Include="..\..\System.Private.CoreLib\src\System.Private.CoreLib.csproj" />
- <ProjectReference Include="..\..\System.Private.Interop\src\System.Private.Interop.csproj" />
<ProjectReference Include="..\..\System.Private.Reflection.Metadata\src\System.Private.Reflection.Metadata.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(IsProjectNLibrary)' != 'true' and '$(EcmaMetadataSupport)' != 'true'">
<ProjectReference Include="..\..\System.Private.TypeLoader\src\System.Private.TypeLoader.csproj" />
+ <ProjectReference Include="..\..\System.Private.Interop\src\System.Private.Interop.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(IsProjectNLibrary)' != 'true' and '$(EcmaMetadataSupport)' == 'true'">
<ProjectReference Include="..\..\System.Private.TypeLoader\src\System.Private.TypeLoader.Experimental.csproj" />
+ <ProjectReference Include="..\..\System.Private.Interop\src\System.Private.Interop.Experimental.csproj" />
<ReferencePath Include="$(AotPackageReferencePath)\System.Private.Reflection.Metadata.Ecma335.dll" />
</ItemGroup>
<ItemGroup Condition="'$(EcmaMetadataSupport)' == 'true'">
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/QueriedMemberList.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/QueriedMemberList.cs
index c8e7d3a23..2da7ffe58 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/QueriedMemberList.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/BindingFlagSupport/QueriedMemberList.cs
@@ -30,13 +30,13 @@ namespace System.Reflection.Runtime.BindingFlagSupport
_allFlagsThatMustMatch = new BindingFlags[Grow];
}
- private QueriedMemberList(int totalCount, int declaredOnlyCount, M[] members, BindingFlags[] allFlagsThatMustMatch, RuntimeTypeInfo typeThatBlockedBrowing)
+ private QueriedMemberList(int totalCount, int declaredOnlyCount, M[] members, BindingFlags[] allFlagsThatMustMatch, RuntimeTypeInfo typeThatBlockedBrowsing)
{
_totalCount = totalCount;
_declaredOnlyCount = declaredOnlyCount;
_members = members;
_allFlagsThatMustMatch = allFlagsThatMustMatch;
- _typeThatBlockedBrowsing = typeThatBlockedBrowing;
+ _typeThatBlockedBrowsing = typeThatBlockedBrowsing;
}
/// <summary>
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Dispensers.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Dispensers.cs
index 79eca8868..90d5f4803 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Dispensers.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/Dispensers.cs
@@ -97,7 +97,7 @@ namespace System.Reflection.Runtime.Assemblies
AssemblyBinder binder = ReflectionCoreExecution.ExecutionDomain.ReflectionDomainSetup.AssemblyBinder;
AssemblyBindResult bindResult;
Exception exception;
- if (!binder.Bind(assemblyRefName, out bindResult, out exception))
+ if (!binder.Bind(assemblyRefName, cacheMissedLookups: true, out bindResult, out exception))
return exception;
return GetRuntimeAssembly(bindResult);
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/EcmaFormat/DefaultValueProcessing.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/EcmaFormat/DefaultValueProcessing.cs
index 50196d699..70b020393 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/EcmaFormat/DefaultValueProcessing.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/EcmaFormat/DefaultValueProcessing.cs
@@ -60,7 +60,7 @@ namespace System.Reflection.Runtime.General.EcmaFormat
private static object ConstantValueAsObject(ConstantHandle constantHandle, MetadataReader metadataReader, Type declaredType, bool raw)
{
object defaultValue = ConstantValueAsRawObject(constantHandle, metadataReader);
- if ((!raw) && declaredType.IsEnum)
+ if ((!raw) && declaredType.IsEnum && defaultValue != null)
defaultValue = Enum.ToObject(declaredType, defaultValue);
return defaultValue;
}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/MetadataReaderExtensions.NativeFormat.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/MetadataReaderExtensions.NativeFormat.cs
index 901d0f4ba..5896aa812 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/MetadataReaderExtensions.NativeFormat.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/MetadataReaderExtensions.NativeFormat.cs
@@ -162,6 +162,24 @@ namespace System.Reflection.Runtime.General
return customModifiers.ToArray();
}
+ public static Handle SkipCustomModifiers(this Handle handle, MetadataReader reader)
+ {
+ HandleType handleType = handle.HandleType;
+ Debug.Assert(handleType == HandleType.TypeDefinition || handleType == HandleType.TypeReference || handleType == HandleType.TypeSpecification || handleType == HandleType.ModifiedType);
+ if (handleType != HandleType.ModifiedType)
+ return handle;
+
+ do
+ {
+ ModifiedType modifiedType = handle.ToModifiedTypeHandle(reader).GetModifiedType(reader);
+ handle = modifiedType.Type;
+ handleType = handle.HandleType;
+ }
+ while (handleType == HandleType.ModifiedType);
+
+ return handle;
+ }
+
public static MethodSignature ParseMethodSignature(this Handle handle, MetadataReader reader)
{
return handle.ToMethodSignatureHandle(reader).GetMethodSignature(reader);
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NativeFormat/DefaultValueParser.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NativeFormat/DefaultValueParser.cs
index e76be1914..244d351ad 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NativeFormat/DefaultValueParser.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/General/NativeFormat/DefaultValueParser.cs
@@ -14,7 +14,7 @@ namespace System.Reflection.Runtime.General.NativeFormat
if (!(constantHandle.IsNull(reader)))
{
defaultValue = constantHandle.ParseConstantValue(reader);
- if ((!raw) && declaredType.IsEnum)
+ if ((!raw) && declaredType.IsEnum && defaultValue != null)
defaultValue = Enum.ToObject(declaredType, defaultValue);
return true;
}
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs
index 33d73b16a..4af12bfc9 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/MethodInfos/RuntimeMethodInfo.cs
@@ -354,7 +354,12 @@ namespace System.Reflection.Runtime.MethodInfos
if (methodInvoker == null)
{
if (ReturnType.IsByRef)
- throw new NotSupportedException(SR.NotSupported_ByRefReturn);
+ {
+ // The invoker is going to dereference and box (for structs) the result of the invocation
+ // on behalf of the caller. Can't box byref-like types and can't box void.
+ if (ReturnType.GetElementType().IsByRefLike || ReturnType.GetElementType() == CommonRuntimeTypes.Void)
+ throw new NotSupportedException();
+ }
methodInvoker = _lazyMethodInvoker = this.UncachedMethodInvoker;
}
return methodInvoker;
diff --git a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs
index 678577135..f027f9caa 100644
--- a/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs
+++ b/src/System.Private.Reflection.Core/src/System/Reflection/Runtime/TypeInfos/NativeFormat/NativeFormatRuntimeGenericParameterTypeInfo.cs
@@ -81,7 +81,11 @@ namespace System.Reflection.Runtime.TypeInfos.NativeFormat
LowLevelList<QTypeDefRefOrSpec> constraints = new LowLevelList<QTypeDefRefOrSpec>();
foreach (Handle constraintHandle in _genericParameter.Constraints)
{
- constraints.Add(new QTypeDefRefOrSpec(reader, constraintHandle));
+ // We're skipping custom modifiers here because Roslyn generates
+ // a modifier for the "unmanaged" constraint. This doesn't conform to the
+ // ECMA-335 spec, but we need to deal with it. The modifier is not visible
+ // to reflection.
+ constraints.Add(new QTypeDefRefOrSpec(reader, constraintHandle.SkipCustomModifiers(reader)));
}
return constraints.ToArray();
}
diff --git a/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs b/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs
index b583053d4..8313fbe31 100644
--- a/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs
+++ b/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs
@@ -44,10 +44,6 @@ namespace Internal.Reflection.Execution
//==========================================================================================================
internal sealed partial class ExecutionEnvironmentImplementation : ExecutionEnvironment
{
- private struct MethodTargetAndDictionary { public IntPtr TargetPointer; public IntPtr DictionaryPointer; }
-
- private LowLevelDictionary<IntPtr, MethodTargetAndDictionary> _callConverterWrappedMethodEntrypoints = new LowLevelDictionary<IntPtr, MethodTargetAndDictionary>();
-
private RuntimeTypeHandle GetOpenTypeDefinition(RuntimeTypeHandle typeHandle, out RuntimeTypeHandle[] typeArgumentsHandles)
{
if (RuntimeAugments.IsGenericType(typeHandle))
@@ -475,27 +471,17 @@ namespace Internal.Reflection.Execution
}
}
- private IntPtr GetDynamicMethodInvokerThunk(RuntimeTypeHandle[] argHandles, MethodBase methodInfo)
+ private IntPtr GetDynamicMethodInvokerThunk(MethodBase methodInfo)
{
- ParameterInfo[] parameters = methodInfo.GetParametersNoCopy();
- // last entry in argHandles is the return type if the type is not typeof(void)
- Debug.Assert(parameters.Length == argHandles.Length || parameters.Length == (argHandles.Length - 1));
-
- bool[] byRefParameters = new bool[parameters.Length + 1];
- RuntimeTypeHandle[] parameterTypeHandles = new RuntimeTypeHandle[parameters.Length + 1];
-
- // This is either a constructor ("returns" void) or an instance method
- MethodInfo reflectionMethodInfo = methodInfo as MethodInfo;
- parameterTypeHandles[0] = (reflectionMethodInfo != null ? reflectionMethodInfo.ReturnType.TypeHandle : CommonRuntimeTypes.Void.TypeHandle);
- byRefParameters[0] = false;
-
- for (int i = 0; i < parameters.Length; i++)
- {
- parameterTypeHandles[i + 1] = argHandles[i];
- byRefParameters[i + 1] = parameters[i].ParameterType.IsByRef;
- }
-
- return CallConverterThunk.MakeThunk(ThunkKind.ReflectionDynamicInvokeThunk, IntPtr.Zero, IntPtr.Zero, false, parameterTypeHandles, byRefParameters, null);
+ MethodParametersInfo methodParamsInfo = new MethodParametersInfo(methodInfo);
+ return CallConverterThunk.MakeThunk(
+ ThunkKind.ReflectionDynamicInvokeThunk,
+ IntPtr.Zero,
+ IntPtr.Zero,
+ false,
+ methodParamsInfo.ReturnTypeAndParameterTypeHandles.ToArray(),
+ methodParamsInfo.ReturnTypeAndParametersByRefFlags,
+ null);
}
private RuntimeTypeHandle[] GetDynamicInvokeInstantiationArguments(MethodBase reflectionMethodBase)
@@ -514,6 +500,17 @@ namespace Internal.Reflection.Execution
if (!returnType.Equals(CommonRuntimeTypes.Void))
dynamicInvokeMethodGenArguments.Add(returnType.TypeHandle);
+ for (int i = 0; i < dynamicInvokeMethodGenArguments.Count; i++)
+ {
+ // We can't instantiate over pointer types, so the DynamicInvoke method compensates for it already.
+ RuntimeTypeHandle type = dynamicInvokeMethodGenArguments[i];
+ while (RuntimeAugments.IsUnmanagedPointerType(type))
+ {
+ type = RuntimeAugments.GetRelatedParameterTypeHandle(type);
+ }
+ dynamicInvokeMethodGenArguments[i] = type;
+ }
+
return dynamicInvokeMethodGenArguments.ToArray();
}
@@ -603,33 +600,17 @@ namespace Internal.Reflection.Execution
methodHandle.NativeFormatHandle);
}
- if (methodInvokeMetadata.MethodEntryPoint != methodInvokeMetadata.RawMethodEntryPoint &&
- !FunctionPointerOps.IsGenericMethodPointer(methodInvokeMetadata.MethodEntryPoint))
- {
- // Keep track of the raw method entrypoints for the cases where they get wrapped into a calling convention converter thunk.
- // This is needed for reverse lookups, like in TryGetMethodForOriginalLdFtnResult
- Debug.Assert(canonFormKind == CanonicalFormKind.Universal);
- lock (_callConverterWrappedMethodEntrypoints)
- {
- _callConverterWrappedMethodEntrypoints.LookupOrAdd(methodInvokeMetadata.MethodEntryPoint, new MethodTargetAndDictionary
- {
- TargetPointer = methodInvokeMetadata.RawMethodEntryPoint,
- DictionaryPointer = methodInvokeMetadata.DictionaryComponent
- });
- }
- }
-
- RuntimeTypeHandle[] dynInvokeMethodArgs = GetDynamicInvokeInstantiationArguments(methodInfo);
-
IntPtr dynamicInvokeMethod;
IntPtr dynamicInvokeMethodGenericDictionary;
if ((methodInvokeMetadata.InvokeTableFlags & InvokeTableFlags.NeedsParameterInterpretation) != 0)
{
- dynamicInvokeMethod = GetDynamicMethodInvokerThunk(dynInvokeMethodArgs, methodInfo);
+ dynamicInvokeMethod = GetDynamicMethodInvokerThunk(methodInfo);
dynamicInvokeMethodGenericDictionary = IntPtr.Zero;
}
else
{
+ RuntimeTypeHandle[] dynInvokeMethodArgs = GetDynamicInvokeInstantiationArguments(methodInfo);
+
GetDynamicMethodInvokeMethodInfo(
methodInvokeMetadata.MappingTableModule,
methodInvokeMetadata.DynamicInvokeCookie,
@@ -913,53 +894,87 @@ namespace Internal.Reflection.Execution
}
else
{
- bool isCallConverterWrappedEntrypoint;
- MethodTargetAndDictionary callConverterWrappedEntrypoint;
- lock (_callConverterWrappedMethodEntrypoints)
+ // The thunk could have been created by the TypeLoader as a dictionary slot for USG code
+ if (!CallConverterThunk.TryGetCallConversionTargetPointerAndInstantiatingArg(originalLdFtnResult, out canonOriginalLdFtnResult, out instantiationArgument))
{
- isCallConverterWrappedEntrypoint = _callConverterWrappedMethodEntrypoints.TryGetValue(originalLdFtnResult, out callConverterWrappedEntrypoint);
+ canonOriginalLdFtnResult = RuntimeAugments.GetCodeTarget(originalLdFtnResult);
+ instantiationArgument = IntPtr.Zero;
}
+ }
+ }
- if (isCallConverterWrappedEntrypoint)
+ internal bool TryGetMethodForOriginalLdFtnResult(IntPtr originalLdFtnResult, ref RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles)
+ {
+ GetFunctionPointerAndInstantiationArgumentForOriginalLdFtnResult(originalLdFtnResult, out IntPtr canonOriginalLdFtnResult, out IntPtr instantiationArgument);
+
+ if (instantiationArgument != IntPtr.Zero)
+ {
+ // Search TemplateMethodMap
+ if (TryGetMethodForOriginalLdFtnResult_GenericMethodWithInstantiationArgument(instantiationArgument, ref declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles))
+ return true;
+ }
+ else
+ {
+ // Search ExactInstantiationsMap
+ foreach (KeyValuePair<NativeFormatModuleInfo, FunctionPointersToOffsets> perModuleLookup in GetLdFtnReverseLookups_ExactInstantations())
{
- canonOriginalLdFtnResult = callConverterWrappedEntrypoint.TargetPointer;
- instantiationArgument = callConverterWrappedEntrypoint.DictionaryPointer;
+ int startIndex;
+ int endIndex;
+
+ if (perModuleLookup.Value.TryGetOffsetsRange(canonOriginalLdFtnResult, out startIndex, out endIndex))
+ {
+ for (int curIndex = startIndex; curIndex <= endIndex; curIndex++)
+ {
+ uint parserOffset = perModuleLookup.Value.Data[curIndex].Offset;
+ if (TryGetMethodForOriginalLdFtnResult_ExactInstantiation_Inner(perModuleLookup.Key, forStartAddress: false, canonOriginalLdFtnResult, parserOffset,
+ ref declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles))
+ return true;
+ }
+ }
}
- else
+ }
+
+ // Search InvokeMap
+ foreach (KeyValuePair<NativeFormatModuleInfo, FunctionPointersToOffsets> perModuleLookup in GetLdFtnReverseLookups_InvokeMap())
+ {
+ int startIndex;
+ int endIndex;
+
+ if (perModuleLookup.Value.TryGetOffsetsRange(canonOriginalLdFtnResult, out startIndex, out endIndex))
{
- // The thunk could have been created by the TypeLoader as a dictionary slot for USG code
- if (!CallConverterThunk.TryGetCallConversionTargetPointerAndInstantiatingArg(originalLdFtnResult, out canonOriginalLdFtnResult, out instantiationArgument))
+ for (int curIndex = startIndex; curIndex <= endIndex; curIndex++)
{
- canonOriginalLdFtnResult = RuntimeAugments.GetCodeTarget(originalLdFtnResult);
- instantiationArgument = IntPtr.Zero;
+ uint parserOffset = perModuleLookup.Value.Data[curIndex].Offset;
+ if (TryGetMethodForOriginalLdFtnResult_InvokeMap_Inner(perModuleLookup.Key, forStartAddress: false, canonOriginalLdFtnResult, instantiationArgument, parserOffset, ref declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles))
+ return true;
}
}
}
+
+ methodHandle = default(QMethodDefinition);
+ genericMethodTypeArgumentHandles = null;
+ return false;
}
- internal bool TryGetMethodForOriginalLdFtnResult(IntPtr originalLdFtnResult, ref RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles)
+ internal bool TryGetMethodForStartAddress(IntPtr methodStartAddress, ref RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle)
{
- GetFunctionPointerAndInstantiationArgumentForOriginalLdFtnResult(originalLdFtnResult, out IntPtr canonOriginalLdFtnResult, out IntPtr instantiationArgument);
-
- // Search TemplateMethodMap
- if ((instantiationArgument != IntPtr.Zero) && TryGetMethodForOriginalLdFtnResult_GenericMethodWithInstantiationArgument(instantiationArgument, ref declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles))
- {
- return true;
- }
-
// Search ExactInstantiationsMap
foreach (KeyValuePair<NativeFormatModuleInfo, FunctionPointersToOffsets> perModuleLookup in GetLdFtnReverseLookups_ExactInstantations())
{
int startIndex;
int endIndex;
- if (perModuleLookup.Value.TryGetOffsetsRange(canonOriginalLdFtnResult, out startIndex, out endIndex))
+ if (perModuleLookup.Value.TryGetOffsetsRange(methodStartAddress, out startIndex, out endIndex))
{
for (int curIndex = startIndex; curIndex <= endIndex; curIndex++)
{
uint parserOffset = perModuleLookup.Value.Data[curIndex].Offset;
- if (TryGetMethodForOriginalLdFtnResult_ExactInstantiation_Inner(perModuleLookup.Key, canonOriginalLdFtnResult, instantiationArgument, parserOffset, ref declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles))
+ if (TryGetMethodForOriginalLdFtnResult_ExactInstantiation_Inner(perModuleLookup.Key, forStartAddress: true, methodStartAddress, parserOffset, ref declaringTypeHandle, out methodHandle, out _))
+ {
+ if (RuntimeAugments.IsGenericType(declaringTypeHandle))
+ declaringTypeHandle = RuntimeAugments.GetGenericDefinition(declaringTypeHandle);
return true;
+ }
}
}
}
@@ -970,19 +985,22 @@ namespace Internal.Reflection.Execution
int startIndex;
int endIndex;
- if (perModuleLookup.Value.TryGetOffsetsRange(canonOriginalLdFtnResult, out startIndex, out endIndex))
+ if (perModuleLookup.Value.TryGetOffsetsRange(methodStartAddress, out startIndex, out endIndex))
{
for (int curIndex = startIndex; curIndex <= endIndex; curIndex++)
{
uint parserOffset = perModuleLookup.Value.Data[curIndex].Offset;
- if (TryGetMethodForOriginalLdFtnResult_InvokeMap_Inner(perModuleLookup.Key, canonOriginalLdFtnResult, instantiationArgument, parserOffset, ref declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles))
+ if (TryGetMethodForOriginalLdFtnResult_InvokeMap_Inner(perModuleLookup.Key, forStartAddress: true, methodStartAddress, IntPtr.Zero, parserOffset, ref declaringTypeHandle, out methodHandle, out _))
+ {
+ if (RuntimeAugments.IsGenericType(declaringTypeHandle))
+ declaringTypeHandle = RuntimeAugments.GetGenericDefinition(declaringTypeHandle);
return true;
+ }
}
}
}
methodHandle = default(QMethodDefinition);
- genericMethodTypeArgumentHandles = null;
return false;
}
@@ -1047,7 +1065,7 @@ namespace Internal.Reflection.Execution
return functionPointerToOffsetInInvokeMap;
}
- private unsafe bool TryGetMethodForOriginalLdFtnResult_InvokeMap_Inner(NativeFormatModuleInfo mappingTableModule, IntPtr canonOriginalLdFtnResult, IntPtr instantiationArgument, uint parserOffset, ref RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles)
+ private unsafe bool TryGetMethodForOriginalLdFtnResult_InvokeMap_Inner(NativeFormatModuleInfo mappingTableModule, bool forStartAddress, IntPtr canonOriginalLdFtnResult, IntPtr instantiationArgument, uint parserOffset, ref RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles)
{
methodHandle = default(QMethodDefinition);
genericMethodTypeArgumentHandles = null;
@@ -1069,7 +1087,7 @@ namespace Internal.Reflection.Execution
// If the passed in method was a fat function pointer, but the entry in the mapping table doesn't need
// an instantiation argument (or the other way around), trivially reject it.
- if ((instantiationArgument == IntPtr.Zero) != ((entryFlags & InvokeTableFlags.RequiresInstArg) == 0))
+ if (!forStartAddress && ((instantiationArgument == IntPtr.Zero) != ((entryFlags & InvokeTableFlags.RequiresInstArg) == 0)))
return false;
Debug.Assert((entryFlags & InvokeTableFlags.HasEntrypoint) != 0);
@@ -1080,39 +1098,46 @@ namespace Internal.Reflection.Execution
IntPtr entryMethodEntrypoint = externalReferences.GetFunctionPointerFromIndex(entryParser.GetUnsigned());
if ((entryFlags & InvokeTableFlags.NeedsParameterInterpretation) == 0)
- entryParser.GetUnsigned(); // skip dynamic invoke cookie
+ entryParser.SkipInteger(); // skip dynamic invoke cookie
+ if (forStartAddress)
+ {
+ declaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryDeclaringTypeRaw);
+ }
+ else
+ {
#if DEBUG
- IntPtr targetAddress;
- Debug.Assert(entryMethodEntrypoint == canonOriginalLdFtnResult ||
- RuntimeAugments.GetCodeTarget(entryMethodEntrypoint) == canonOriginalLdFtnResult ||
- TypeLoaderEnvironment.TryGetTargetOfUnboxingAndInstantiatingStub(entryMethodEntrypoint, out targetAddress) &&
- targetAddress == canonOriginalLdFtnResult);
+ IntPtr targetAddress;
+ Debug.Assert(entryMethodEntrypoint == canonOriginalLdFtnResult ||
+ RuntimeAugments.GetCodeTarget(entryMethodEntrypoint) == canonOriginalLdFtnResult ||
+ TypeLoaderEnvironment.TryGetTargetOfUnboxingAndInstantiatingStub(entryMethodEntrypoint, out targetAddress) &&
+ targetAddress == canonOriginalLdFtnResult);
#endif
- if ((entryFlags & InvokeTableFlags.RequiresInstArg) == 0 && declaringTypeHandle.IsNull())
- declaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryDeclaringTypeRaw);
+ if ((entryFlags & InvokeTableFlags.RequiresInstArg) == 0 && declaringTypeHandle.IsNull())
+ declaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryDeclaringTypeRaw);
- if ((entryFlags & InvokeTableFlags.IsGenericMethod) != 0)
- {
- if ((entryFlags & InvokeTableFlags.RequiresInstArg) != 0)
+ if ((entryFlags & InvokeTableFlags.IsGenericMethod) != 0)
{
- MethodNameAndSignature dummyNameAndSignature;
- bool success = TypeLoaderEnvironment.Instance.TryGetGenericMethodComponents(instantiationArgument, out declaringTypeHandle, out dummyNameAndSignature, out genericMethodTypeArgumentHandles);
- Debug.Assert(success);
+ if ((entryFlags & InvokeTableFlags.RequiresInstArg) != 0)
+ {
+ MethodNameAndSignature dummyNameAndSignature;
+ bool success = TypeLoaderEnvironment.Instance.TryGetGenericMethodComponents(instantiationArgument, out declaringTypeHandle, out dummyNameAndSignature, out genericMethodTypeArgumentHandles);
+ Debug.Assert(success);
+ }
+ else
+ genericMethodTypeArgumentHandles = GetTypeSequence(ref externalReferences, ref entryParser);
}
else
- genericMethodTypeArgumentHandles = GetTypeSequence(ref externalReferences, ref entryParser);
- }
- else
- {
- genericMethodTypeArgumentHandles = null;
- if ((entryFlags & InvokeTableFlags.RequiresInstArg) != 0)
- declaringTypeHandle = RuntimeAugments.CreateRuntimeTypeHandle(instantiationArgument);
- }
+ {
+ genericMethodTypeArgumentHandles = null;
+ if ((entryFlags & InvokeTableFlags.RequiresInstArg) != 0)
+ declaringTypeHandle = RuntimeAugments.CreateRuntimeTypeHandle(instantiationArgument);
+ }
- RuntimeTypeHandle entryType = externalReferences.GetRuntimeTypeHandleFromIndex(entryDeclaringTypeRaw);
- declaringTypeHandle = GetExactDeclaringType(entryType, declaringTypeHandle);
+ RuntimeTypeHandle entryType = externalReferences.GetRuntimeTypeHandleFromIndex(entryDeclaringTypeRaw);
+ declaringTypeHandle = GetExactDeclaringType(entryType, declaringTypeHandle);
+ }
if ((entryFlags & InvokeTableFlags.HasMetadataHandle) != 0)
{
@@ -1173,17 +1198,17 @@ namespace Internal.Reflection.Execution
uint parserOffset = entryParser.Offset;
// Declaring Handle
- entryParser.GetUnsigned();
+ entryParser.SkipInteger();
// NameAndSig
- entryParser.GetUnsigned();
+ entryParser.SkipInteger();
// generic method arity
int parsedArity = (int)entryParser.GetSequenceCount();
for (int i = 0; i < parsedArity; i++)
{
- entryParser.GetUnsigned();
+ entryParser.SkipInteger();
}
IntPtr functionPointer = externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned());
@@ -1196,14 +1221,11 @@ namespace Internal.Reflection.Execution
return functionPointerToOffsetInInvokeMap;
}
- private unsafe bool TryGetMethodForOriginalLdFtnResult_ExactInstantiation_Inner(NativeFormatModuleInfo mappingTableModule, IntPtr canonOriginalLdFtnResult, IntPtr instantiationArgument, uint parserOffset, ref RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles)
+ private unsafe bool TryGetMethodForOriginalLdFtnResult_ExactInstantiation_Inner(NativeFormatModuleInfo mappingTableModule, bool forStartAddress, IntPtr canonOriginalLdFtnResult, uint parserOffset, ref RuntimeTypeHandle declaringTypeHandle, out QMethodDefinition methodHandle, out RuntimeTypeHandle[] genericMethodTypeArgumentHandles)
{
methodHandle = default(QMethodDefinition);
genericMethodTypeArgumentHandles = null;
- if (instantiationArgument != IntPtr.Zero)
- return false;
-
NativeReader invokeMapReader;
if (!TryGetNativeReaderForBlob(mappingTableModule, ReflectionMapBlob.ExactMethodInstantiationsHashtable, out invokeMapReader))
{
@@ -1225,11 +1247,22 @@ namespace Internal.Reflection.Execution
return false;
int parsedArity = (int)entryParser.GetSequenceCount();
- genericMethodTypeArgumentHandles = new RuntimeTypeHandle[parsedArity];
- for (int i = 0; i < parsedArity; i++)
+ if (forStartAddress)
+ {
+ for (int i = 0; i < parsedArity; i++)
+ {
+ entryParser.SkipInteger();
+ }
+ }
+ else
{
- genericMethodTypeArgumentHandles[i] = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
+ genericMethodTypeArgumentHandles = new RuntimeTypeHandle[parsedArity];
+
+ for (int i = 0; i < parsedArity; i++)
+ {
+ genericMethodTypeArgumentHandles[i] = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
+ }
}
IntPtr functionPointer = externalReferences.GetIntPtrFromIndex(entryParser.GetUnsigned());
@@ -1486,10 +1519,7 @@ namespace Internal.Reflection.Execution
{
Type parameterType = parameters[i].ParameterType;
- // If the parameter is a pointer type, use IntPtr. Else use the actual parameter type.
- if (parameterType.IsPointer)
- result.Add(CommonRuntimeTypes.IntPtr.TypeHandle);
- else if (parameterType.IsByRef)
+ if (parameterType.IsByRef)
result.Add(parameterType.GetElementType().TypeHandle);
else if (parameterType.GetTypeInfo().IsEnum && !parameters[i].HasDefaultValue)
result.Add(Enum.GetUnderlyingType(parameterType).TypeHandle);
@@ -1509,6 +1539,8 @@ namespace Internal.Reflection.Execution
MethodInfo reflectionMethodInfo = _methodBase as MethodInfo;
Type returnType = reflectionMethodInfo != null ? reflectionMethodInfo.ReturnType : CommonRuntimeTypes.Void;
+ if (returnType.IsByRef)
+ returnType = returnType.GetElementType();
result.Insert(0, returnType.TypeHandle);
return result;
diff --git a/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecution.cs b/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecution.cs
index d2135fd08..c8b4a019e 100644
--- a/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecution.cs
+++ b/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecution.cs
@@ -64,10 +64,6 @@ namespace Internal.Reflection.Execution
};
ExecutionEnvironment = executionEnvironment;
-
-#if SUPPORT_JIT
- Internal.Runtime.TypeLoader.MethodExecutionStrategy.GlobalExecutionStrategy = new Internal.Runtime.JitSupport.RyuJitExecutionStrategy();
-#endif
}
//
@@ -98,16 +94,13 @@ namespace Internal.Reflection.Execution
methodHandle = default(MethodHandle);
RuntimeTypeHandle declaringTypeHandle = default(RuntimeTypeHandle);
- if (!ExecutionEnvironment.TryGetMethodForOriginalLdFtnResult(methodStartAddress,
- ref declaringTypeHandle, out QMethodDefinition qMethodDefinition, out _))
+ if (!ExecutionEnvironment.TryGetMethodForStartAddress(methodStartAddress,
+ ref declaringTypeHandle, out QMethodDefinition qMethodDefinition))
return false;
if (!qMethodDefinition.IsNativeFormatMetadataBased)
return false;
- if (RuntimeAugments.IsGenericType(declaringTypeHandle))
- declaringTypeHandle = RuntimeAugments.GetGenericDefinition(declaringTypeHandle);
-
if (!ExecutionEnvironment.TryGetMetadataForNamedType(declaringTypeHandle, out QTypeDefinition qTypeDefinition))
return false;
diff --git a/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecutionDomainCallbacksImplementation.cs b/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecutionDomainCallbacksImplementation.cs
index 1a004f50d..b6ba92e2b 100644
--- a/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecutionDomainCallbacksImplementation.cs
+++ b/src/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ReflectionExecutionDomainCallbacksImplementation.cs
@@ -104,18 +104,12 @@ namespace Internal.Reflection.Execution
{
RuntimeTypeHandle declaringTypeHandle = default(RuntimeTypeHandle);
QMethodDefinition methodHandle;
- RuntimeTypeHandle[] genericMethodTypeArgumentHandles;
- if (!ReflectionExecution.ExecutionEnvironment.TryGetMethodForOriginalLdFtnResult(methodStartAddress,
- ref declaringTypeHandle, out methodHandle, out genericMethodTypeArgumentHandles))
+ if (!ReflectionExecution.ExecutionEnvironment.TryGetMethodForStartAddress(methodStartAddress,
+ ref declaringTypeHandle, out methodHandle))
{
return null;
}
- if (RuntimeAugments.IsGenericType(declaringTypeHandle))
- {
- declaringTypeHandle = RuntimeAugments.GetGenericDefinition(declaringTypeHandle);
- }
-
// We don't use the type argument handles as we want the uninstantiated method info
return ReflectionCoreExecution.ExecutionDomain.GetMethod(declaringTypeHandle, methodHandle, genericMethodTypeArgumentHandles: null);
}
diff --git a/src/System.Private.Reflection.Execution/src/Resources/Strings.resx b/src/System.Private.Reflection.Execution/src/Resources/Strings.resx
index f03a830ef..0a8ef5f1b 100644
--- a/src/System.Private.Reflection.Execution/src/Resources/Strings.resx
+++ b/src/System.Private.Reflection.Execution/src/Resources/Strings.resx
@@ -141,30 +141,9 @@
<data name="InvalidOperation_NoValue" xml:space="preserve">
<value>Nullable object must have a value.</value>
</data>
- <data name="PlatformNotSupported_CantInvokeIntrinsic" xml:space="preserve">
- <value>Late-bound invocation is not supported for compiler-intrinsic methods.</value>
- </data>
- <data name="PlatformNotSupported_VarArgs" xml:space="preserve">
- <value>Methods using the vararg calling convention are not supported on this platform.</value>
- </data>
- <data name="PlatformNotSupported_PointerArguments" xml:space="preserve">
- <value>Passing or returning pointers through Invoke is not supported on this platform.</value>
- </data>
<data name="RFLCT_Targ_StatFldReqTarg" xml:space="preserve">
<value>Non-static field requires a target.</value>
</data>
- <data name="LdToken_NoMetadata_1" xml:space="preserve">
- <value>Prerelease Restriction: The following type member cannot be referenced from inside a Linq Expression:\n\n </value>
- </data>
- <data name="LdToken_NoMetadata_2" xml:space="preserve">
- <value>\n\nThe following may be used as a workaround:\n\n</value>
- </data>
- <data name="LdToken_NoMetadata_3" xml:space="preserve">
- <value> 1. Make the member public or mark the member with the System.Reflection.Metadata.Controls.ReflectionInfo attribute specifying the argument ReflectionInfoOption.Include\n</value>
- </data>
- <data name="LdToken_NoMetadata_4" xml:space="preserve">
- <value> 2. Enable Reflection for its declaring type with the System.Reflection.Consumption.EnableDynamicProgramming attribute.\n\n\n</value>
- </data>
<data name="MissingConstructor_Name" xml:space="preserve">
<value>Constructor on type '{0}' not found.</value>
</data>
@@ -192,9 +171,6 @@
<data name="Argument_ConstraintFailed" xml:space="preserve">
<value>'{0}', on '{1}' violates the constraint of type '{2}'.</value>
</data>
- <data name="PlatformNotSupported_GetMethodInfoForStubDelegate" xml:space="preserve">
- <value>Obtaining a MethodInfo of a reflection-constructed delegate to a virtual method is not supported on this platform.</value>
- </data>
<data name="Argument_ImplementIComparable" xml:space="preserve">
<value>At least one object must implement IComparable.</value>
</data>
diff --git a/src/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.Experimental.csproj b/src/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.Experimental.csproj
index 069aa60a9..d70b8fc7a 100644
--- a/src/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.Experimental.csproj
+++ b/src/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.Experimental.csproj
@@ -2,7 +2,7 @@
<PropertyGroup>
<AssemblyName>System.Private.Reflection.Execution.Experimental</AssemblyName>
<EcmaMetadataSupport>true</EcmaMetadataSupport>
- <JitSupport>true</JitSupport>
+ <DynamicCodeSupport>true</DynamicCodeSupport>
</PropertyGroup>
<Import Project="System.Private.Reflection.Execution.csproj" />
diff --git a/src/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj b/src/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj
index 5b935ef32..ed737d170 100644
--- a/src/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj
+++ b/src/System.Private.Reflection.Execution/src/System.Private.Reflection.Execution.csproj
@@ -13,9 +13,6 @@
<PropertyGroup Condition="'$(EcmaMetadataSupport)' == 'true'">
<DefineConstants>ECMA_METADATA_SUPPORT;$(DefineConstants)</DefineConstants>
</PropertyGroup>
- <PropertyGroup Condition="'$(JitSupport)' == 'true'">
- <DefineConstants>SUPPORT_JIT;$(DefineConstants)</DefineConstants>
- </PropertyGroup>
<!-- Setup the right references -->
<ItemGroup>
@@ -28,17 +25,18 @@
<Aliases>global,System_Private_CoreLib</Aliases>
</ProjectReference>
<ProjectReference Include="..\..\System.Private.Reflection.Metadata\src\System.Private.Reflection.Metadata.csproj" />
-
- <ProjectReference Include="..\..\System.Private.Interop\src\System.Private.Interop.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(IsProjectNLibrary)' != 'true' and '$(EcmaMetadataSupport)' != 'true'">
+ <ProjectReference Include="..\..\System.Private.Interop\src\System.Private.Interop.csproj" />
<ProjectReference Include="..\..\System.Private.TypeLoader\src\System.Private.TypeLoader.csproj" />
<ProjectReference Include="..\..\System.Private.Reflection.Core\src\System.Private.Reflection.Core.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(IsProjectNLibrary)' != 'true' and '$(EcmaMetadataSupport)' == 'true'">
+ <ProjectReference Include="..\..\System.Private.Interop\src\System.Private.Interop.Experimental.csproj" />
<ProjectReference Include="..\..\System.Private.TypeLoader\src\System.Private.TypeLoader.Experimental.csproj" />
<ProjectReference Include="..\..\System.Private.Reflection.Core\src\System.Private.Reflection.Core.Experimental.csproj" />
<ProjectReference Include="..\..\System.Private.Jit\src\System.Private.Jit.csproj" />
+ <ProjectReference Include="..\..\System.Private.Interpreter\src\System.Private.Interpreter.csproj" />
</ItemGroup>
<PropertyGroup>
@@ -95,7 +93,6 @@
<Compile Include="Internal\Reflection\Extensions\NonPortable\DelegateMethodInfoRetriever.cs" />
<Compile Include="Internal\Runtime\CompilerHelpers\LibraryInitializer.cs" />
<Compile Include="System\Reflection\MissingRuntimeArtifactException.cs" />
-
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\Common\src\Internal\Runtime\MetadataBlob.cs" >
diff --git a/src/System.Private.Reflection.Metadata/tests/System.Private.Reflection.Metadata.Tests.csproj b/src/System.Private.Reflection.Metadata/tests/System.Private.Reflection.Metadata.Tests.csproj
index 17e544899..08994fa92 100644
--- a/src/System.Private.Reflection.Metadata/tests/System.Private.Reflection.Metadata.Tests.csproj
+++ b/src/System.Private.Reflection.Metadata/tests/System.Private.Reflection.Metadata.Tests.csproj
@@ -6,7 +6,7 @@
<AssemblyName>System.Private.Reflection.Metadata.Tests</AssemblyName>
<RootNamespace>System.Private.Reflection.Metadata.Tests</RootNamespace>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
- <TargetFramework>netstandard1.3</TargetFramework>
+ <TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<NativeFormatCommonPath>..\..\Common\src\Internal\NativeFormat</NativeFormatCommonPath>
@@ -26,8 +26,11 @@
<Compile Include="$(MetadataCommonPath)\NativeFormatReaderGen.cs" />
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.DotNet.BuildTools.TestSuite">
- <Version>$(XunitNetcoreExtensionsVersion)</Version>
+ <PackageReference Include="xunit">
+ <Version>$(XUnitPackageVersion)</Version>
+ </PackageReference>
+ <PackageReference Include="Microsoft.DotNet.XUnitExtensions">
+ <Version>$(MicrosoftDotNetXUnitExtensionsVersion)</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
diff --git a/src/System.Private.StackTraceMetadata/src/System.Private.StackTraceMetadata.Experimental.csproj b/src/System.Private.StackTraceMetadata/src/System.Private.StackTraceMetadata.Experimental.csproj
new file mode 100644
index 000000000..637480fcb
--- /dev/null
+++ b/src/System.Private.StackTraceMetadata/src/System.Private.StackTraceMetadata.Experimental.csproj
@@ -0,0 +1,8 @@
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+ <PropertyGroup>
+ <AssemblyName>System.Private.StackTraceMetadata.Experimental</AssemblyName>
+ <DynamicCodeSupport>true</DynamicCodeSupport>
+ </PropertyGroup>
+
+ <Import Project="System.Private.StackTraceMetadata.csproj" />
+</Project>
diff --git a/src/System.Private.StackTraceMetadata/src/System.Private.StackTraceMetadata.csproj b/src/System.Private.StackTraceMetadata/src/System.Private.StackTraceMetadata.csproj
index 799bc65e0..22c4b488c 100644
--- a/src/System.Private.StackTraceMetadata/src/System.Private.StackTraceMetadata.csproj
+++ b/src/System.Private.StackTraceMetadata/src/System.Private.StackTraceMetadata.csproj
@@ -1,7 +1,7 @@
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
- <AssemblyName>System.Private.StackTraceMetadata</AssemblyName>
+ <AssemblyName Condition="'$(AssemblyName)' == ''">System.Private.StackTraceMetadata</AssemblyName>
<AssemblyVersion>4.0.0.0</AssemblyVersion>
<OutputType>Library</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
@@ -11,8 +11,10 @@
<ItemGroup Condition="'$(IsProjectNLibrary)' != 'true'">
<ProjectReference Include="..\..\System.Private.CoreLib\src\System.Private.CoreLib.csproj" />
<ProjectReference Include="..\..\System.Private.Reflection.Metadata\src\System.Private.Reflection.Metadata.csproj" />
- <ProjectReference Include="..\..\System.Private.TypeLoader\src\System.Private.TypeLoader.csproj" />
- <ProjectReference Include="..\..\System.Private.Reflection.Execution\src\System.Private.Reflection.Execution.csproj" />
+ <ProjectReference Condition="'$(DynamicCodeSupport)' != 'true'" Include="..\..\System.Private.TypeLoader\src\System.Private.TypeLoader.csproj" />
+ <ProjectReference Condition="'$(DynamicCodeSupport)' != 'true'" Include="..\..\System.Private.Reflection.Execution\src\System.Private.Reflection.Execution.csproj" />
+ <ProjectReference Condition="'$(DynamicCodeSupport)' == 'true'" Include="..\..\System.Private.TypeLoader\src\System.Private.TypeLoader.Experimental.csproj" />
+ <ProjectReference Condition="'$(DynamicCodeSupport)' == 'true'" Include="..\..\System.Private.Reflection.Execution\src\System.Private.Reflection.Execution.Experimental.csproj" />
</ItemGroup>
<ItemGroup>
diff --git a/src/System.Private.Threading/src/Resources/Strings.resx b/src/System.Private.Threading/src/Resources/Strings.resx
index f160191c0..ff802f945 100644
--- a/src/System.Private.Threading/src/Resources/Strings.resx
+++ b/src/System.Private.Threading/src/Resources/Strings.resx
@@ -117,52 +117,7 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
- <data name="CountdownEvent_Increment_AlreadyZero" xml:space="preserve">
- <value>The event is already signaled and cannot be incremented.</value>
- </data>
- <data name="CountdownEvent_Increment_AlreadyMax" xml:space="preserve">
- <value>The increment operation would cause the CurrentCount to overflow.</value>
- </data>
- <data name="CountdownEvent_Decrement_BelowZero" xml:space="preserve">
- <value>Invalid attempt made to decrement the event's count below zero.</value>
- </data>
- <data name="Common_OperationCanceled" xml:space="preserve">
- <value>The operation was canceled.</value>
- </data>
- <data name="Barrier_Dispose" xml:space="preserve">
- <value>The barrier has been disposed.</value>
- </data>
- <data name="Barrier_SignalAndWait_InvalidOperation_ZeroTotal" xml:space="preserve">
- <value>The barrier has no registered participants.</value>
- </data>
- <data name="Barrier_SignalAndWait_ArgumentOutOfRange" xml:space="preserve">
- <value>The specified timeout must represent a value between -1 and Int32.MaxValue, inclusive.</value>
- </data>
- <data name="Barrier_RemoveParticipants_InvalidOperation" xml:space="preserve">
- <value>The participantCount argument is greater than the number of participants that haven't yet arrived at the barrier in this phase.</value>
- </data>
- <data name="Barrier_RemoveParticipants_ArgumentOutOfRange" xml:space="preserve">
- <value>The participantCount argument must be less than or equal the number of participants.</value>
- </data>
- <data name="Barrier_RemoveParticipants_NonPositive_ArgumentOutOfRange" xml:space="preserve">
- <value>The participantCount argument must be a positive value.</value>
- </data>
- <data name="Barrier_InvalidOperation_CalledFromPHA" xml:space="preserve">
- <value>This method may not be called from within the postPhaseAction.</value>
- </data>
- <data name="Barrier_AddParticipants_NonPositive_ArgumentOutOfRange" xml:space="preserve">
- <value>The participantCount argument must be a positive value.</value>
- </data>
- <data name="Barrier_SignalAndWait_InvalidOperation_ThreadsExceeded" xml:space="preserve">
- <value>The number of threads using the barrier exceeded the total number of registered participants.</value>
- </data>
<data name="BarrierPostPhaseException" xml:space="preserve">
<value>The postPhaseAction failed with an exception.</value>
</data>
- <data name="Barrier_ctor_ArgumentOutOfRange" xml:space="preserve">
- <value>The participantCount argument must be non-negative and less than or equal to 32767.</value>
- </data>
- <data name="Barrier_AddParticipants_Overflow_ArgumentOutOfRange" xml:space="preserve">
- <value>Adding participantCount participants would result in the number of participants exceeding the maximum number allowed.</value>
- </data>
-</root> \ No newline at end of file
+</root>
diff --git a/src/System.Private.TypeLoader/src/Internal/Reflection/Core/AssemblyBinder.cs b/src/System.Private.TypeLoader/src/Internal/Reflection/Core/AssemblyBinder.cs
index 75cb21e54..e346f5f6b 100644
--- a/src/System.Private.TypeLoader/src/Internal/Reflection/Core/AssemblyBinder.cs
+++ b/src/System.Private.TypeLoader/src/Internal/Reflection/Core/AssemblyBinder.cs
@@ -30,7 +30,7 @@ namespace Internal.Reflection.Core
{
public const String DefaultAssemblyNameForGetType = "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
- public abstract bool Bind(RuntimeAssemblyName refName, out AssemblyBindResult result, out Exception exception);
+ public abstract bool Bind(RuntimeAssemblyName refName, bool cacheMissedLookups, out AssemblyBindResult result, out Exception exception);
public abstract bool Bind(byte[] rawAssembly, byte[] rawSymbolStore, out AssemblyBindResult result, out Exception exception);
diff --git a/src/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.Ecma.cs b/src/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.Ecma.cs
index c6342da01..444538f55 100644
--- a/src/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.Ecma.cs
+++ b/src/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.Ecma.cs
@@ -59,7 +59,7 @@ namespace Internal.Reflection.Execution
lock(s_ecmaLoadedAssemblies)
{
// 3. Attempt to bind to already loaded assembly
- if (Bind(runtimeAssemblyName, out bindResult, out exception))
+ if (Bind(runtimeAssemblyName, cacheMissedLookups: false, out bindResult, out exception))
{
result = true;
return;
@@ -75,7 +75,7 @@ namespace Internal.Reflection.Execution
moduleList.RegisterModule(newModuleInfo);
// 5. Then try to load by name again. This load should always succeed
- if (Bind(runtimeAssemblyName, out bindResult, out exception))
+ if (Bind(runtimeAssemblyName, cacheMissedLookups: true, out bindResult, out exception))
{
result = true;
return;
@@ -86,7 +86,7 @@ namespace Internal.Reflection.Execution
}
}
- partial void BindEcmaAssemblyName(RuntimeAssemblyName refName, ref AssemblyBindResult result, ref Exception exception, ref Exception preferredException, ref bool foundMatch)
+ partial void BindEcmaAssemblyName(RuntimeAssemblyName refName, bool cacheMissedLookups, ref AssemblyBindResult result, ref Exception exception, ref Exception preferredException, ref bool foundMatch)
{
lock(s_ecmaLoadedAssemblies)
{
@@ -186,7 +186,7 @@ namespace Internal.Reflection.Execution
}
// Cache missed lookups
- if (!foundMatch)
+ if (cacheMissedLookups && !foundMatch)
{
PEInfo peinfo = new PEInfo(refName, null, null);
s_ecmaLoadedAssemblies.Add(peinfo);
diff --git a/src/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.cs b/src/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.cs
index 701160534..e2fcc6a57 100644
--- a/src/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.cs
+++ b/src/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.cs
@@ -35,7 +35,7 @@ namespace Internal.Reflection.Execution
public static AssemblyBinderImplementation Instance { get; } = new AssemblyBinderImplementation();
partial void BindEcmaByteArray(byte[] rawAssembly, byte[] rawSymbolStore, ref AssemblyBindResult bindResult, ref Exception exception, ref bool? result);
- partial void BindEcmaAssemblyName(RuntimeAssemblyName refName, ref AssemblyBindResult result, ref Exception exception, ref Exception preferredException, ref bool resultBoolean);
+ partial void BindEcmaAssemblyName(RuntimeAssemblyName refName, bool cacheMissedLookups, ref AssemblyBindResult result, ref Exception exception, ref Exception preferredException, ref bool resultBoolean);
partial void InsertEcmaLoadedAssemblies(List<AssemblyBindResult> loadedAssemblies);
public sealed override bool Bind(byte[] rawAssembly, byte[] rawSymbolStore, out AssemblyBindResult bindResult, out Exception exception)
@@ -53,7 +53,7 @@ namespace Internal.Reflection.Execution
return result.Value;
}
- public sealed override bool Bind(RuntimeAssemblyName refName, out AssemblyBindResult result, out Exception exception)
+ public sealed override bool Bind(RuntimeAssemblyName refName, bool cacheMissedLookups, out AssemblyBindResult result, out Exception exception)
{
bool foundMatch = false;
result = default(AssemblyBindResult);
@@ -102,7 +102,7 @@ namespace Internal.Reflection.Execution
}
}
- BindEcmaAssemblyName(refName, ref result, ref exception, ref preferredException, ref foundMatch);
+ BindEcmaAssemblyName(refName, cacheMissedLookups, ref result, ref exception, ref preferredException, ref foundMatch);
if (exception != null)
return false;
diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallConverterThunk.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallConverterThunk.cs
index b9b8a9cff..f0f8256c7 100644
--- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallConverterThunk.cs
+++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallConverterThunk.cs
@@ -1114,11 +1114,12 @@ namespace Internal.Runtime.TypeLoader
#endif
}
}
- else if (conversionParams._conversionInfo.IsAnyDynamicInvokerThunk && thRetType.IsValueType())
+ else if (conversionParams._conversionInfo.IsAnyDynamicInvokerThunk &&
+ (thRetType.IsValueType() || thRetType.IsPointerType() || returnType == CorElementType.ELEMENT_TYPE_BYREF))
{
Debug.Assert(returnValueToCopy != null);
- if (conversionParams._calleeArgs.GetReturnType(out thDummy, out dummyBool) == CorElementType.ELEMENT_TYPE_VOID)
+ if (returnType == CorElementType.ELEMENT_TYPE_VOID)
{
// Invokers returning void need to return a null object
returnValueToCopy = null;
@@ -1128,8 +1129,37 @@ namespace Internal.Runtime.TypeLoader
if (!conversionParams._callerArgs.HasRetBuffArg() && conversionParams._calleeArgs.HasRetBuffArg())
returnValueToCopy = (void*)(new IntPtr(*((void**)returnValueToCopy)) + IntPtr.Size);
+ if (returnType == CorElementType.ELEMENT_TYPE_BYREF)
+ {
+ // If this is a byref return, we're going to dereference the result
+ returnValueToCopy = *(void**)returnValueToCopy;
+ }
+
+ RuntimeTypeHandle returnTypeRuntimeTypeHandle = thRetType.GetRuntimeTypeHandle();
+
// Need to box value type before returning it
- object returnValue = RuntimeAugments.Box(thRetType.GetRuntimeTypeHandle(), new IntPtr(returnValueToCopy));
+ object returnValue;
+ if (returnType == CorElementType.ELEMENT_TYPE_BYREF && returnValueToCopy == null)
+ {
+ // This is a byref return and dereferencing it would result in a NullReferenceException.
+ // Set the return value to a sentinel that InvokeUtils will recognize.
+ // Can't throw from here or we would wrap this in a TargetInvocationException.
+ returnValue = InvokeUtils.NullByRefValueSentinel;
+ }
+ else if (RuntimeAugments.IsUnmanagedPointerType(returnTypeRuntimeTypeHandle))
+ {
+ returnValue = System.Reflection.Pointer.Box(*(void**)returnValueToCopy, Type.GetTypeFromHandle(returnTypeRuntimeTypeHandle));
+ }
+ else if (RuntimeAugments.IsValueType(returnTypeRuntimeTypeHandle))
+ {
+ returnValue = RuntimeAugments.Box(returnTypeRuntimeTypeHandle, new IntPtr(returnValueToCopy));
+ }
+ else
+ {
+ // byref return of a reference type
+ Debug.Assert(returnType == CorElementType.ELEMENT_TYPE_BYREF);
+ returnValue = Unsafe.As<byte, object>(ref *(byte*)returnValueToCopy);
+ }
CallConversionParameters.s_pinnedGCHandles._returnObjectHandle.Target = returnValue;
pinnedResultObject = CallConversionParameters.s_pinnedGCHandles._returnObjectHandle.GetRawTargetAddress();
returnValueToCopy = (void*)&pinnedResultObject;
diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallInterceptor.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallInterceptor.cs
index b26dd803f..039dab7bf 100644
--- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallInterceptor.cs
+++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallInterceptor.cs
@@ -95,6 +95,9 @@ namespace Internal.Runtime.CallInterceptor
{
address = *(IntPtr*)address.ToPointer();
}
+#if CCCONVERTER_TRACE
+ CallingConventionConverterLogger.WriteLine("READ " + (_types[index].ByRef ? "ByRef " : "") + "LocalVariableSet, _pbMemory:" + new IntPtr(_pbMemory).LowLevelToString() + "[" + index.LowLevelToString() + "]. " + _types[index].TypeInstanceFieldSize.LowLevelToString() + " bytes <- [" + address.LowLevelToString() + "]");
+#endif
return Unsafe.Read<T>((void*)address);
}
@@ -108,6 +111,9 @@ namespace Internal.Runtime.CallInterceptor
{
address = *(IntPtr*)address.ToPointer();
}
+#if CCCONVERTER_TRACE
+ CallingConventionConverterLogger.WriteLine("WRITE " + (_types[index].ByRef ? "ByRef " : "") + "LocalVariableSet, _pbMemory:" + new IntPtr(_pbMemory).LowLevelToString() + "[" + index.LowLevelToString() + "]. " + _types[index].TypeInstanceFieldSize.LowLevelToString() + " bytes -> [" + address.LowLevelToString() + "]");
+#endif
Unsafe.Write<T>((void*)address, value);
}
@@ -510,16 +516,38 @@ namespace Internal.Runtime.CallInterceptor
break;
default:
- callConversionOps.Add(new CallConversionOperation(
- CallConversionOperation.OpCode.COPY_X_BYTES_FROM_LOCALBLOCK_Y_POINTER_Z_TO_OFFSET_W_IN_TRANSITION_BLOCK,
- calleeArgs.GetArgSize(),
- CallConversionInterpreter.ArgBlock,
- i,
- ofsCallee
+ {
+#if ARM64
+ if (ofsCallee < 0 && argTypeHandle.IsHFA() && argTypeHandle.GetHFAType() == CorElementType.ELEMENT_TYPE_R4)
+ {
+ // S and D registers overlap. The FP block of the transition block has 64-bit slots that are used for both floats and doubles.
+ // When dealing with float HFAs, we need to copy the 32-bit floats into the 64-bit slots to match the format of the transition block's FP block.
+
+ callConversionOps.Add(new CallConversionOperation(
+ CallConversionOperation.OpCode.ARM64_COPY_X_HFA_FLOATS_FROM_LOCALBLOCK_Y_POINTER_Z_TO_OFFSET_W_IN_TRANSITION_BLOCK,
+ (int)argTypeHandle.GetSize() / 4,
+ CallConversionInterpreter.ArgBlock,
+ i,
+ ofsCallee
#if CCCONVERTER_TRACE
- , "Arg #" + i.LowLevelToString()
+ , "Arg #" + i.LowLevelToString()
#endif
- ));
+ ));
+ break;
+ }
+#endif
+
+ callConversionOps.Add(new CallConversionOperation(
+ CallConversionOperation.OpCode.COPY_X_BYTES_FROM_LOCALBLOCK_Y_POINTER_Z_TO_OFFSET_W_IN_TRANSITION_BLOCK,
+ calleeArgs.GetArgSize(),
+ CallConversionInterpreter.ArgBlock,
+ i,
+ ofsCallee
+#if CCCONVERTER_TRACE
+ , "Arg #" + i.LowLevelToString()
+#endif
+ ));
+ }
break;
}
}
@@ -556,8 +584,20 @@ namespace Internal.Runtime.CallInterceptor
}
else
{
- // Copy from return buffer into return value local
- callConversionOps.Add(new CallConversionOperation(CallConversionOperation.OpCode.COPY_X_BYTES_FROM_RETBUF_TO_LOCALBLOCK_Y_POINTER_Z, checked((int)returnType.GetSize()), CallConversionInterpreter.ArgBlock, 0));
+#if ARM64
+ if (returnType.IsHFA() && returnType.GetHFAType() == CorElementType.ELEMENT_TYPE_R4)
+ {
+ // S and D registers overlap. The return buffer has 64-bit slots that are used for both floats and doubles.
+ // When dealing with float HFAs, we need to copy 32-bit float values from the 64-bit slots of the return buffer (A simple memcopy won't work here).
+
+ callConversionOps.Add(new CallConversionOperation(CallConversionOperation.OpCode.ARM64_COPY_X_HFA_FLOATS_FROM_RETBUF_TO_LOCALBLOCK_Y_POINTER_Z, checked((int)returnType.GetSize() / 4), CallConversionInterpreter.ArgBlock, 0));
+ }
+ else
+#endif
+ {
+ // Copy from return buffer into return value local
+ callConversionOps.Add(new CallConversionOperation(CallConversionOperation.OpCode.COPY_X_BYTES_FROM_RETBUF_TO_LOCALBLOCK_Y_POINTER_Z, checked((int)returnType.GetSize()), CallConversionInterpreter.ArgBlock, 0));
+ }
}
}
@@ -640,7 +680,7 @@ namespace Internal.Runtime.CallInterceptor
s = "RETURN_RETBUF_FROM_OFFSET_X_IN_TRANSITION_BLOCK";
break;
case OpCode.RETURN_FLOATINGPOINT_BYVALUE_FROM_LOCALBLOCK_X_POINTER_Y_OF_SIZE_Z:
- s = "__RETURN_FLOATINGPOINT_BYVALUE_FROM_LOCALBLOCK_X_POINTER_Y_OF_SIZE_Z__";
+ s = "RETURN_FLOATINGPOINT_BYVALUE_FROM_LOCALBLOCK_X_POINTER_Y_OF_SIZE_Z";
break;
case OpCode.RETURN_INTEGER_BYVALUE_FROM_LOCALBLOCK_X_POINTER_Y_OF_SIZE_Z:
s = "RETURN_INTEGER_BYVALUE_FROM_LOCALBLOCK_X_POINTER_Y_OF_SIZE_Z";
@@ -663,6 +703,20 @@ namespace Internal.Runtime.CallInterceptor
case OpCode.COPY_GENERIC_CONTEXT_TO_OFFSET_X_IN_TRANSITION_BLOCK:
s = "COPY_GENERIC_CONTEXT_TO_OFFSET_X_IN_TRANSITION_BLOCK";
break;
+#if ARM64
+ case OpCode.ARM64_COMPACT_X_FLOATS_INTO_HFA_AT_OFFSET_Y_IN_TRANSITION_BLOCK:
+ s = "ARM64_COMPACT_X_FLOATS_INTO_HFA_AT_OFFSET_Y_IN_TRANSITION_BLOCK";
+ break;
+ case OpCode.ARM64_EXPAND_X_FLOATS_INTO_HFA_IN_RETURN_BLOCK:
+ s = "ARM64_EXPAND_X_FLOATS_INTO_HFA_IN_RETURN_BLOCK";
+ break;
+ case OpCode.ARM64_COPY_X_HFA_FLOATS_FROM_LOCALBLOCK_Y_POINTER_Z_TO_OFFSET_W_IN_TRANSITION_BLOCK:
+ s = "ARM64_COPY_X_HFA_FLOATS_FROM_LOCALBLOCK_Y_POINTER_Z_TO_OFFSET_W_IN_TRANSITION_BLOCK";
+ break;
+ case OpCode.ARM64_COPY_X_HFA_FLOATS_FROM_RETBUF_TO_LOCALBLOCK_Y_POINTER_Z:
+ s = "ARM64_COPY_X_HFA_FLOATS_FROM_RETBUF_TO_LOCALBLOCK_Y_POINTER_Z";
+ break;
+#endif
default:
s = "";
break;
@@ -690,7 +744,7 @@ namespace Internal.Runtime.CallInterceptor
}
#else
- public CallConversionOperation(OpCode op, int X, int Y, int Z, int W)
+ public CallConversionOperation(OpCode op, int X, int Y, int Z, int W)
{
this.Op = op;
this.X = X;
@@ -755,7 +809,13 @@ namespace Internal.Runtime.CallInterceptor
CALL_DESCR_MANAGED_WITH_RETBUF_AS_LOCALBLOCK_X_POINTER_Y_STACKSLOTS_Z_FPCALLINFO_W,
CALL_DESCR_NATIVE_WITH_RETBUF_AS_LOCALBLOCK_X_POINTER_Y_STACKSLOTS_Z_FPCALLINFO_W,
COPY_X_BYTES_FROM_RETBUF_TO_LOCALBLOCK_Y_POINTER_Z,
- COPY_GENERIC_CONTEXT_TO_OFFSET_X_IN_TRANSITION_BLOCK
+ COPY_GENERIC_CONTEXT_TO_OFFSET_X_IN_TRANSITION_BLOCK,
+#if ARM64
+ ARM64_COMPACT_X_FLOATS_INTO_HFA_AT_OFFSET_Y_IN_TRANSITION_BLOCK,
+ ARM64_EXPAND_X_FLOATS_INTO_HFA_IN_RETURN_BLOCK,
+ ARM64_COPY_X_HFA_FLOATS_FROM_LOCALBLOCK_Y_POINTER_Z_TO_OFFSET_W_IN_TRANSITION_BLOCK,
+ ARM64_COPY_X_HFA_FLOATS_FROM_RETBUF_TO_LOCALBLOCK_Y_POINTER_Z
+#endif
}
public OpCode Op;
@@ -875,6 +935,73 @@ namespace Internal.Runtime.CallInterceptor
}
break;
+#if ARM64
+ case CallConversionOperation.OpCode.ARM64_COMPACT_X_FLOATS_INTO_HFA_AT_OFFSET_Y_IN_TRANSITION_BLOCK:
+ {
+ Debug.Assert(op.X > 0 && op.X <= 4);
+
+ float* pFPRegs = (float*)(locals.TransitionBlockPtr + op.Y);
+ for (int i = 1; i < op.X; i++)
+ pFPRegs[i] = pFPRegs[i * 2];
+
+#if CCCONVERTER_TRACE
+ CallingConventionConverterLogger.WriteLine(" -> Compact " + op.X.LowLevelToString() + " ARM64 HFA floats at [" + new IntPtr(pFPRegs).LowLevelToString() + "]");
+#endif
+ }
+ break;
+
+ case CallConversionOperation.OpCode.ARM64_EXPAND_X_FLOATS_INTO_HFA_IN_RETURN_BLOCK:
+ {
+ Debug.Assert(op.X > 0 && op.X <= 4);
+
+ byte* pReturnBlock = locals.TransitionBlockPtr + TransitionBlock.GetOffsetOfFloatArgumentRegisters();
+ for (int i = op.X - 1; i >= 0; i--)
+ {
+ float value = ((float*)pReturnBlock)[i];
+ *((IntPtr*)pReturnBlock + i) = IntPtr.Zero; // Clear destination slot to zeros before copying the float value
+ *((float*)((IntPtr*)pReturnBlock + i)) = value;
+ }
+
+#if CCCONVERTER_TRACE
+ CallingConventionConverterLogger.WriteLine(" -> Expand " + op.X.LowLevelToString() + " ARM64 HFA floats at [" + new IntPtr(pReturnBlock).LowLevelToString() + "]");
+#endif
+ }
+ break;
+
+ case CallConversionOperation.OpCode.ARM64_COPY_X_HFA_FLOATS_FROM_LOCALBLOCK_Y_POINTER_Z_TO_OFFSET_W_IN_TRANSITION_BLOCK:
+ {
+ Debug.Assert(op.X > 0 && op.X <= 4);
+
+ float* pSrc = (float*)(locals.GetLocalBlock(op.Y).GetRawMemoryPointer()[op.Z]);
+ float* pDst = (float*)(locals.TransitionBlockPtr + op.W);
+ for (int i = 0; i < op.X; i++)
+ {
+ ((IntPtr*)pDst)[i] = IntPtr.Zero; // Clear destination slot to zeros before copying the float value
+ pDst[i * 2] = pSrc[i];
+ }
+
+#if CCCONVERTER_TRACE
+ CallingConventionConverterLogger.WriteLine(" -> Copy " + op.X.LowLevelToString() + " ARM64 HFA floats from [" + new IntPtr(pSrc).LowLevelToString() + "] to [" + new IntPtr(pDst).LowLevelToString() + "]");
+#endif
+ }
+ break;
+
+ case CallConversionOperation.OpCode.ARM64_COPY_X_HFA_FLOATS_FROM_RETBUF_TO_LOCALBLOCK_Y_POINTER_Z:
+ {
+ Debug.Assert(op.X > 0 && op.X <= 4);
+
+ float* pSrc = (float*)locals.IntPtrReturnVal.ToPointer();
+ float* pDst = (float*)(locals.GetLocalBlock(op.Y).GetRawMemoryPointer()[op.Z].ToPointer());
+ for (int i = 0; i < op.X; i++)
+ pDst[i] = pSrc[i * 2];
+
+#if CCCONVERTER_TRACE
+ CallingConventionConverterLogger.WriteLine(" -> Copy " + op.X.LowLevelToString() + " ARM64 HFA floats from [" + new IntPtr(pSrc).LowLevelToString() + "] to [" + new IntPtr(pDst).LowLevelToString() + "]");
+#endif
+ }
+ break;
+#endif
+
case CallConversionOperation.OpCode.COPY_X_BYTES_FROM_LOCALBLOCK_Y_OFFSET_Z_IN_LOCALBLOCK_TO_OFFSET_W_IN_TRANSITION_BLOCK:
{
void* pSrc = ((byte*)locals.GetLocalBlock(op.Y).GetRawMemoryPointer()) + op.Z;
@@ -1064,15 +1191,15 @@ namespace Internal.Runtime.CallInterceptor
case CallConversionOperation.OpCode.RETURN_FLOATINGPOINT_BYVALUE_FROM_LOCALBLOCK_X_POINTER_Y_OF_SIZE_Z:
{
#if CALLDESCR_FPARGREGSARERETURNREGS
- byte* returnBlock = locals.TransitionBlockPtr + TransitionBlock.GetOffsetOfFloatArgumentRegisters();
- MemoryHelpers.Memset((IntPtr)returnBlock, IntPtr.Size, 0);
- Buffer.MemoryCopy(locals.GetLocalBlock(op.X).GetRawMemoryPointer()[op.Y].ToPointer(), returnBlock, op.Z, op.Z);
+ byte* pReturnBlock = locals.TransitionBlockPtr + TransitionBlock.GetOffsetOfFloatArgumentRegisters();
+ MemoryHelpers.Memset((IntPtr)pReturnBlock, IntPtr.Size, 0);
+ Buffer.MemoryCopy(locals.GetLocalBlock(op.X).GetRawMemoryPointer()[op.Y].ToPointer(), pReturnBlock, op.Z, op.Z);
locals.IntPtrReturnVal = CallConverterThunk.ReturnVoidReturnThunk;
#elif X86
CallConverterThunk.SetupCallerActualReturnData(locals.TransitionBlockPtr);
- fixed (ReturnBlock* retBlk = &CallConverterThunk.t_NonArgRegisterReturnSpace)
+ fixed (ReturnBlock* pReturnBlock = &CallConverterThunk.t_NonArgRegisterReturnSpace)
{
- Buffer.MemoryCopy(locals.GetLocalBlock(op.X).GetRawMemoryPointer()[op.Y].ToPointer(), retBlk, op.Z, op.Z);
+ Buffer.MemoryCopy(locals.GetLocalBlock(op.X).GetRawMemoryPointer()[op.Y].ToPointer(), pReturnBlock, op.Z, op.Z);
}
if (op.Z == 4)
{
@@ -1446,8 +1573,10 @@ namespace Internal.Runtime.CallInterceptor
{
int ofsCaller = callerArgs.GetNextOffset();
- TypeHandle dummyTypeHandle;
- if (callerArgs.IsArgPassedByRef() && callerArgs.GetArgType(out dummyTypeHandle) != CorElementType.ELEMENT_TYPE_BYREF)
+ TypeHandle argTypeHandle;
+ CorElementType argType = callerArgs.GetArgType(out argTypeHandle);
+
+ if (callerArgs.IsArgPassedByRef() && argType != CorElementType.ELEMENT_TYPE_BYREF)
{
callConversionOps.Add(new CallConversionOperation(
CallConversionOperation.OpCode.COPY_X_BYTES_TO_LOCALBLOCK_Y_OFFSET_Z_IN_LOCALBLOCK_FROM_OFFSET_W_IN_TRANSITION_BLOCK,
@@ -1462,6 +1591,24 @@ namespace Internal.Runtime.CallInterceptor
}
else
{
+#if ARM64
+ if (ofsCaller < 0 && argTypeHandle.IsHFA() && argTypeHandle.GetHFAType() == CorElementType.ELEMENT_TYPE_R4)
+ {
+ // S and D registers overlap. The FP block of the transition block will have the float values of the HFA struct stored in 64-bit slots. We cannot directly
+ // memcopy or point at these values without first re-writing them as consecutive 32-bit float values
+
+ callConversionOps.Add(new CallConversionOperation(
+ CallConversionOperation.OpCode.ARM64_COMPACT_X_FLOATS_INTO_HFA_AT_OFFSET_Y_IN_TRANSITION_BLOCK,
+ (int)argTypeHandle.GetSize() / 4,
+ ofsCaller,
+ 0
+#if CCCONVERTER_TRACE
+ , "Arg #" + i.LowLevelToString()
+#endif
+ ));
+ }
+#endif
+
callConversionOps.Add(new CallConversionOperation(
CallConversionOperation.OpCode.SET_LOCALBLOCK_X_POINTER_Y_TO_OFFSET_Z_IN_TRANSITION_BLOCK,
CallConversionInterpreter.ArgBlock,
@@ -1492,6 +1639,14 @@ namespace Internal.Runtime.CallInterceptor
else if (callerArgs.GetFPReturnSize() > 0)
{
callConversionOps.Add(new CallConversionOperation(CallConversionOperation.OpCode.RETURN_FLOATINGPOINT_BYVALUE_FROM_LOCALBLOCK_X_POINTER_Y_OF_SIZE_Z, CallConversionInterpreter.ArgBlock, 0, checked((int)callerArgs.GetFPReturnSize())));
+
+#if ARM64
+ if (returnType.IsHFA() && returnType.GetHFAType() == CorElementType.ELEMENT_TYPE_R4)
+ {
+ // S and D registers overlap, so we need to re-write the float values into 64-bit slots to match the format of the UniversalTransitionBlock's FP return block
+ callConversionOps.Add(new CallConversionOperation(CallConversionOperation.OpCode.ARM64_EXPAND_X_FLOATS_INTO_HFA_IN_RETURN_BLOCK, (int)returnType.GetSize() / 4, 0, 0));
+ }
+#endif
}
else
{
diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallingConventions.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallingConventions.cs
index 66dc46496..939017568 100644
--- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallingConventions.cs
+++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallingConventions.cs
@@ -107,6 +107,7 @@ namespace Internal.Runtime.CallConverter
public bool IsNull() { return _eeType == null && !_isByRef; }
public bool IsValueType() { if (_isByRef) return false; return _eeType->IsValueType; }
+ public bool IsPointerType() { if (_isByRef) return false; return _eeType->IsPointerType; }
public unsafe uint GetSize()
{
@@ -836,7 +837,7 @@ namespace Internal.Runtime.CallConverter
#if !_TARGET_X86_
numRegistersUsed++;
#else
- // DESKTOP BEHAVIOR is to do nothing here, as ret buf is never reached by the scan algortithm that walks backwards
+ // DESKTOP BEHAVIOR is to do nothing here, as ret buf is never reached by the scan algorithm that walks backwards
// but in .NET Native, the x86 argument scan is a forward scan, so we need to skip the ret buf arg (which is always
// on the stack)
initialArgOffset = IntPtr.Size;
@@ -934,9 +935,14 @@ namespace Internal.Runtime.CallConverter
#if _TARGET_ARM64_
// NOT DESKTOP BEHAVIOR: The S and D registers overlap, and the UniversalTransitionThunk copies D registers to the transition blocks. We'll need
// to work with the D registers here as well.
+ bool processingFloatsAsDoublesFromTransitionBlock = false;
if (argType == CorElementType.ELEMENT_TYPE_VALUETYPE && _argTypeHandle.IsHFA() && _argTypeHandle.GetHFAType() == CorElementType.ELEMENT_TYPE_R4)
{
- argSize *= 2;
+ if ((argSize / sizeof(float)) + _idxFPReg <= 8)
+ {
+ argSize *= 2;
+ processingFloatsAsDoublesFromTransitionBlock = true;
+ }
}
#endif
@@ -1238,8 +1244,10 @@ namespace Internal.Runtime.CallConverter
if (_argTypeHandle.IsHFA())
{
CorElementType type = _argTypeHandle.GetHFAType();
- // DESKTOP BEHAVIOR cFPRegs = (type == CorElementType.ELEMENT_TYPE_R4) ? (argSize / sizeof(float)) : (argSize / sizeof(double));
- cFPRegs = argSize / sizeof(double);
+ if (processingFloatsAsDoublesFromTransitionBlock)
+ cFPRegs = argSize / sizeof(double);
+ else
+ cFPRegs = (type == CorElementType.ELEMENT_TYPE_R4) ? (argSize / sizeof(float)) : (argSize / sizeof(double));
}
else
{
diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ConstrainedCallSupport.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ConstrainedCallSupport.cs
index f00b66e76..184c7a430 100644
--- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ConstrainedCallSupport.cs
+++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/ConstrainedCallSupport.cs
@@ -25,10 +25,8 @@ namespace Internal.Runtime.TypeLoader
private delegate IntPtr ResolveCallOnValueTypeDel(IntPtr thisPtr, IntPtr callDescIntPtr);
#endif
-#if PROJECTN
[DllImport("*", ExactSpelling = true, EntryPoint = "ConstrainedCallSupport_GetStubs")]
private extern static unsafe void ConstrainedCallSupport_GetStubs(out IntPtr constrainedCallSupport_DerefThisAndCall_CommonCallingStub, out IntPtr constrainedCallSupport_DirectConstrainedCall_CommonCallingStub);
-#endif
private static IntPtr s_constrainedCallSupport_DerefThisAndCall_CommonCallingStub;
private static IntPtr s_constrainedCallSupport_DirectConstrainedCall_CommonCallingStub;
@@ -42,14 +40,8 @@ namespace Internal.Runtime.TypeLoader
static ConstrainedCallSupport()
{
- // TODO: export this unmanaged API in CoreRT
-#if PROJECTN
ConstrainedCallSupport_GetStubs(out s_constrainedCallSupport_DerefThisAndCall_CommonCallingStub,
out s_constrainedCallSupport_DirectConstrainedCall_CommonCallingStub);
-#else
- s_constrainedCallSupport_DerefThisAndCall_CommonCallingStub = IntPtr.Zero;
- s_constrainedCallSupport_DirectConstrainedCall_CommonCallingStub = IntPtr.Zero;
-#endif
}
// There are multiple possible paths here.
diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/McgIntrinsics.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/McgIntrinsics.cs
index f89a4be8e..2953fdea4 100644
--- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/McgIntrinsics.cs
+++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/McgIntrinsics.cs
@@ -5,6 +5,13 @@
using System;
+namespace System.Runtime.CompilerServices
+{
+ internal sealed class IntrinsicAttribute : Attribute
+ {
+ }
+}
+
namespace System.Runtime.InteropServices
{
[AttributeUsage((System.AttributeTargets.Method | System.AttributeTargets.Class))]
diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/MetadataReaderExtensions.Ecma.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/MetadataReaderExtensions.Ecma.cs
index ebd30963a..7b50bee42 100644
--- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/MetadataReaderExtensions.Ecma.cs
+++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/MetadataReaderExtensions.Ecma.cs
@@ -9,6 +9,7 @@ using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
+using System.Globalization;
using Internal.LowLevelLinq;
using Internal.Reflection.Core;
@@ -91,10 +92,18 @@ namespace System.Reflection.Runtime.General
publicKeyOrTokenByteArray = Array.Empty<byte>();
}
+ string cultureName = culture.GetString(reader);
+ if (!String.IsNullOrEmpty(cultureName))
+ {
+ // Canonicalize spelling and force a CultureNotFoundException if not a valid culture
+ CultureInfo cultureInfo = CultureInfo.GetCultureInfo(cultureName);
+ cultureName = cultureInfo.Name;
+ }
+
return new RuntimeAssemblyName(
name.GetString(reader),
version,
- culture.GetString(reader),
+ cultureName,
assemblyNameFlags,
publicKeyOrTokenByteArray
);
diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/JitSupport.MethodEntrypointStubs.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/MethodEntrypointStubs.cs
index 6f0c2927c..6f0c2927c 100644
--- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/JitSupport.MethodEntrypointStubs.cs
+++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/MethodEntrypointStubs.cs
diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutFieldAlgorithm.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutFieldAlgorithm.cs
index 5f7c58637..3ab3a6c8f 100644
--- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutFieldAlgorithm.cs
+++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NativeLayoutFieldAlgorithm.cs
@@ -120,7 +120,8 @@ namespace Internal.Runtime.TypeLoader
{
layout.GcStatics = new StaticsBlock() { Size = position[(int)NativeFormat.FieldStorage.GCStatic], LargestAlignment = DefType.MaximumAlignmentPossible };
layout.NonGcStatics = new StaticsBlock() { Size = position[(int)NativeFormat.FieldStorage.NonGCStatic], LargestAlignment = DefType.MaximumAlignmentPossible };
- layout.ThreadStatics = new StaticsBlock() { Size = position[(int)NativeFormat.FieldStorage.TLSStatic], LargestAlignment = DefType.MaximumAlignmentPossible };
+ layout.ThreadGcStatics = new StaticsBlock() { Size = position[(int)NativeFormat.FieldStorage.TLSStatic], LargestAlignment = DefType.MaximumAlignmentPossible };
+ layout.ThreadNonGcStatics = new StaticsBlock() { Size = LayoutInt.Zero, LargestAlignment = LayoutInt.Zero };
}
int curStaticField = 0;
@@ -179,7 +180,8 @@ namespace Internal.Runtime.TypeLoader
GcStatics = new StaticsBlock() { Size = gcDataSize, LargestAlignment = DefType.MaximumAlignmentPossible },
NonGcStatics = new StaticsBlock() { Size = nonGcDataSize, LargestAlignment = DefType.MaximumAlignmentPossible },
Offsets = null, // We're not computing field offsets here, so return null
- ThreadStatics = new StaticsBlock() { Size = threadDataSize, LargestAlignment = DefType.MaximumAlignmentPossible },
+ ThreadGcStatics = new StaticsBlock() { Size = threadDataSize, LargestAlignment = DefType.MaximumAlignmentPossible },
+ ThreadNonGcStatics = new StaticsBlock() { Size = LayoutInt.Zero, LargestAlignment = LayoutInt.Zero },
};
return staticLayout;
diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NoMetadataFieldLayoutAlgorithm.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NoMetadataFieldLayoutAlgorithm.cs
index adff035ae..83c069b89 100644
--- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NoMetadataFieldLayoutAlgorithm.cs
+++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/NoMetadataFieldLayoutAlgorithm.cs
@@ -83,7 +83,8 @@ namespace Internal.Runtime.TypeLoader
GcStatics = default(StaticsBlock),
NonGcStatics = default(StaticsBlock),
Offsets = Array.Empty<FieldAndOffset>(), // No fields are considered to exist for completely NoMetadataTypes
- ThreadStatics = default(StaticsBlock),
+ ThreadGcStatics = default(StaticsBlock),
+ ThreadNonGcStatics = default(StaticsBlock),
};
return staticLayout;
}
diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs
index 315e0f9d2..271ec8cef 100644
--- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs
+++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs
@@ -1944,19 +1944,11 @@ namespace Internal.Runtime.TypeLoader
if (floatingCells == null)
return IntPtr.Zero;
- // First, check if the current version of the existing floating dictionary matches the version in the native layout. If so, there
- // is no need to allocate anything new, and we can just use the existing statically compiled floating portion of the input dictionary.
-
- // If the fixed dictionary claims to have a floating section
+ // If the floating section is already constructed, then return. This means we are beaten by another thread.
if (*((IntPtr*)fixedDictionary) != IntPtr.Zero)
{
- int currentFloatingVersion = (int)(((IntPtr*)fixedDictionary)[floatingVersionCellIndex]);
-
- if (currentFloatingVersion == floatingVersionInLayout)
- {
- isNewlyAllocatedDictionary = false;
- return fixedDictionary + IntPtr.Size * floatingVersionCellIndex;
- }
+ isNewlyAllocatedDictionary = false;
+ return *((IntPtr*)fixedDictionary);
}
GenericTypeDictionary floatingDict = new GenericTypeDictionary(floatingCells);
diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilderState.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilderState.cs
index 709a17f06..b83174f60 100644
--- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilderState.cs
+++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilderState.cs
@@ -507,7 +507,7 @@ namespace Internal.Runtime.TypeLoader
DefType defType = TypeBeingBuilt as DefType;
if (defType != null && !defType.IsGenericDefinition)
{
- return defType.ThreadStaticFieldSize.AsInt;
+ return defType.ThreadGcStaticFieldSize.AsInt;
}
else
{
@@ -532,7 +532,7 @@ namespace Internal.Runtime.TypeLoader
public uint NumSealedVTableEntries;
public int[] GenericVarianceFlags;
- // Sentinel static to allow us to initializae _instanceLayout to something
+ // Sentinel static to allow us to initialize _instanceLayout to something
// and then detect that InstanceGCLayout should return null
private static LowLevelList<bool> s_emptyLayout = new LowLevelList<bool>();
diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs
index bde93220d..67a0d3da6 100644
--- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs
+++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs
@@ -1340,7 +1340,7 @@ namespace Internal.Runtime.TypeLoader
#if SUPPORTS_R2R_LOADING
TryGetCodeTableEntry(methodOnType, out entryPoint, out unboxingStubAddress, out foundAddressType);
#endif
-#if SUPPORT_JIT
+#if SUPPORT_DYNAMIC_CODE
if (foundAddressType == MethodAddressType.None)
MethodEntrypointStubs.TryGetMethodEntrypoint(methodOnType, out entryPoint, out unboxingStubAddress, out foundAddressType);
#endif
diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.MethodAddress.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.MethodAddress.cs
index 1f33974f8..dbc95140f 100644
--- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.MethodAddress.cs
+++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.MethodAddress.cs
@@ -52,7 +52,7 @@ namespace Internal.Runtime.TypeLoader
#if SUPPORTS_R2R_LOADING
TryGetCodeTableEntry(method, out methodAddress, out unboxingStubAddress, out foundAddressType);
#endif
-#if SUPPORT_JIT
+#if SUPPORT_DYNAMIC_CODE
if (foundAddressType == MethodAddressType.None)
MethodEntrypointStubs.TryGetMethodEntrypoint(method, out methodAddress, out unboxingStubAddress, out foundAddressType);
#endif
diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderTypeSystemContext.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderTypeSystemContext.cs
index 3b9b0bcd1..ccbf4aff9 100644
--- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderTypeSystemContext.cs
+++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderTypeSystemContext.cs
@@ -45,7 +45,7 @@ namespace Internal.Runtime.TypeLoader
public override FieldLayoutAlgorithm GetLayoutAlgorithmForType(DefType type)
{
if ((type == UniversalCanonType)
-#if SUPPORT_JIT
+#if SUPPORT_DYNAMIC_CODE
|| (type.IsRuntimeDeterminedType && (((RuntimeDeterminedType)type).CanonicalType == UniversalCanonType)))
#else
)
@@ -202,7 +202,7 @@ namespace Internal.Runtime.TypeLoader
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
AssemblyBindResult bindResult;
Exception failureException;
- if (!AssemblyBinderImplementation.Instance.Bind(name.ToRuntimeAssemblyName(), out bindResult, out failureException))
+ if (!AssemblyBinderImplementation.Instance.Bind(name.ToRuntimeAssemblyName(), cacheMissedLookups: true, out bindResult, out failureException))
{
if (throwErrorIfNotFound)
throw failureException;
diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeSystemExtensions.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeSystemExtensions.cs
index cbdbd68fd..0154a424c 100644
--- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeSystemExtensions.cs
+++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeSystemExtensions.cs
@@ -145,8 +145,9 @@ namespace Internal.Runtime.TypeLoader
methodOnInstantiatedType = typeSystemContext.GetMethodForInstantiatedType(typicalMethod, (InstantiatedType)declaringType);
MethodDesc instantiatedMethod = methodOnInstantiatedType;
- if (genericMethodArgs.Length != 0)
+ if (genericMethodArgs != null)
{
+ Debug.Assert(genericMethodArgs.Length > 0);
Instantiation genericMethodInstantiation = typeSystemContext.ResolveRuntimeTypeHandles(genericMethodArgs);
typeSystemContext.GetInstantiatedMethod(methodOnInstantiatedType, genericMethodInstantiation);
}
diff --git a/src/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeNoMetadataType.cs b/src/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeNoMetadataType.cs
index d9c688be6..3e6b79244 100644
--- a/src/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeNoMetadataType.cs
+++ b/src/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeNoMetadataType.cs
@@ -198,9 +198,9 @@ namespace Internal.TypeSystem.NoMetadata
}
}
- if ((mask & TypeFlags.IsByRefLikeComputed) != 0)
+ if ((mask & TypeFlags.AttributeCacheComputed) != 0)
{
- flags |= TypeFlags.IsByRefLikeComputed;
+ flags |= TypeFlags.AttributeCacheComputed;
unsafe
{
diff --git a/src/System.Private.TypeLoader/src/System.Private.TypeLoader.Experimental.csproj b/src/System.Private.TypeLoader/src/System.Private.TypeLoader.Experimental.csproj
index 530409f48..1625467d0 100644
--- a/src/System.Private.TypeLoader/src/System.Private.TypeLoader.Experimental.csproj
+++ b/src/System.Private.TypeLoader/src/System.Private.TypeLoader.Experimental.csproj
@@ -2,7 +2,7 @@
<PropertyGroup>
<AssemblyName>System.Private.TypeLoader.Experimental</AssemblyName>
<EcmaMetadataSupport>true</EcmaMetadataSupport>
- <JitSupport>true</JitSupport>
+ <DynamicCodeSupport>true</DynamicCodeSupport>
</PropertyGroup>
<Import Project="System.Private.TypeLoader.csproj" />
diff --git a/src/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj b/src/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj
index 1ba5ae861..0a9048622 100644
--- a/src/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj
+++ b/src/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj
@@ -33,8 +33,8 @@
<PropertyGroup Condition="'$(IsProjectNLibrary)' != 'true'">
<DefineConstants>EETYPE_TYPE_MANAGER;$(DefineConstants)</DefineConstants>
</PropertyGroup>
- <PropertyGroup Condition="'$(JitSupport)' == 'true'">
- <DefineConstants>SUPPORT_JIT;$(DefineConstants)</DefineConstants>
+ <PropertyGroup Condition="'$(DynamicCodeSupport)' == 'true'">
+ <DefineConstants>SUPPORT_DYNAMIC_CODE;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(IsProjectNLibrary)' == 'true'">
<DefineConstants>FEATURE_INTERPRETER;$(DefineConstants)</DefineConstants>
@@ -56,7 +56,8 @@
<PropertyGroup>
<NativeFormatCommonPath>..\..\Common\src\Internal\NativeFormat</NativeFormatCommonPath>
</PropertyGroup>
- <ItemGroup Condition="'$(JitSupport)' == 'true'">
+ <ItemGroup Condition="'$(DynamicCodeSupport)' == 'true'">
+ <Compile Include="..\..\Common\src\TypeSystem\CodeGen\TypeDesc.CodeGen.cs" />
<Compile Include="..\..\Common\src\TypeSystem\RuntimeDetermined\ArrayType.RuntimeDetermined.cs" />
<Compile Include="..\..\Common\src\TypeSystem\RuntimeDetermined\ByRefType.RuntimeDetermined.cs" />
<Compile Include="..\..\Common\src\TypeSystem\RuntimeDetermined\DefType.RuntimeDetermined.cs" />
@@ -74,6 +75,7 @@
<Compile Include="..\..\Common\src\TypeSystem\RuntimeDetermined\TypeSystemContext.RuntimeDetermined.cs" />
<Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\ILEmitter.cs" />
<Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DelegateThunks.cs" />
+ <Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\DynamicInvokeMethodThunk.cs" />
<Compile Include="..\..\Common\src\TypeSystem\IL\Stubs\EnumThunks.cs" />
<Compile Include="..\..\Common\src\TypeSystem\IL\HelperExtensions.cs" />
<Compile Include="..\..\Common\src\TypeSystem\IL\ILDisassembler.cs" />
@@ -86,10 +88,12 @@
<Compile Include="..\..\Common\src\TypeSystem\IL\MethodILDebugView.cs" />
<Compile Include="..\..\Common\src\TypeSystem\IL\DelegateInfo.cs" />
<Compile Include="..\..\Common\src\TypeSystem\IL\TypeSystemContext.DelegateInfo.cs" />
+ <Compile Include="..\..\Common\src\TypeSystem\IL\TypeSystemContext.DynamicInvoke.cs" />
<Compile Include="..\..\Common\src\TypeSystem\IL\TypeSystemContext.EnumMethods.cs" />
+ <Compile Include="..\..\Common\src\TypeSystem\IL\TypeSystemContext.GeneratedAssembly.cs" />
<Compile Include="Internal\TypeSystem\ILStubMethod.Runtime.cs" />
<Compile Include="Internal\TypeSystem\MethodForRuntimeDeterminedType.Runtime.cs" />
- <Compile Include="Internal\Runtime\TypeLoader\JitSupport.MethodEntrypointStubs.cs" />
+ <Compile Include="Internal\Runtime\TypeLoader\MethodEntrypointStubs.cs" />
</ItemGroup>
<ItemGroup Condition="'$(EcmaMetadataSupport)' == 'true'" >
<Compile Include="System\Reflection\Runtime\General\QHandles.Ecma.cs" />
diff --git a/src/Test.CoreLib/src/Test.CoreLib.csproj b/src/Test.CoreLib/src/Test.CoreLib.csproj
index 685a4fd63..2ae214276 100644
--- a/src/Test.CoreLib/src/Test.CoreLib.csproj
+++ b/src/Test.CoreLib/src/Test.CoreLib.csproj
@@ -75,6 +75,9 @@
<Compile Include="..\..\Runtime.Base\src\System\Runtime\InteropServices\UnsafeGCHandle.cs">
<Link>Runtime.Base\src\System\Runtime\InteropServices\UnsafeGCHandle.cs</Link>
</Compile>
+ <Compile Include="..\..\Runtime.Base\src\System\Runtime\InteropServices\UnmanagedType.cs">
+ <Link>Runtime.Base\src\System\Runtime\InteropServices\UnmanagedType.cs</Link>
+ </Compile>
<Compile Include="..\..\Runtime.Base\src\RhBaseName.cs">
<Link>Runtime.Base\src\RhBaseName.cs</Link>
</Compile>
diff --git a/src/dirs.proj b/src/dirs.proj
index bc9ce5cad..a0ab1b264 100644
--- a/src/dirs.proj
+++ b/src/dirs.proj
@@ -2,9 +2,10 @@
<Import Project="dir.props" />
<ItemGroup>
- <!-- This project requires ILASM and we have access to that only on Windows -->
+ <!-- These projects requires ILASM and we have access to that only on Windows -->
<ExcludeProjects Condition="'$(OSEnvironment)'!='Windows_NT'" Include="**\TypeSystem.Tests.csproj" />
<ExcludeProjects Condition="'$(OSEnvironment)'!='Windows_NT'" Include="**\ILCompiler.MetadataTransform.Tests.csproj" />
+ <ExcludeProjects Condition="'$(OSEnvironment)'!='Windows_NT'" Include="**\ILVerification.Tests.csproj" />
<Project Include="AotPackageReference\AotPackageReference.depproj" />